网络上有很多相关blog对Redis进行非常全面的介绍,本文档只记录一些个人的思考总结。
关键知识点
SDS存储方式
两点:预分配空间+惰性释放,避免了缩短字符串时所需的内存重分配操作,并为将来可能有的增长操作提供了优化,即空间换时间,提高读写性能。
hash实现
渐进式哈希,使用两个bukect,h[0]和h[1],将hash操作均摊到每个操作上,均摊后延迟不明显,同样也有空间换时间的思想。
跳表
跳表的思想比较简单,但是redis的实现很巧妙,直接用概率来决定索引层级。
备份方式
RDB存数据,AOF存指令;RDB慢,AOF快;RDB存量快照,AOF增量;数据恢复=RDB+AOF,但是还是可能会有漏网之鱼。
主从模式
- slave具有优先级,并且是由配置文件定义的。
- 如果「从节点」与「主节点」断连,「从节点」需要根据一个唯一标示去寻找「主节点」,这个标示就是RunID。
哨兵模式
- 主观下线:一个哨兵认为下线;客观下线:
N/2+1个哨兵认为下线。 - 脑裂:这边有一个例子很棒 Redis 脑裂:一次奇怪的数据丢失|极客时间摘录
- 哨兵leader会一直存在吗?具体得看代码,但是哨兵leader存在没有意义,因为到了下一次故障时,会重新选举leader。
集群模式
- 故障的检测和恢复是由master的slave节点和其余主节点共同完成的
- 集群模式的hash slot机制,数据存储和转移
过期策略
定期删除(轮询库抽样定时处理)+惰性删除(操作到的数据过期删除)
内存淘汰
volatile-lru、allkeys-lru、volatile-random、allkeys-lru、volatile-ttl、noeviction
思考
Q:主从复制中,为什么不是RDB全量复制,AOF增量复制,而是维护了一个新的环结构数据?
- RDB和AOF是备份手段,第一次同步的时候,全量复制使用RDB没有问题,因为这是一个初始化操作,并且这时候「从节点」其实是未就绪的,不需要“迎客”
- 当第一次同步完后,「从节点」需要相应读操作了;首先这时对节点的性能要求很高;其次AOF是需要写数据到文件中较慢,没有直接使用在内存中的repl_back_buffer快,因此增量复制不用AOF同步。
Q:集群模式中,故障恢复怎么又是slave节点又是其余主节点的,不能直接由其余主节点或者全都由故障主节点的slave节点完成吗?
先描述一下整体流程:
- 集群其余「主节点」判断某个「主节点」故障,标记下线
- 故障「主节点」的「从节点」发现「主节点」下线,进入主从替换流程,向集群广播消息,进行拉票
- 其余「主节点」进行投票,获得票数过半的故障「主节点」的「从节点」晋升,若没过半则反复进行拉票-投票
- 选出新「主节点」,接手原「主节点」资产
其实如果只由「主节点」的「从节点」们独立进行选举也能做到,就类似哨兵模式那样,但是问题就在于,“集群模式是master节点们的集群模式”,如果光由「从节点」们过家家,是无法保证新「主节点」在集群中的通信顺畅的,因此应该“从集群模式角度进行主从切换”,而不是“从主从模式的角度进行主从切换”。