文章目录
1.4.1 Redis的缓存过期淘汰策略
1.4.1.1 Redis内存满了怎么办
真要打满了会怎么样?如果Redis内存使用超出了设置的最大值会怎样?
改改配置,故意把最大值设为1个byte试试,发现OOM了
1.4.1.2 过期策略
往redis里写的数据是怎么没了的?它如何删除的?
立即删除,需时刻遍历过期key,cpu消耗大,对空间友好
惰性删除,下次访问过期key删除,对空间不友好,可能key不在访问就不会删除
定期删除(折中方案)
定期删除的漏网之鱼
1 定期删除时,从来没有被抽查到
2 惰性删除时,也从来没有被点中使用过
上述2步骤======> 大量过期的key堆积在内存中,导致redis内存空间紧张或者很快耗尽
必须要有一个更好的兜底方案…内存淘汰策略
1.4.1.3 缓存淘汰策略
平时用哪一种?如何配置、修改?命令和配置文件reids.conf参数配置
1.4.1.3.1 Redis 中LRU设计
抽样删除热度最低的key。
如果基于传统LRU算法实现Redis LRU会有什么问题?
问题1:需要额外的数据结构存储,消耗内存
问题2:如图,假设A在10秒内被访问了5次,而B在10秒内被访问了3次。因为B最后一次被访问的时间比A要晚,在同等的情况下,A反而先被回收。
原理问题:redis如何找出热度最低(最少使用)的数据?
Redis中所有对象结构有一个lru字段记录对象热度,对象创建是会记录lru值,被访问时更新lru(设置值不是当前时间戳,而是Server.lrulock的值,也就是unix时间)。
Server.lrulock:Redis中有个定时处理的函数serverCron,默认每100毫秒调用函数updateCachedTime 更新一次全局变量的 server.lruclock 的值,它记录的是当前unix时间。
为什么不获取精确的时间而是放在全局变量中?不会有延迟的问题吗?
这样函数查询key调用lookupKey中更新数据的lru热度值时,就不用每次调用系统函数time,可以提高执行效率。
热度如何评估?当对象里有LRU字段值,就可以评估对象热度了
评估方式:对象lru值和全局server.lruclock的差值,差值越大(越久没更新),表示该对象热度越低
1.4.1.3.2 Redis 中LFU设计
字段lru作为LFU使用有24bit位
高16为记录访问时间(单位分),
低8为记录访问次数(counter),基于概率对数实现,8位可表示百万次访问评率
对象被读写时更新lfu的值(基于算法增加)
当长时间不访问该值,lfu应该减少:减少值由衰减因子控制,如果为1,N分没访问计数器减少N
1.4.2 持久化机制
官网:https://redis.io/topics/persistence
RDB和AOF如何选择(比较)?
建议两种都用,redis启动优先加载AOF文件恢复数据,因为AOF保存的数据更完整
如果可以忍受一小段时间内数据的丢失,选RDB。否则就使用AOF重写。
但是不建议单独使用某一种持久化机制,而是应该两种一起用,在这种情况下,当redis重启的时候会优先载入AOF文件来恢复原始的数据,因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整。
1.4.2.1 持久化流程
(1)客户端向服务端发送写操作(数据在客户端的内存中)。
(2)数据库服务端接收到写请求的数据(数据在服务端的内存中)。
(3)服务端调用write这个系统调用,将数据往磁盘上写(数据在系统内存的缓冲区中)。
(4)操作系统将缓冲区中的数据转移到磁盘控制器上(数据在磁盘缓存中)。
(5)磁盘控制器将数据写到磁盘的物理介质中(数据真正落到磁盘上)。
1.4.2.2 RDB
redis.conf配置触发规则:不需要RDB注释sava
lastsave命令查看最近生成的快照:
bgsave原理:
1.4.2.3 AOF
redis.conf配置appenddonly开启:
数据都是实时持久滑到磁盘吗?
1.4.2.3.1 AOF运行原理
每当有一个写命令过来时,就直接保存在我们的AOF文件中
1.4.2.3.2 AOF文件重写原理
文件越来越大,怎么办?bgrewriteaof命令重写,生成新的aof文件
重写过程中新的写命令记录到AOF重写缓存中,写完成后追加到aof文件
1.4.3 Redis为什么这么快?Redis IO多路复用深度解析
Redis单线程如何处理那么多并发客户端连接,为什么单线程,为什么快?
I/O多路复用解决了redis单线程读写操作等待用户输入或输出都是阻塞的问题