写点什么

Redis 主从复制、Sentinel、集群总结

用户头像
Hex
关注
发布于: 1 小时前

本文记录学习《Redis 设计与实现》一书中第三部分关于主从复制、Sentinel、集群的知识总结及理解。

一、主从复制

单节点部署,一旦节点发生故障,就会导致服务不可用,主-从集群就是为了解决这类问题,提高可用性,同时通过主从进行读写分离,可以减少主库的读压力。


主从复制包含全量复制、基于长链接的命令传播、增量复制。


当从节点执行 slaveof ip port 后,建立主从关系后,会进行第一次全量复制,如下:


1、第一次全量同步,master 节点开启 bgsave 子进程来创建全量 RDB,并发送给从节点,;


2、从节点接收到主节点的 RDB 文件,清除本地数据后加载 RDB 文件;


2、命令传播,全量同步的过程中产生的写命令会缓存在复制缓冲区(replication buffer),主节点将复制缓冲区内的写命令发给从节点执行。

主从节点网络断开-增量复制

在 2.8 版本之前,主从节点网络断开后会进行全量复制,效率低下。


从 2.8 开始,网络断开后重新连接,主从节点会进行增量复制。


当主从节点断开连接后,重新连接上后,会根据主从节点的偏移量从 repl_backlog_buffer 缓冲区获取写命令进行增量同步。



全量复制为什么用 RDB,不用 AOF?

1、RDB 文件内容是经过压缩的二进制数据,而 AOF 文件记录的是每一次写操作的命令,写操作越多文件会变得很大,其中还包括很多对同一个 key 的多次冗余操作,使用 RDB 文件传输相对 AOF 文件会减少网络消耗;


2、从库通过 RDB 快照加载数据要快,AOF 要逐条执行命令;

二、哨兵机制

哨兵节点是一个特殊的 Redis 实例,特殊在于普通 Redis 节点相比,命令集不同,哨兵节点不能执行数据操作命令,可以执行 PING,INFO 等命令。哨兵集群的作用是用来监控 Redis 集群,对发生故障的 master 节点能进行故障转移,保证高可用。


哨兵节点会与所有 Redis 主-从节点创建两个连接,一个是订阅_sentinel:hello 频道;一个是命令连接。

主观下线 vs 客观下线

哨兵会每隔一秒向 Redis 节点(主、从)发送 ping 命令,根据节点的响应分为:


  • 有效响应:在规定的时间(通过 down-after-milliseconds 设置)内,响应+PONG、-LOADING、-MASTERDOWN,即为有效响应

  • 无效响应:除了上面三种响应或在规则的时间内未响应,即为无效响应


如果未无效响应,则会被哨兵标记为主观下线。


当哨兵将一个主节点判断为主观下线后,为了确认该节点是否为客观下线,会向其他监控这一节点的哨兵进行询问,发送 is-master-down-by-addr 命令,当收到所有的回复中,有大于等于 quonum 个哨兵判断此主节点为主观下线,即可判断此主节点为客观下线。



在判定主节点为客观下线后,哨兵集群会选举领头的哨兵(通过 Raft 算法选举,此处不展开),领头的哨兵随后进行故障转移。

三、集群

Redis 节点通过 cluster meet 命令完成节点间握手,建立连接。建立连接后,节点间会定时互相发送 ping/pong 命令,交换数据信息(节点信息、状态等)。


每个 Redis 节点都有一个 clusterNode 来保存节点信息,当节点加入集群中时会有个 clusterState 结构来保存集群的信息状态,如下图所示:



节点间通过 cluster meet 命令,在连接过程中会去更新 clusterState 中的 nodes 信息。


集群的整个数据库被分为 16384 个槽,每个节点负责的槽可以通过cluster addslots来进行指派。在 clusterNode 结构中属性 slots 记录节点负责哪些槽:


struct clusterNode {  unsigned char slots[16384/8];  int numslots;}
复制代码


同时,clusterState 结构里会存 16384 个槽的指派信息,如下:


struct clusterState {  clusterNode *slots[16384];}
复制代码


通过 clusterState 的 slots 可以通过 O(1)时间找到某个槽对应的节点。

在集群中执行命令

在集群环境下,客户端向某节点发送数据库命令时,会首先计算 key 属于哪个槽,如果槽对应的指派是当前节点,会执行命令;如果槽对应的指标不是当前节点,会返回 MOVED 给客户端,并返回槽对应指派的节点信息,后再次执行命令。


计算 key 属于哪个槽:CRC16(key) & 16383

为什么是 16384 个槽?

  • 节点之间检测状态,发送的数据里包含节点的分槽信息数组 slots[16383/8],如果槽太多会导致每次传输的数据包增大,因为节点间的检测时很频繁的,会影响传输效率,容易造成网络阻塞

  • 一般来说 Redis 的集群节点数不建议超过 1000 个,16384 个槽位足够用

四、参考

  • 《Redis 设计与实现》

  • https://www.cnblogs.com/rjzheng/p/11430592.html

发布于: 1 小时前阅读数: 6
用户头像

Hex

关注

还未添加个人签名 2018.05.24 加入

还未添加个人简介

评论

发布
暂无评论
Redis主从复制、Sentinel、集群总结