本文记录学习《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