• 欢迎访问蜷缩的蜗牛博客 蜷缩的蜗牛
  • 微信搜索: 蜷缩的蜗牛 | 联系站长 kbsonlong@qq.com
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏吧

Memcached 与Redis (3): Redis 的集群与复制

Zookeeper 蜷缩的蜗牛 4个月前 (05-25) 12次浏览 已收录

1. Redis 集群
1.1 集群节点

加入集群:

节点使用 cluster meet 命令来尝试握手, 若成功, 则加入到相应的集群中.

ClusterNode

节点使用 ClusterNode 来记录自己的状态, 并为集群中所有其它节点创建相应的 clusterNode.

ClusterNode{ ctime, name, flags, configEpoch, ip, port, clusterLink};
ClusterLink{ ctime, fd, sndbuf, rcvbuf, ClusterNode*};
ClusterState{ mySelf, currentEpoch; state, size, dict* nodes}.

flags 记录着 Node 的角色加状态信息.
fd 代表 tcp 描述符.
sndbuf 和 rcvbuf 作为缓冲区 ,保存着从其它 Node 发送和接收到的消息.
ClusterState 是以该 Node 的视角来看, 集群目前所处的状态.

1.2 slot

以分片的方式来保存 DB 中的键值对, 分为 16384 个 slot.
当所有 16384 个槽都有节点处理时,集群处理 OK 上线状态.否则为 fail.
记录当前 Node 被指派的槽信息: clusterNode{ char slots; int numslots};

其中, slots 二进制位为 1 时代表处理相应数值的槽.

节点会在集群内相互传播槽指派信息.

记录着集群中所有槽的指派信息: clusterState{ clusterNode * slots[16384]};.
通过查看 state.slots[i] 的值, 即可得到负责处理槽 i 的 Node.

可以在 online 状态下进行重新分片动作.

1.3 在集群中执行命令

接收命令的 Node 会计算出 key 属于那个槽,

当该槽并未被指派给自己时, 会向客户端返回 MOVED 错误, 指引客户端 redirect 至正确的 Node.

计算 key 所属槽的: slot_number(key) = CRC16(key) & 16383;

集群的客户端会与多个 Node 创建�TCP 链接, redirect 命令通过转换 TCP 来完成命令的发送.

如果与想要 redirect 的节点还未建立 TCP 链接, 会先建立后再进行转向.
集群模式下的 redis-cli 客户端会隐藏 MOVED 错误而自动完成 redirect.
而单机模式下的客户端因为无法进行 redirect, 会打印出 MOVED 错误.

Node 只能使用 0 号数据库, 而单机服务器并无该限制.

记录槽和键的对应关系: clusterState{ zskiplist *slot_to_keys}.

1.4 ASK 错误

在重新分片期间, 可能会出现槽的键值同时分布在源和目的节点中的情况.
若源节点发现键已不在自身上, 则向客户端返回 ASK 错误, 来指引客户端转向正在导入槽的目标节点.

1.5 复制与故障转移.

master 和 slave

master 负责处理槽;
slave �会复制 master 的数据, 并在 master 下线后, 代替它继续进行处理.

设置 slave 节点: cluster replicate .

接收者设置自己的 clusterNode *slaveof 属性为 node_id, 同时修改 flags.
此时会开始从 master 进行数据复制的动作: slaveof .

clusterNode{ clusterNode *slaves, numslaves}.

记录着正在复制该 master 的 slave 信息

故障检测

定期发送 PING 消息, 若规定时间内没有返回, 则将节点标记为 probable fail(PFAIL).
若集群中, 若半数以上处理槽的 master 都将某节点设置为 PFAIL, 则该节点将被标记为 FAIL, 同时进行广播.

故障转移

如果 slave 发现 master 已下线, 则开始进行故障转移.

选举新的 master

集群的配置纪元为自增计数器, 每一次故障转移会进行自增.
每个处理槽的 master 都有一票, 第一个向 master 要求投票的 slave 将获得 master 的投票.
收集到大于 N/2 个投票的 slave 会成为新的 master.

1.6 消息

PING 消息.

默认每秒发送一次.
过程: 从已知节点列表中随机选出五个节点, 对其中的最长时间没有发送过 PING 的节点发送该消息, 来检测其是否在线.

PONG 消息.

对 MEET 和 PING 的响应.
或者用于让其它节点刷新对自己状态的认识

如: 故障转移后新的 master.

PUBLISH 消息.

节点收到后, 会执行该命令, 然后向集群广播 PUBLISH 消息.

2. 复制

复制分为: 初次复制和断线后复制.

2.1 旧版的实现

同步的实现.

master 在收到 SYNC 命令后, 从后台生成 RDB 文件, 并使用缓存记录从现在开始的所有写操作.
slave 接收并载入 RDB 文件, 并接收执行缓存中记录的写操作.

命令传播.

在同步过后, master 会将其执行的更新命令发送给 master, 说明其已达到一致状态.
由于执行 SYNC 命令非常耗费资源, 所以在断线后复制时效率不佳.

2.2 新版的实现

完整重同步.

用于初次复制, 步骤等于 SYNC.

部分重同步.

处理断线后重复制.
master 只用将断线期间的更新命令发送给 slave, 并让其执行.

master 和 slave 各自维护各自的 replication offset, 并分别在传播和接收传播时加上 N.

通过对比 offset 的值来得知主从是否处于一致状态.

复制积压缓存区.

由 master 负责维护的 fixed-size 的 FIFO 队列, 默认大小为 1MB.
进行命令传播时, 将命令写入缓存区.
缓存区同时会为队列中每个字节记录相应的 offset.
对于断线重连的 slave, 若其 offset 之后的数据仍然存在于缓存区, 则使用部分重同步, 否则就需要使用完全重同步.
根据 slave 断线后重连的时长和 master 的写命令频率来调整缓存区大小.

服务器运行 ID.

对于断线重连的 slave, 会将保存的 master 的 ID 发送给重新连接到的 master, 若相同,则可以尝试进行部分重同步.

2.3 心跳检测

replconf ACK .
用于检测主从服务器的网络连接状态.
辅助实现 min-slaves 配置选项, 以防止 master 在不安全状态下执行写命令.
检测命令丢失.

当 master 发现 slave 的 offset 小于自己的 offset, 会从复制积压缓存区中找出 slave 缺失的数据并进行重发.

3. Sentinel

本质上是运行在特殊模式下的 Redis 服务器.
sentinel 成为 master 的客户端, 并创建两个指向 master 的异步网络连接.

命令连接. 用于向 master 发送命令, 并接收命令回复.

订阅连接. 订阅 master 的 sentinel:hello channel.

获取 master 信息.

每隔 10 秒通过命令连接向 master 发送 INFO 命令, 然后通过分析返回�获取 master 的状态.

本文转载自 title


蜷缩的蜗牛 , 版权所有丨如未注明 , 均为原创丨 转载请注明Memcached 与 Redis (3): Redis 的集群与复制
喜欢 (0)
[]
分享 (0)