Redis进阶
多路IO复用
实现流程
- 连接时,将对应的socket fd注册到监听列表中
- 客户端进行读写操作时,redis将命令封装成事件,并绑定在fd上
- 通过文件事件处理器监听多个fd,当fd有事件产生时,处理器进行回调处理
实现原理
利用linux中的select/poll/epoll函数
linux默认使用epoll函数,其他系统降级为select
函数区别
select
轮询,上限1024
poll
轮询,无上限
epoll
基于红黑树、双向链表,使用事件回调
为什么使用多路复用
为了让单线程服务端同时处理多个客户端事件
Redis过期删除机制
如何判断过期数据?
Redis内部维护一个过期字典(hash表)
删除策略
定期删除
定时获取key进行删除
惰性删除
只有获取key的时候才会进行过期检查,可能造成大量过期key未删除
默认策略
定期删除+惰性删除
内存淘汰机制
Redis拥有8中淘汰机制,总体上可分为三大类
拒绝机制
- no-eviction(默认)
内存不足时,拒绝写入操作
在设置了过期时间的数据中淘汰
- volatile-lru
淘汰最近使用最少的数据 - volatile-ttl
淘汰即将过期的数据 - volatile-random
淘汰随机数据 - volatile-lfu(4.0新增)
淘汰不常用的数据
在所有数据中淘汰
- allkeys-lru(常用)
淘汰最近最少使用的数据 - allkeys-random
淘汰随机数据 - allkeys-lfu(4.0新增)
淘汰不常用的数据
缓存一致性
概念
mysql和redis中的数据不一致
解决方案
旁路缓存模式
先更新DB,再删除redis
删除redis失败怎么办?
进行删除重试,将删除失败的key加入队列中,通过其他线程进行循环删除,直到删除成功
延迟双删
概念
通过二次删除,在一段时间内保证数据一致性
工作流程
- 删除redis
- 更新db
- 子线程等待N秒,再次进行删除redis
binlog订阅
基于canal框架,订阅mysql的binlog,异步操作redis
渐进式hash
概念
redis底层使用一个字典维护key/value值,字典由hash表实现
负载因子计算
hash表节点数 / hash表大小
什么时候使用渐进式hash?
当出现rehash操作时,会使用渐进式hash
rehash
rehash触发条件
- 满足扩容条件
- 没有执行bgsave,且负载因子大于等于1
- 正在执行bgsave,且负载因子大于等于5
- 满足缩减条件
- 负载率低于10%
rehash会导致什么问题问题?
rehash时,需要将ht[0]的数据转移到ht[1]中,为了避免性能损耗过大,采用分段式转移
rehash工作流程
- 分配ht[1]空间,字典同时持有ht[0] ht[1]两个hash表
- 维护索引值rehashidx,默认值为0
- 每次工作完成后,将rehashidx的值加一,并将ht[0]在rehashidx上的kv转移到ht[1]中
- 当转移完成后,将rehashidx值置为-1,表示rehash工作完成