redis 4.x Cluster与codis集群对比分析

redis 4.x Cluster与codis集群对比分析

Posted by fengdi on November 29, 2018

1、架构对比

1.1、redis 4.0 cluster

Redis 4.0 版本的集群是去中心化的结构,集群元数据信息分布在每个节点上,主备切换依赖于多个节点协商选主。Redis 提供了 redis-trib 工具做部署集群及运维等操作。 客户端访问散列的 db 节点需依赖 smart client,也就是客户端需要对 redis 返回的节点信息做判断选择路由等操作。例如客户端请求一个节点,如果所请求的 key 不在该节点上,客户端需要判断返回的 move 或 ask 等指令,重定向请求到对应的节点。

1.2、codis cluster

  • codis 由3大组件构成:
    • ocodis-server:修改过源码的 redis,支持 slot、扩容迁移等
    • codis-proxy:支持多线程,go 语言实现的内核
    • codis Dashboard:集群管理工具
  • codis 提供 web 图形界面管理集群
  • 集群元数据存在在 zookeeper 或 etcd
  • 提供独立的组件 codis-ha 负责 redis 节点主备切换
  • 基于 proxy 的 codis,客户端对路由表变化无感知。客户端需要从 codis dashboard 调用 list proxy 命令获取所有 proxy 列表,并根据自身的轮询策略决定访问哪个 proxy 节点以实现负载均衡

2、性能对比

2.1、压测环境

在3台物理机上分别搭建了以上3种redis集群。每台物理机千兆网卡、24核 CPU、内存189 GB。3台物理机分别跑压测工具 memtier_benchmark、codis proxy/阿里云 proxy、redis server。Redis server 使用各种集群配套的 redis 内核。 固定 key size 32个字节,set/get 操作比例为1:10。每个线程16个客户端。连续压测5分钟,分8个、 16个、 32个、 48个、 64个线程压测。 因为 Redis 4.0集群需要额外的客户端选择节点,而 memtier_benchmark 不支持,所以使用了 hashtag 来压测 Redis 4.0。 每个集群有8个 master db 和8个 slave db,aof 打开。aof rewrite 的最小 buffer 为64 MB。压测的对象分别为单个 redis 4.0 节点, 单个阿里云 redis-proxy, 单核的 codis-proxy, 8核的 codis-proxy。codis 使用的 go 版本为1.7.4。 压测结果图如下:

可以看出,单核的 codis-proxy 性能最弱。8核的 codis-proxy 压测没有对 key 使用 hashtag,相当于将请求分散到后端8个 db 节点上, 也可以说相当于8个阿里云的 redis-proxy,自然性能数据就比较高了。 单核的阿里云 redis-proxy 在压力够大的情况下性能逼近原生的 redis db 节点。在实际生产环境中,使用原生的 redis cluster,客户端需要实现 cluster protocol, 解析 move、ask 等指令并重定向节点,随意访问 key 可能需要两次访问操作才能完成,性能上并不能完全如单节点一样。

3、支持特性对比

3.1、支持的不同协议对比

操作 redis 4.x 集群 codis 集群
事务 支持相同slot 不支持
sub/pub 支持相同slot 不支持
flushall 支持 不支持
select 不支持 不支持
mset/mget 支持相同slot 支持

3.2、水平扩展对比

Redis 4.0 cluster、codis分布式集群均实现了面对 slot 的管理,扩展的最小单元是 slot。分布式集群水平扩展的本质是对集群节点的路由信息管理以及数据的迁移。3种集群迁移数据的最小单位均是 key。

3.2.1、Redis cluster 水平扩展原理

Redis 4.0 cluster 支持指定 slot 在节点中移动,也支持加入空节点后根据集群节点中已存在的 slot 分布自动进行再分布。以 redis-trib 的 move_slot 为例解析 slot 移动的过程:

  • 调用setslot命令修改源、目标节点 slot 的状态。
  • 获取源节点上 slot 的 key 列表。
  • 调用migrate命令迁移 key,迁移过程中 redis 属于阻塞状态,只有目标节点 restore 成功后才返回。
  • 调用setslot命令修改源、目标节点 slot 的状态

Redis cluster 提供迁移状态中的重定向机制,向客户端返回 ASK,客户端收到后需先发送asking指令到目标节点上,然后再发请求到目标节点上才可以访问。当访问的 key 满足以下全部条件时会出现重定向返回:

  • key 所属 slot 在该节点上。如不在,返回的是 MOVE。
  • slot 处于迁移状态中。
  • key 不存在。

如上所述,migrate 是一个同步阻塞型的操作,如果 key 并不为空,即使 slot 处于迁移状态,key 依然能被读写,以此保证数据的一致性。

3.2.2、codis 水平扩展原理

codis 对 slot 的再分布策略与 redis cluster 相同。codis-server 内核并没有存储 slot 的信息,也不解析 key 所在的 slot,只有在dbadd等操作时将对应的 key 记录到以 slot 为 key 的 dict 中。如果 key 带有 tag,则将 tag 做 crc32 运算后将 key 插入到以 crc32值为 key 的 skiplist 中。 codis Dashboard 后台起迁移状态机程序,先确保通知到所有 proxy 开始迁移,即 prepare 阶段,如有一台以上 proxy 失败,则迁移任务失败。迁移步骤与 redis cluster 类似,不同点是:

  • slot 状态信息存储在 zookeeper/etcd。
  • 发送slotsmgrttagslot而非migrate指令,slotsmgrttagslot执行时会随机获取一个 key 迁移,如 key 带有 tag,则从上文中的 skiplist 获取所有 key 批量迁移。

迁移过程中如何保证数据的一致性? codis 同样也是同步阻塞型的迁移操作。在保持数据一致性方面,因为 codis-server 内核不维护 slot 的状态,所以一致性的保证落在了 proxy 组件上。codis-proxy 在处理请求时,先判断 key 所在 slot 的状态,如 slot 处于迁移中,则向 codis-server 发起指定 key 迁移的命令,等 key 迁移完成后,codis-proxy 转向目标的 codis-server 请求。做法简单,对 redis 内核修改较少,但同时也导致迁移慢,客户端卡住的时间较久。

4、其他对比

操作 redis 4.x 集群 codis 集群
内核热升级 不支持 不支持
proxy热升级 无proxy 不支持
slots槽数 16384 1024
密码 不支持,需改 redis-trib 脚本 支持,所有组件密码必须一致
mset/mget 支持相同slot 支持