redis 集群

#anki

创建 redis 集群

  1. 在配置文件中修改cluster-enabled配置项为 yes
  2. 启动 redis 实例
  3. 使用命令互相发现?节点握手(cluster meet命令)
  4. 使用 cluster replicate 指定主副节点
  5. 分配哈希槽(hash slot)cluster addslots
  6. 开始使用

数据写入

  • 写入请求被发送到随机一个节点
  • 该节点通过哈希计算(全字段计算、hashtag 计算),确认数据被放在哪个哈希槽(哪个主节点上)(dummy 客户端、smart 客户端)
  • 进行请求转发,将重定向命令发送给客户端
  • 客户端将请求发送到正确的主节点上(节点对不属于它的键命令只响应重定向,并不负责转发,由客户端完成转发操作
  • 执行写入操作
  • 何时返回写入成功?(直接返回成功,异步写入从节点)
  • 如何同步?(直接将写命令发送给从节点)

数据读取

  • 读取请求被发送到随机一个节点
  • 该节点通过哈希计算,确认数据被放在哪个哈希槽
  • 如何判断去哪个节点读取数据(主节点还是对应的从节点)
  • 执行读取操作

只有当从节点开启readonly命令时(默认关闭),从节点才会接收读请求,这时主节点只接收写请求,实现读写分离?

过期数据如何同步过期状态

主节点在进行惰性删除和定期清理的时候,发送 del 命令到从节点。 从节点不会主动清理过期数据。

主从节点数据复制流程

从节点在主线程中每隔 1 秒发送 replconf ack{offset} 命令,给主节点上报当前的复制偏移量。

从节点刚连上主节点时会进行一次全量复制或部分复制,之后通过异步写操作进行数据同步。

复制过程是否会阻塞主线程 ?

如果复制持续失败,偏移量过大,是否有补救措施

如网络闪断,网络恢复后,会尝试采用全量复制(采用RDB方式)或部分复制(读取缓冲区数据)补全故障期间数据。

心跳机制

Gossip(流言)协议

槽数据迁移过程

  1. 对目标节点发送cluster setslot {slot} importing {sourceNodeId}命令,通知目标节点准备导入数据
  2. 对源节点发送cluster setslot {slot} migrating {targetNodeId}命令,通知源节点准备迁出槽数据
  3. 源节点循环执行cluster getkeysinslot {slot} {count}命令,获取 count 个属于槽 {slot} 的键
  4. 在源节点上执行migrate {targetIp} {targetPort}""0{timeout} keys {keys...} 命令,把获取的键通过流水线(pipeline)机制批量迁移到目标节点,批量迁移版本的 migrate 命令在 Redis3.0.6 以上版本提供,之前的migrate 命令只能单个键迁移。对于大量 key 的场景,批量键迁移将极大降低节点之间网络 IO 次数
  5. 重复执行步骤 3 和步骤 4 直到槽下所有的键值数据迁移到目标节点
  6. 向所有主节点发送cluster setslot {slot} node {targetNodeId}命令,通知槽分配给目标节点。为了保证槽节点映射变更及时传播,需要遍历发送给所有主节点,将被迁移的槽指向新节点。

如何处理槽迁移过程中的读请求

当数据从源节点到目标节点迁移过程中,可能出现一部分数据在源节点,而另一部分在目标节点。

  • 客户端根据本地 slot 缓存发送命令到源节点,如果存在键对应则直接执行返回结果给客户端。
  • 如果节点返回 MOVED 错误,更新本地的 slot 到 Redis 节点的映射关系,然后重新发起请求。
  • 如果数据正在迁移中,节点会回复 ASK 重定向异常。格式如下: ( error ) ASK { slot } { targetIP } : { targetPort }
  • 客户端从 ASK 重定向异常提取出目标节点信息,发送 asking 命令到目标节点打开客户端连接标识,再执行键命令。

主节点故障

  • 节点间会不间断地发送 ping-pong 消息进行通信,当通信持续失败时,发送节点会认为对方节点下线(主观下线
  • 半数以上持有槽的主节点都标记某个节点是主观下线时,触法对该节点的客观下线
  • 该主节点会广播一条 fail 消息,让集群内所有节点标记该节点下客观下线,同时通过故障节点的从节点触发故障转移流程。
  • 故障节点的从节点根据复制偏移量以不同的优先级发起选举
  • 由持有槽的主节点进行投票,超过二分之一得票的从节点当选
  • 从节点执行clusterDelSlot操作撤销故障主节点负责的槽,并执行 clusterAddSlot把这些槽委派给自己。
  • 向集群广播自己的 pong 消息,通知集群内所有节点。

从节点故障

cluster slots风暴

复制风暴

集群模式下哪些命令可能导致异常

  • key 批量操作支持有限,如 msetmget 等,只支持对具有相同 slot 值的 key 执行批量操作。
  • key 事务操作支持有限,只支持同一节点的 key
  • 集群模式不支持多数据库空间
  • 主从复制结构只支持一层,不支持树状嵌套结构