1 网络模型
单线程reactor
2 为什么不采用多线程
2.1 redis的性能瓶颈在于网络传递与内存。没必要过渡优化。
2.2 数据结构多样化,加锁复杂,锁力度不好控制。
2.3 多线程上文切换以及加锁带来无效的性能占用。
3 单线程为什么高效
3.1 使用了epoll多路复用,提供高并发的理论支撑。
3.2 优化掉了所有的耗时操作,IO密集与CPU密集,是保证单线程高效的重要依据。
子进程进行持久化操作,多线程进行落盘。
多种数据结构减小锁粒度。
渐进式rehash减小cpu密集操作。
读取数据后,编解码消息使用多io线程。
4 redis事务 ACID
redis事务为什么不常被使用--乐观锁,失败需要业务层重试,增加编码难度。
lua脚本满足事务的那几个特性 --原子、隔离
5 redis不同类型的编码方式
int embstr raw, quicklist ziplist , dict ziplist, intset dict, ziplist skiplist
6 redis hash冲突
链表,扩容-有子进程的前提下才进行,渐进式rehash,前提没有子进程的前提下才进行。
7 redis淘汰策略 在配置文件配置
过期key: lru(最长时间没有使用) lfu (最少使用的) ttl(即将过期) 随机
所有key: lru lfu 随机
禁止淘汰key:
8 redis持久化
fork进程写时复制流程 1 先复制进程,包括内存页表,并设置为只读,父子进程同时指向一块只读的物理内存 2 主进程写数据时,发生缺页中断,触发缺页处理函数,复制一块相同的物理内存,子进程指向此内存,父进程设置为可读可写。
可靠性与效率之间权衡。
1 aof 追加,命令协议,执行执行个命令恢复数据 aof三种配置: 1 always 每个命令落盘,阻塞当前线程,代价最高,丢失数据最少。 2 every_sec 异步定时落盘。 3 no 由系统管理落盘,可能丢失数据最高。
2 aof + 重写, 1 fork进程处理内存中的数据生成aof文件,避免aof文件历史冗余。2 使用一个临时缓冲区保存重写时生成的文件,aof持久化之后通过信号通知,并将临时数据追加到aof文件。
3 rdb 二进制快照,fork进程那一刻的内存所有数据状态,直接进行二进制数据落盘。落盘速度快。通常5分钟一次,丢失数据会更多。
4 aof + rdb 混用, rdb持久化期间,新生的数据追加的aof临时缓冲区。
aof 文件过大,数据恢复慢。 rdb 文件小,数据恢复快,丢失数据多。
大key对持久化的影响:fsync压力大, fork操作慢。
9 redis主从复制 解决单点故障问题
复制方式:同步、异步
9.1 备主动拉取数据。
9.2 runid 验证是不是主的从数据库
9.3 环形缓冲区 待同步数据,全量同步、增量同步。
9.4 复制偏移量 在环形缓冲区验证,同步数据位置
10 redis高可用
数据同步+主从切换
哨兵方式 哨兵节点,不存数据奇数个节点,存放监控状态与选主。根据什么选举,数据最新即复制偏移量最大。
集群方式 多个主节点数据如何均衡,分布式一致性hash,hash(key) % 2^14 16384
扩缩容,数据迁移,映射关系搞好。