【Cache System】Redis 集群方案

Posted by 西维蜀黍 on 2020-07-10, Last Modified on 2022-12-10

Redis 集群方案

Redis 的集群解决方案有社区的,也有官方的,社区的解决方案有 CodisTwemproxy

Codis

Codis 由我国的豌豆荚团队开源

Twemproxy

Twemproxy 由Twitter团队开源。

Redis Cluster

Redis Cluster 是Redis3.0之后,官方的集群解决方案,由 Redis 官方团队来实现。

这大大增强了Redis水平扩展的能力。

与Codis 和 Twemproxy 不同的是:Redis Cluster并非使用Porxy模式来连接集群节点,而是使用无中心节点的模式来组建集群。

Redis Cluster实现在多个节点之间进行数据共享,即使部分节点失效或者无法进行通讯时,Cluster仍然可以继续处理请求。若每个主节点都有一个从节点支持,在主节点下线或者无法与集群的大多数节点进行通讯的情况下, 从节点提升为主节点,并提供服务,保证Cluster正常运行,Redis Cluster的节点分片是通过哈希槽(hash slot)实现的,每个键都属于这 16384(0~16383) 个哈希槽的其中一个,每个节点负责处理一部分哈希槽。

Redis Cluster的概念特点

  • 去中心、去中间件,各节点平等,保存各自数据和集群状态,节点间活跃互连。
  • 传统用一致性哈希分配数据,集群用哈希槽(hash slot)分配。 算法为CRC16。
  • 默认分配16384个slot, 用CRC16算法取模{ CRC16(key)%16384 }计算所属slot。
  • 最少3个主节点

优点:

  • 官方解决方案
  • 可以在线水平扩展(Twemproxy的一大弊端就是不支持在线扩容节点)
  • 客户端直连,系统瓶颈更少
  • 无中心架构
  • 支持数据分片

Redis Cluster集群现实存在的问题 尽管属于无中心化架构一类的分布式系统,但不同产品的细节实现和代码质量还是有不少差异的,就比如Redis Cluster有些地方的设计看起来就有一些“奇葩”和简陋:

  • 不能自动发现:无Auto Discovery功能。集群建立时以及运行中新增结点时,都要通过手动执行MEET命令或redis-trib.rb脚本添加到集群中
  • 不能自动Resharding:不仅不自动,连Resharding算法都没有,要自己计算从哪些结点上迁移多少Slot,然后还是得通过redis-trib.rb操作
  • 严重依赖外部redis-trib:如上所述,像集群健康状况检查、结点加入、Resharding等等功能全都抽离到一个Ruby脚本中了。还不清楚上面提到的缺失功能未来是要继续加到这个脚本里还是会集成到集群结点中?redis-trib也许要变成Codis中Dashboard的角色
  • 无监控管理UI:即便未来加了UI,像迁移进度这种信息在无中心化设计中很难得到
  • 只保证最终一致性:写Master成功后立即返回,如需强一致性,自行通过WAIT命令实现。但对于“脑裂”问题,目前Redis没提供网络恢复后的Merge功能,“脑裂”期间的更新可能丢失

注意,如果设置Redis Cluster的数据冗余是1的话,至少要3个Master和3个Slave。

Compared with Twemproxy and Redis Cluster

Codis Twemproxy Redis Cluster
resharding without restarting cluster Yes No Yes
pipeline Yes Yes No
hash tags for multi-key operations Yes Yes Yes
multi-key operations while resharding Yes - No(details)
Redis clients supporting Any clients Any clients Clients have to support cluster protocol

“Resharding” means migrating the data in one slot from one redis server to another, usually happens while increasing/decreasing the number of redis servers.

Codis和Redis Cluster的区别

Redis Cluster基于smart client和无中心的设计,client必须按key的哈希将请求直接发送到对应的节点。

这意味着:

  • 如果使用 Redis Cluster,则必须使用特定编程语言对应的redis driver(如果你所使用的编程语言对应的Redis Driver不完善,)
  • client不能直接像使用Redis单机一样,通过使用pipeline来提高效性能,因而,如果想同时执行多个请求来提高performance,则只能在client端自行实现异步逻辑。

而因为Codis有中心节点(即基于proxy的设计),对client来说,可以像对单机redis一样去操作proxy(除了一些命令不支持),还可以继续使用pipeline。

并且如果proxy后面有多个 redis node,速度会显著快于单redis的pipeline。同时Codis使用zookeeper来作为辅助,这意味着单纯对于redis集群来说,需要额外的机器搭zk,不过对于很多已经在其他服务上用了zk的公司来说这不是问题。