Redis 开发与运维Redis Cluster 集群

Posted 木兮同学

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redis 开发与运维Redis Cluster 集群相关的知识,希望对你有一定的参考价值。

文章目录


一、故障转移

故障发现

  • Redis 集群不需要依赖哨兵,自身实现了高可用。高可用首先需要解决集群部分失败的场景:当集群内少量节点出现故障时通过自动故障转移保证集群可以正常对外提供服务。
  • Redis 集群内节点通过 ping/pong 消息实现节点通信,消息不但可以传播节点槽信息,还可以传播其他状态如:主从状态、节点故障等。
  • 因此故障发现也是通过消息传播机制实现的,主要环节包括:主观下线和客观下线
    • 主观下线
      • 某个节点认为另一个节点不可用,这个状态并非最终的故障判定,只能代表一个节点的意见,存在误判可能。
      • 集群中每个节点都会定期向其他节点发送 ping 消息,接收节点回复 pong 消息作为响应。如果在 cluster-node-timeout 时间内通信一直失败,则发送节点会认为接收节点存在故障,把接收节点标记为主观下线状态。
    • 客观下线
      • 标记一个节点真正的下线,集群内多个节点都认为该节点不可用,从而达成共识。如果持有槽的主节点故障,需要为该节点进行故障转移。
      • 当某个节点判断另一个节点主观下线后,相应的节点状态会跟随消息在集群内传播。通过 Gossip 消息传播,集群内节点不断收集到故障节点的下线报告。当半数以上持有槽的主节点都标记某个节点是主观下线时,触发客观下线流程

故障恢复

  • 故障节点变为客观下线后,如果下线节点是持有槽的主节点则需要在它的从节点中选出一个替换它,从而保证集群的高可用。
  • 下线主节点的所有从节点承担故障恢复的义务,当从节点通过内部定时任务发现自身复制的主节点进入客观下线时,将会触发故障恢复流程。

二、集群运维

集群完整性

  • 为了保证集群完整性,默认情况下当集群 16384 个槽任何一个没有指派到节点时整个集群不可用。

带宽消耗

  • 集群内 Gossip 消息通信本身会消耗带宽,官方建议集群最大规模在 1000 以内,也是出于对消息通信成本的考虑,因此单集群不适合部署超大规模的节点。
  • 集群带宽消耗主要分为:读写命令消耗 + Gossip 消息消耗。因此搭建 Redis 集群时需要根据业务数据规模和消息通信成本做出合理规划
    • 1)在满足业务需要的情况下尽量避免大集群。同一个系统可以针对不同业务场景拆分使用多套集群。这样每个集群既满足伸缩性和故障转移要求,还可以规避大规模集群的弊端。
    • 2)适度提高 cluster-node-timeout 降低消息发送频率,同时cluster-node-timeout 还影响故障转移的速度,因此需要根据自身业务场景兼顾二者的平衡。
    • 3)如果条件允许集群尽量均匀部署在更多机器上。避免集中部署,如集群有60个节点,集中部署在3台机器上每台部署 20个节点,这时机器带宽消耗将非常严重。

Pub/Sub 广播问题

  • Redis 在 2.0 版本提供了 Pub/Sub(发布/订阅)功能,用于针对频道实现消息的发布和订阅。
  • 但是在集群模式下内部实现对所有的 publish 命令都会向所有的节点进行广播,造成每条 publish 数据都会在集群内所有节点传播一次,加重带宽负担
  • 所以,针对集群模式下 publish 广播问题,当频繁应用发布订阅功能时应该避免在大量节点的集群内使用,否则会严重消耗集群内网络带宽。针对这种情况建议使用 sentinel 结构专门用于 Pub/Sub 功能,从而规避这一问题。

集群倾斜

  • 集群倾斜是指不同节点之间数据量和请求量出现明显差异,这种情况将加大负载均衡和开发运维的难度。
  • 数据倾斜,主要分以下几种:
    • 节点和槽分配严重不均。针对每个节点分配的槽不均的情况,可以使用 redis-trib.rb info host:ip 进行定位。
    • 不同槽对应键数量差异过大。键通过 CRC16 哈希函数映射到槽上,正常情况下槽内键数量会相对均匀。但大量使用 hash_tag 时,会产生不同的键映射到同一个槽的情况。
    • 集合对象包含大量元素
    • 内存相关配置不一致
  • 请求倾斜,集群内特定节点请求量/流量过大将导致节点之间负载不均,影响集群均衡和运维成本。避免方式如下:
    • 合理设计键,热点大集合对象做拆分或使用 hmget 替代 hgetall 避免整体读取。
    • 不要使用热键作为 hash_tag,避免映射到同一槽。
    • 对于一致性要求不高的场景,客户端可使用本地缓存减少热键调用。

集群读写分离

  • 只读连接
    • 集群模式下从节点不接受任何读写请求,发送过来的键命令会重定向到负责槽的主节点上。当需要使用从节点分担主节点读压力时,可以使用 readonly 命令打开客户端连接只读状态。
    • 当开启只读状态时,从节点接收读命令处理流程变为:如果对应的槽属于自己正在复制的主节点则直接执行读命令,否则返回重定向信息。
  • 读写分离
    • 集群模式下的读写分离,同样会遇到:数据延迟、读到过期数据、从节点故障等问题。
    • 集群模式下读写分离成本比较高,可以直接扩展主节点数量提高集群性能,一般不建议集群模式下做读写分离。

数据迁移

  • 应用 Redis 集群时,常需要把单机 Redis 数据迁移到集群环境。redis-trib.rb 工具提供了导入功能,用于数据从单机向集群环境迁移的场景。命令如下:
redis-trib.rb import host:port --from <arg> --copy --replace

来源:《Redis 开发与运维》第 10 章 集群

以上是关于Redis 开发与运维Redis Cluster 集群的主要内容,如果未能解决你的问题,请参考以下文章

Redis 开发与运维Redis Cluster 集群

Redis 开发与运维Redis Cluster 集群

Redis 开发与运维Redis Cluster 集群

Redis 开发与运维Redis Cluster 集群

Redis 开发与运维Redis Cluster 集群

Redis 开发与运维Redis Cluster 集群