从图可知,Redis 启动时会先检查 AOF 是否存在,如果 AOF 存在则直接加载 AOF,如果不存在 AOF,则直接加载 RDB 文件。
Pineline
Pipeline 和 Linux 的管道类似,它可以让 Redis 批量执行指令。
Redis 基于请求/响应模型,单个请求处理需要一一应答。如果需要同时执行大量命令,则每条命令都需要等待上一条命令执行完毕后才能继续执行,这中间不仅仅多了 RTT,还多次使用了系统 IO。
Pipeline 由于可以批量执行指令,所以可以节省多次 IO 和请求响应往返的时间。但是如果指令之间存在依赖关系,则建议分批发送指令。
Redis 的同步机制
主从同步原理
Redis 一般是使用一个 Master 节点来进行写操作,而若干个 Slave 节点进行读操作,Master 和 Slave 分别代表了一个个不同的 Redis Server 实例。
另外定期的数据备份操作也是单独选择一个 Slave 去完成,这样可以最大程度发挥 Redis 的性能,为的是保证数据的弱一致性和最终一致性。
另外,Master 和 Slave 的数据不是一定要即时同步的,但是在一段时间后 Master 和 Slave 的数据是趋于同步的,这就是最终一致性。
全同步过程如下:
- Slave 发送 Sync 命令到 Master。
- Master 启动一个后台进程,将 Redis 中的数据快照保存到文件中。
- Master 将保存数据快照期间接收到的写命令缓存起来。
- Master 完成写文件操作后,将该文件发送给 Slave。
- 使用新的 AOF 文件替换掉旧的 AOF 文件。
- Master 将这期间收集的增量写命令发送给 Slave 端。
增量同步过程如下:
- Master 接收到用户的操作指令,判断是否需要传播到 Slave。
- 将操作记录追加到 AOF 文件。
- 将操作传播到其他 Slave:对齐主从库;往响应缓存写入指令。
- 将缓存中的数据发送给 Slave。
Redis Sentinel(哨兵)
主从模式弊端:当 Master 宕机后,Redis 集群将不能对外提供写入操作。Redis Sentinel 可解决这一问题。
解决主从同步 Master 宕机后的主从切换问题:
监控:检查主从服务器是否运行正常。
提醒:通过 API 向管理员或者其它应用程序发送故障通知。
自动故障迁移:主从切换(在 Master 宕机后,将其中一个 Slave 转为 Master,其他的 Slave 从该节点同步数据)。
Redis 集群
如何从海量数据里快速找到所需?
①分片
按照某种规则去划分数据,分散存储在多个节点上。通过将数据分到多个 Redis 服务器上,来减轻单个 Redis 服务器的压力。
②一致性 Hash 算法
既然要将数据进行分片,那么通常的做法就是获取节点的 Hash 值,然后根据节点数求模。
但这样的方法有明显的弊端,当 Redis 节点数需要动态增加或减少的时候,会造成大量的 Key 无法被命中。所以 Redis 中引入了一致性 Hash 算法。
该算法对 2^32 取模,将 Hash 值空间组成虚拟的圆环,整个圆环按顺时针方向组织,每个节点依次为 0、1、2…2^32-1。
之后将每个服务器进行 Hash 运算,确定服务器在这个 Hash 环上的地址,确定了服务器地址后,对数据使用同样的 Hash 算法,将数据定位到特定的 Redis 服务器上。
如果定位到的地方没有 Redis 服务器实例,则继续顺时针寻找,找到的第一台服务器即该数据最终的服务器位置。
③Hash 环的数据倾斜问题
Hash 环在服务器节点很少的时候,容易遇到服务器节点不均匀的问题,这会造成数据倾斜,数据倾斜指的是被缓存的对象大部分集中在 Redis 集群的其中一台或几台服务器上。
如上图,一致性 Hash 算法运算后的数据大部分被存放在 A 节点上,而 B 节点只存放了少量的数据,久而久之 A 节点将被撑爆。
针对这一问题,可以引入虚拟节点解决。简单地说,就是为每一个服务器节点计算多个 Hash,每个计算结果位置都放置一个此服务器节点,称为虚拟节点,可以在服务器 IP 或者主机名后放置一个编号实现。
例如上图:将 NodeA 和 NodeB 两个节点分为 Node A#1-A#3,NodeB#1-B#3。
结语
这篇准(tou)备(lan)了相当久的时间,因为有些东西总感觉自己拿不准不敢往上写,差点自闭,如果有同学觉得哪里写的不对劲的,评论区留言。