Redis是由意大利人Salvatore Sanfilippo(网名:antirez)开发的一款内存高速缓存数据库。Redis全称为:Remote Dictionary Server(远程数据服务),该软件使用C语言编写,Redis是一个key-value存储系统,它支持丰富的数据类型,如:string、list、set、zset(sorted set)、hash。html
Redis支持多种数据类型,有String、List、Hash、Set、zset面试
String类型是二进制安全的,意思是Redis的String能够包含任何数据,好比图片或者序列化的对象等。一个Redis中字符串的value最多能够是512M。通常作一些复杂的计数功能的缓存。redis
List是按照插入顺序排序的字符串链表。数据库
从元素插入和删除的效率视角来看,若是咱们是在链表的两头插入或删除元素,这将会是很是高效的操做,即便链表中已经存储了百万条记录,该操做也能够在常量时间内完成。然而须要说明的是,若是元素插入或删除操做是做用于链表中间,那将会是很是低效的 。后端
Redis链表常常会被用于消息队列的服务,以完成多程序之间的消息交换。假设一个应用程序正在执行LPUSH操做向链表中添加新的元素,咱们一般将这样的程序称之为"生产者(Producer)",而另一个应用程序正在执行RPOP操做从链表中取出元素,咱们称这样的程序为"消费者(Consumer)"。若是此时,消费者程序在取出消息元素后马上崩溃,因为该消息已经被取出且没有被正常处理,那么咱们就能够认为该消息已经丢失,由此可能会致使业务数据丢失,或业务状态的不一致等现象的发生。然而经过使用RPOPLPUSH命令,消费者程序在从主消息队列中取出消息以后再将其插入到备份队列中,直到消费者程序完成正常的处理逻辑后再将该消息从备份队列中删除。同时咱们还能够提供一个守护进程,当发现备份队列中的消息过时时,能够从新将其再放回到主消息队列中,以便其它的消费者程序继续处理。缓存
能够利用 lrange 命令,作基于 Redis 的分页功能,性能极佳,用户体验好安全
Hash是一个健值对集合,是一个String类型的key与value的映射表,特别适合用于存储对象。 可用于存储、读取、修改用户属性, Hash 结构可使你像在数据库中 Update 一个属性同样只修改某一项属性值。服务器
Set 是一个集合,集合的概念就是一堆不重复值的组合。利用 Redis 提供的 Set 数据结构,能够存储一些集合性的数据。 集合是经过哈希表实现的,因此添加,删除,查找的复杂度都是O(1) 。Redis 很是人性化的为集合提供了求交集、并集、差集等操做,那么就能够很是方便的实现如共同关注、共同喜爱、二度好友等功能 。也能够作全局去重的功能。数据结构
和Sets相比,Sorted Sets是将 Set 中的元素增长了一个权重参数 score,使得集合中的元素可以按 score 进行有序排列。能够作排行榜应用,取 TOP N 操做。Sorted Set 能够用来作延时任务。最后一个应用就是能够作范围查找。多线程
性能和并发。
性能:将一些耗时比较久,且结果不常常变更的SQL,放到Redis中,这样,请求直接从缓存中读取,使得可以迅速响应。
并发:大并发的状况下,全部的请求直接访问数据库,数据库会出现链接异常。这个时候,就须要使用Redis作一个缓冲操做,让请求先访问到redis,而不是直接访问数据库 。
什么是非阻塞I/O呢?
阻塞与非阻塞能够简单理解为调用一个IO操做能不能当即获得返回应答,若是不能当即得到返回,须要等待,那就阻塞了;不然就能够理解为非阻塞。
什么是I/O多路复用机制呢?
单个线程,经过记录跟踪每一个I/O流(sock)的状态,来同时管理多个I/O流 。
I/O多路复用的优点并非对于单个链接能处理的更快,而是在于能够在单个线程/进程中处理更多的链接。与多进程和多线程技术相比,I/O多路复用技术的最大优点是系统开销小,系统没必要建立进程/线程,也没必要维护这些进程/线程,从而大大减少了系统的开销。
Redis采用的过时策略是:按期删除+惰性删除策略。
按期删除,Redis 默认每隔100ms 检查,是否有过时的 Key,有过时 Key 则删除。
须要说明的是,Redis 不是每隔100ms 将全部的 Key 检查一次,而是随机抽取进行检查(若是每隔 100ms,所有 Key 进行检查,Redis 岂不是卡死)。
按期删除能够经过: 第1、配置redis.conf 的hz选项,默认为10 (即1秒执行10次,100ms一次,值越大说明刷新频率越快,最Redis性能损耗也越大,建议不要超过100) 第2、配置redis.conf的maxmemory最大值,当已用内存超过maxmemory限定时,就会触发主动清理策略
所以,若是只采用按期删除策略,会致使不少 Key 到时间没有删除。因而,惰性删除派上用场。
也就是说在你获取某个 Key 的时候,Redis 会检查一下,这个 Key 若是设置了过时时间,若是过时了,此时就会删除。
过时策略能够参考:[Redis数据过时策略详解](https://www.cnblogs.com/xuliangxing/p/7151812.html)
可是当某些key没有被按期删除到,也没有获取某些key,内存岂不是也会占用很高,这时候就须要内存淘汰机制了
在 redis.conf 中有一行配置
# maxmemory-policy volatile-lru
Redis内存淘汰策略有(触发该策略的机制是 当内存不足以容纳新写入数据时):
首先,采起正确更新策略,先更新数据库,再删缓存。其次,由于可能存在删除缓存失败的问题,提供一个补偿措施便可,例如利用消息队列。
缓存穿透:黑客故意去请求缓存中不存在的数据,致使全部的请求都怼到数据库上,从而数据库链接异常。
解决方法:
缓存雪崩:当缓存服务器重启或者大量缓存集中在某一个时间段失效,来了一批请求,请求所有到DB,DB瞬时压力太重雪崩。
解决方法:
缓存击穿:对于一些设置了过时时间的key,若是这些key可能会在某些时间点被超高并发地访问,是一种很是“热点”的数据。这个时候,须要考虑一个问题:缓存被“击穿”的问题,这个和缓存雪崩的区别在于这里针对某一key缓存,前者则是不少key。 缓存在某个时间点过时的时候,刚好在这个时间点对这个Key有大量的并发请求过来,这些请求发现缓存过时通常都会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端DB压垮。
解决方法:
参考:
使用keys指令能够扫出指定模式的key列表。若是这个redis正在给线上的业务提供服务,keys指令会致使线程阻塞一段时间,线上服务会停顿,直到指令执行完毕,服务才能恢复。这个时候可使用scan指令,scan指令能够无阻塞的提取出指定模式的key列表,可是会有必定的重复几率,在客户端作一次去重就能够了,可是总体所花费的时间会比直接用keys指令长。
通常使用list结构做为队列,rpush生产消息,lpop消费消息。当lpop没有消息的时候,要适当sleep一会再重试。 若是不用sleep,list还有个指令叫blpop,在没有消息的时候,它会阻塞住直到消息到来。
使用pub/sub主题订阅者模式,能够实现1:N的消息队列。 也就是生产一次消费屡次。可是使用pub/sub是有缺点的,在消费者下线的状况下,生产的消息会丢失,得使用专业的消息队列如rabbitmq等。
redis如何实现延时队列:使用sortedset,拿时间戳做为score,消息内容做为key,调用zadd来生产消息,消费者用zrangebyscore指令获取N秒以前的数据轮询进行处理。
主要是使用了redis 的setnx命令,缓存了锁,reids缓存的key是锁的key,全部的共享, value是锁的到期时间(注意:这里把过时时间放在value了,没有时间上设置其超时时间)。
1.经过setnx尝试设置某个key的值,成功(当前没有这个锁)则返回,成功得到锁
2.锁已经存在则获取锁的到期时间,和当前时间比较,超时的话,则设置新的值
实现方法能够参考:Redis分布式锁实现