Redis拓展知识
一、消息
1.sub/pub
- 实现了一个建议的消息队列,实现了发布者与订阅者的模式,生产者和消费者是不同的连接;
- 如果一个消费者没有消息会直接舍弃,消息没有ack机制,且消息不持久化。
2.Stream
- redis5.0提出了支持多播的可持久化的消息队列Stream,参照了kafka分组的设计(stream没有分区的概念,分区需要在客户端完成);
- 每个Stream可以挂多个消费者组,其中有一个游标标识消费到了哪条消息,一个消费者组中的消费者是竞争的关系,消费者内部由一个pending_id(PEL,Pending Entries List)记录没有ack的消息;
- 操作指令:xadd、xdel、xrange、xlen、del;
- 消费分为两个类型,可以单个消费者xread消费,也可以消费者组xreadgroup消费,可以阻塞,可以不阻塞消费;
- stream消息链表xdel不会删除消息只是做一个标识,消息链表的定长长度maxlen会限制消息的长度;
二、过期策略
- 删除策略:设置过期的key单独放在一个独立的字典,会采用定期扫描的集中处理和懒惰删除的零散处理,主从结构从节点删除依赖于主节点的aof日志。
- 删除原理:默认每秒进行10次过期扫描,采用贪心策略,先随机20个key进行过期删除,如果过期的超过1/4再继续选取,默认的扫描时间不会超过25ms。为了避免一个时间同一时间过期时间key过多导致客户端超时断开连接失败,设置超时时间尽量不要在同一时间过期;
- 懒惰删除:del删除大key、unlink指令、flushdb async、flushall async都可以进行异步的删除,原理事放在一个异步的任务队列(双向链表)中慢慢的删除。
三、内存更新LRU
- 删除策略:当实际内存超过maxmemory时,有以下几种可算的策略。
- noeviction:(默认)不会继续服务写请求(不包括del),读请求可以继续;
- volatile-lru:尝试淘汰设置了过去时间的key,最少使用的key优先被淘汰;
- volatile-ttl:尝试淘汰设置了过去时间的key,剩余ttl寿命越小优先淘汰;
- volatile-random:尝试淘汰设置了过去时间的key,剩余ttl寿命越小优先淘汰;
- volatile-random:尝试淘汰设置了过去时间的key,随机淘汰;
- allkeys-lru:全体key最少使用的key优先被淘汰;
- allkeys-random:全体key随机淘汰;
2.LRU算法:
- 传统LRU算法,链表结构,按照一定的顺序排列,被访问了就放在链表的头部,淘汰时淘汰链表的尾端;
- redis的LRU算法,传统LRU算法需要消耗额外的内存,在现有基础上采用随机采样法,给每个key加一个字段,长度24bit,表示最后使用的时间戳;
- 采用懒惰算法:执行写的操作时候发现超内存,随机采样出5个(maxmemory_samples可设置)淘汰,如果淘汰后内存还不足,继续淘汰;
3.LFU算法:
Redis4.0后按最近的访问频率进行淘汰,防止一个key偶尔被访问一次被当作热key;
-
数据结构:
last decrement time 16bit logistic counter 8 bit ① logc存储访问频率,频次的对数,该值会随着时间衰减,初始化key默认是5,每访问一次就更新,采用概率法递增;
② ldt存储上次logc更新的时间,2的16次方取模,精度是分钟,在淘汰时才更新,更新时会衰减logc([当前值-对象空现时间]/衰减系数[默认1])的值;