开源的内存数据结构存储,读写速度快,用于缓存,消息队列,分布式锁等场景
与Memcached的相同点:
结构类型 | 结构存储的值 | 结构的读写能力 |
---|---|---|
string | 字符串,整数或浮点数 | 字符串操作,整数的自增自减 |
List | 链表,链表上每个都是字符串 | 两端的push和pop操作 |
set集合 | 包含字符串的无序集合 | 字符串集合,检查字符串是否在集合中,添加,删除,获取 |
hash | 键值对的无序集合 | 添加,删除湖片区元素 |
Zset | 键值对的有序集合 | 字符串与浮点数的有序集合,排列由分数的大小确定 |
SDS(简单动态字符串)
底层由双向链表或压缩链表(小于512且元素小于64字节)实现
压缩列表(<512且所有值小于64字节)或者哈希表实现
小于512整数集合,>=512哈希表
压缩列表或跳表实现
Redis单线程指的是[接受客户端请求->解析请求->进行数据读写->发送数据给客户端]是由一个线程完成的
整个Redis程序并不是单线程的,Redis程序会启动后台线程.三种线程[关闭文件,AOF刷盘,释放内存]
redis的reactor模型
Redis6.0版本之后,可以启动额外的网络IO线程,默认情况下会启动7个线程
Redis持久化有三种策略:
Redis执行完一条写操作之后,把该命令以追加的方式写到文件中,Redis重启后,会读取该文件记录的命令,然后逐一执行的方式恢复数据
Redis采用先写入内存再写入AOF日志的策略原因如下
当然这样做也会带来如下的风险
Redis写入AOF日志的流程如下图
Redis提供了三种写回磁盘的策略,控制的是IO系统调用的过程,三种策略分别为Always,Everysec,No,介绍如下
从上到下,安全性递减,性能递增
AOF日志是一个文件,随着写命令增加,文件大小会增加,Redis为了避免AOF文件越来越大,提供了AOF重写机制
Redis的AOF重写是由后台的子进程完成的,那如何控制主进程和后台子进程的AOF一致性呢,Redis设置了一个AOF重写缓冲区,在创建子进程时使用这个缓冲区,流程如下图
也即是,在子进程重写时,开启AOF重写缓冲区,写入命令将会同时写入到AOF缓冲区和AOF重写缓冲区,当子进程完成重写之后,向主进程发送一条信号,主进程将AOF重写缓冲区的内容追加到新的AOF文件中,之后将这个新的AOF覆盖掉原有的AOF文件,完成AOF重写
因为AOF日志存储的是操作的命令,并不是实际的数据,因此用AOF做故障恢复时,需将日志全部执行一遍,AOF日志过多的情况下,Redis的恢复将十分缓慢
为了解决这一个问题,提出了RDB快照,RDB快照记录的时某一个瞬间内存中的内容,RDB记录同样会创建子进程,并且由于写时复制,这个时候原本的父进程依然可以执行写操作
RDB优势在于数据的恢复块,但是可能丢失数据
AOF数据丢失少,但是恢复慢
Redis 4.0之后混合了AOF日志和内存快照,也就是说AOF文件前半部分时RDB格式的全量数据,后半部分是AOF的增量数据
混合持久化优点:
混合持久化缺点:
Redis集群设计原因:需要高可用的Redis服务
主从复制是Redis高可用的基础保证,实际上就是将一台Redis服务器的数据同步到多台从Redis服务器上,即一主多从的模式,且主从服务器之间采用的是读写分离的方式
Redis的异步主从复制是无法实现强一致性保证的
使用Redis主从服务的时候,若主从服务器出现故障宕机时,需要手动进行恢复,为了解决这个问题,Redis增加了哨兵模式,哨兵模式可以监控主从服务器,并且提供主从节点之间的故障转移功能
当Redis缓存的数据量大到一台服务器无法缓存时,就需要使用Redis切片集群,将数据分布到不同的服务器上,降低对单主节点的依赖,提高redis服务的读写性能
Redis Cluster方案采用哈希槽来处理数据和节点之间的映射关系,共16384个哈希槽
情景:在一个网络波动的情况下,Redis有一个主节点A,和从节点BCD,以及哨兵E,当A与BCDE之间网络故障,但与客户端之间网络联通,这个时候客户端往A写数据,A无法同步到BCD,E发现异常并选举B作为新的主节点,在这之后网络恢复正常,并且B是新的主节点,将数据全量同步给ACD,这个时候A将清空自己的数据,并且接受B的数据,此时客户端的更新失效,产生数据丢失
解决方案:当主节点发现从节点下线或者通信超时的总量小于阈值时,禁止主节点写数据,直接把错误返回给客户端
Redis中有两个参数可以设置
Redis可以对key设置过期时间,相应的机制被称为过期键值删除策略,每当对一个key设置了超时时间,Redis将会把该Key带上过期时间存储到一个过期字典中,可就是说过期字典保存了所有key的过期时间
查询一个key时,先查询是否在过期字典中
Redis使用的过期删除策略为惰性删除和定期删除
不主动删除Key,每次从数据库访问key时,都检测key是否过期,如果过期删除该key
优点:策略对CPU时间友好
缺点:浪费内存空间
每隔一段时间从数据库取出一定数量的key进行检查,删除其中过期的key
优点:限制删除操作时长和频率,减少删除操作对CPU的影响,同时尽量节约空间
缺点:难以确定删除时长和频率,执行太过频繁对CPU不友好
Redis持久化时,文件有两种表现形RDB和AOF,过期键在这两种格式下的呈现状态如下
RDB分为两个阶段:
AOF分为两个阶段,写入阶段和加载阶段:
Redis运行在主从模式下时,从库不会进行过期扫描,从库对过期的处理是被动的,也就是依赖主库的控制,主库的Key在到期时,会在AOF文件里增加一条DEL指令,同步到所有的从库
Redis的运行内存达到了某个阈值,就会触发内存淘汰机制,阈值是设置的最大运行内存,淘汰策略有八种,主要是依照LRU和LFU策略设计的
Redis数据过期之后,用户访问的数据如果不在缓存里,业务系统需要重新生成缓存,这时候需要访问数据库,并将数据库更新到Redis后,以后的请求可以直接命中缓存
缓存雪崩问题是指:大量的缓存在同一时间过期时,若有大量的用户请求,都无法在Redis中处理,所有的请求全部访问数据库,导致数据库的压力骤增,严重的导致数据库宕机,从而导致一系列的连锁反应,造成整个系统崩溃,这就是缓存雪崩问题
缓存雪崩问题的解决方案:1.将缓存失效的时间随机打散2.设置缓存不过期
缓存击穿问题是指,业务有几个数据会被频繁的访问,如果缓存中的某个热点数据过期了,此时大量的请求访问了该热点数据,转而直接访问数据库,数据库很容易高并发的请求冲垮,这就是缓存击穿问题
缓存击穿避免方式:
发生缓存雪崩或者击穿时,数据库中依然保存了应用要访问的数据,一旦缓存恢复相对应的数据,就可以减轻数据库的压力,当用户访问的数据,既不在缓存中,也不在数据库中,导致请求访问缓存时,发现缓存缺失,转而访问数据库,而数据库中也没有要访问的数据,没办法构建缓存数据,当有大量的请求到来时,数据库压力剧增,这就是缓存穿透问题
缓存穿透发生有两种情况
缓存穿透的应对措施三种
将一部分热点数据缓存起来,策略的思路是,通过数据的最新访问时间来做排名,过滤掉不常访问的数据,留下经常访问的数据
三种常见的缓存更新策略
读策略的步骤:
延迟队列类似于定时器,那么Redis用ZSet加上轮询队列,处理回调即可完成延迟队列的实现
大key是指Redis的key对应的value很大(元素多或者单个元素占用的空间很大)