Redis 运维实战 第03期:Codis

2022-04-25 08:27:10 浏览数 (1)

在前面,我们提到了 Redis 集群方案 Redis Cluster,今天我们来聊聊 Redis 另外一种比较受欢迎的集群方案:Codis。

Codis 是豌豆荚开源的 Redis 分布式中间件,使用 Go 语言开发,其拥有不停机数据迁移、对客户端透明、平滑扩容、拥有管理后台等特点。

下面我们从几个方向聊聊这一集群方案:

1 架构

首先,一起来看看 Codis 的架构图:

这里简单介绍各个组件的作用:

  • Codis Server:Codis 3.x 是由 Redis 3.2.8 分支开发而来,相对 Redis 3.2.8,其变化可以参考官方文档:Redis 修改部分。
  • Codis Proxy:客户端连接 Redis 的代理,需要注意的是,有部分命令不支持:不支持的命令列表。
  • Codis Dashboard:集群管理工具,支持 codis-proxy、codis-server 的添加、删除操作,以及数据迁移操作等。
  • Codis Admin:集群管理的命令行工具。
  • Codis FE:集群管理界面。
  • Storage:为集群状态提供外部存储。

2 安装

Codis 安装参考 Github 安装文档(https://github.com/CodisLabs/codis/blob/release3.2/doc/tutorial_zh.md)。

3 Codis 分片

在讲解 Redis Cluster 时,我们知道其有 16384 个虚拟槽,而 Codis,也是使用类似的槽结构,它默认把所有的 key 分为 1024 个槽(这个槽是可以配置,可以设置成 2048 或者 4096 个),每一个槽位都对应了一个分组,具体槽位的分配,可以进行自定义。首先要对客户端写入的 key 进行 CRC32 运算,计算出哈希值,再除以 1024 取余,然后就能算出这个 key 属于哪个槽,然后根据槽与分组的映射关系,就能去对应的分组当中处理数据了。

那么不同的 Codis 实例之间槽位关系是如何同步的呢?

Codis 通常是由 ZooKeeper 来管理的,当槽位关系发生变化时,Codis Proxy 会监听到这些变化,然后重新同步槽位关系,从而保证多个 Codis Proxy 之间共享相同的槽位关系配置

4 扩容

比如某个 Codis 集群下,只有一个 Codis Server 实例,那 1024 个 slot 全部指向同一个 Codis Server。当扩容到两个实例时,如果选择的是自动均衡,那么会有一半的 slot 迁移到新的节点上。

那么此时 Codis 怎样找到槽位对应的所有 key 呢?

Codis 通过 SLOTSSCAN 指令,可以扫描需要迁移 slot 下所有的 key,然后挨个迁移每个 key 到新的 Codis Server 节点上 。

在迁移过程中,Codis 如果接收到位于正在迁移槽位中的 key 后,会立即强制对当前的单个 key 进行迁移,迁移完成后,再将请求转发到新的 Codis Server 实例上。这也是 Codis 为什么可以平滑扩容的原因。

5 几种集群方案的对比

在笔者以往的工作经历中,使用最多的就是 Codis、Twemproxy、Redis cluster,这里就通过一个表格,对三种集群方案做一个对比,具体选择哪个,可自行评估。

集群方案

优点

缺点

Codis

平滑扩容支持读写分离拥有管理平台多线程

Codis 集群整体性能比单个 Redis 性能有所下降依赖 zk跟不上官方高版本 Redis 的新功能

Twemproxy

分布式

不支持平滑扩容运维难度大单线程

Redis cluster

无Proxy,直连性能较高支持平滑扩容无中心架构

读写分离实现复杂不支持 pipeline维护成本高客户端必须支持集群协议

6 与 Codis 相关的问题

6.1 Codis 可以当队列使用吗?

Codis 支持 LPUSH LPOP 指令,但是当使用队列时,对于单个 key,只能落在一台机器上。因此不管这个队列多大,性能只相当于单实例。因此建议将一个大队列拆分成多个小的队列,放在不同的 key 中。

6.2 Codis 支持多线程吗?

Codis Proxy 是多线程的,启动的线程数是 CPU 的核数。

专栏《Redis 运维实战》系列文章推荐

Redis 运维实战 第01期:Redis 复制

Redis 运维实战 第02期:Redis Cluster

0 人点赞