Redis:codis分布式集群解决方案

一、codis介绍

在大数据高并发场景下,单个 Redis 实例往往会显得捉襟见肘。首先体现在内存上,单个 Redis 的内存不宜过大,内存太大会导致 rdb 文件过大,进一步导致主从同步时全量同步时间过长,在实例重启恢复时也会消耗很长的数据加载时间,特别是在云环境下,单个实例内存往往都是受限的。其次体现在 CPU 的利用率上,单个 Redis 实例只能利用单个核心,这单个核心要完成海量数据的存取和管理工作压力会非常大。

正是在这样的大数据高并发的需求之下,Redis 集群方案应运而生。它可以将众多小内存的 Redis 实例综合起来,将分布在多台机器上的众多 CPU 核心的计算能力聚集到一起,完成海量数据存储和高并发读写操作。

Codis 是 Redis 集群方案之一,令我们感到骄傲的是,它是中国人开发并开源的,来自前豌豆荚中间件团队。
官网地址

二、codis集群架构

在这里插入图片描述

三、codis分片原理

Codis 要负责将特定的 key 转发到特定的 Redis 实例,那么这种对应关系 Codis 是如何管理的呢?

Codis 将所有的 key 默认划分为 1024 个槽位(slot),它首先对客户端传过来的 key 进行 crc32 运算计算哈希值,再将 hash 后的整数值对 1024 这个整数进行取模得到一个余数,这个余数就是对应 key 的槽位。

槽位数量默认是 1024,它是可以配置的,如果集群节点比较多,建议将这个数值配置大一些,比如 2048、4096。

//伪代码
hash = crc32(command.key)
slot_index = hash % 1024
redis = slots[slot_index].redis
redis.do(command)

在这里插入图片描述

四、Codis 实例之间槽位关系同步

如果 Codis 的槽位映射关系只存储在内存里,那么不同的 Codis 实例之间的槽位关系就无法得到同步。所以 Codis 还需要一个分布式配置存储数据库专门用来持久化槽位关系。Codis 开始使用 ZooKeeper,后来连 etcd 也一块支持了。

Codis 将槽位关系存储在 zk 中,并且提供了一个 Dashboard 可以用来观察和修改槽位关系,当槽位关系变化时,Codis Proxy 会监听到变化并重新同步槽位关系,从而实现多个Codis Proxy 之间共享相同的槽位关系配置。

在这里插入图片描述

五、Codis 扩容

刚开始 Codis 后端只有一个 Redis 实例,1024 个槽位全部指向同一个 Redis。然后一个 Redis 实例内存不够了,所以又加了一个 Redis 实例。这时候需要对槽位关系进行调整,将一半的槽位划分到新的节点。这意味着需要对这一半的槽位对应的所有 key 进行迁移,迁移到新的 Redis 实例。

1、Codis Key迁移

那 Codis 如果找到槽位对应的所有 key 呢?

Codis 对 Redis 进行了改造,增加了 SLOTSSCAN 指令,可以遍历指定 slot 下所有的key。Codis 通过 SLOTSSCAN 扫描出待迁移槽位的所有的 key,然后挨个迁移每个 key 到新的 Redis 节点。

在迁移过程中,Codis 还是会接收到新的请求打在当前正在迁移的槽位上,因为当前槽位的数据同时存在于新旧两个槽位中,Codis 如何判断该将请求转发到后面的哪个具体实例呢?

Codis 无法判定迁移过程中的 key 究竟在哪个实例中,所以它采用了另一种完全不同的思路。当 Codis 接收到位于正在迁移槽位中的 key 后,会立即强制对当前的单个 key 进行迁移,迁移完成后,再将请求转发到新的 Redis 实例。

我们知道 Redis 支持的所有 Scan 指令都是无法避免重复的,同样 Codis 自定义的SLOTSSCAN 也是一样,但是这并不会影响迁移。因为单个 key 被迁移一次后,在旧实例中它就彻底被删除了,也就不可能会再次被扫描出来了。

//伪代码
slot_index = crc32(command.key) % 1024
if slot_index in migrating_slots:
	do_migrate_key(command.key) # 强制执行迁移
	redis = slots[slot_index].new_redis
else:
	redis = slots[slot_index].redis
redis.do(command)

六、Codis 自动均衡

Redis 新增实例,手工均衡 slots 太繁琐,所以 Codis 提供了自动均衡功能。自动均衡会在系统比较空闲的时候观察每个 Redis 实例对应的 Slots 数量,如果不平衡,就会自动进行迁移。

七、Codis MGET指令操作过程

mget 指令用于批量获取多个 key 的值,这些 key 可能会分布在多个 Redis 实例中。Codis 的策略是将 key 按照所分配的实例打散分组,然后依次对每个实例调用 mget 方法,最后将结果汇总为一个,再返回给客户端。
在这里插入图片描述

八、Codis 优缺点

1、优点

Codis 在设计上相比 Redis Cluster 官方集群方案要简单很多,因为它将分布式的问题交给了第三方 zk/etcd 去负责,自己就省去了复杂的分布式一致性代码的编写维护工作。而Redis Cluster 的内部实现非常复杂,它为了实现去中心化,混合使用了复杂的 Raft 和Gossip 协议,还有大量的需要调优的配置参数,当集群出现故障时,维护人员往往不知道从何处着手。

2、缺点

Codis 给 Redis 带来了扩容的同时,也损失了其它一些特性,Codis 的官方文档中给出了一系列不支持的命令列表。

  • 因为 Codis 中所有的 key分散在不同的 Redis 实例中,所以事务就不能再支持了,事务只能在单个 Redis 实例中完成。
  • 部分指令不在支持。比如 rename 操作也很危险,它的参数是两个 key,如果这两个 key 在不同的 Redis 实例中,rename 操作是无法正确完成的。
  • 为了支持扩容,单个 key 对应的 value 不宜过大,否则可能会带来迁移卡顿。
  • Codis 因为增加了 Proxy 作为中转层,所有在网络开销上要比单个 Redis 大,毕竟数据包多走了一个网络节点,整体在性能上要比单个 Redis 的性能有所下降。
  • Codis 的集群配置中心使用 zk 来实现,意味着在部署上增加了 zk 运维的代价。

Codis 需要随着redis版本而更新,从官网可以看出,版本已经很久没有更新了,可能会被redis cluster方案逐步淘汰。

九、Codis 配置

1. 安装zookeeper(可以选择不安装,但是这里推荐安装使用)

这里以Ubuntu 18.04举例

//安装zookeeper ubuntu18.04
shell> apt search zookeeper|grep ^zookeeper
shell> sudo apt install zookeeper

//找启动脚本
shell> sudo find / -name "zookeeper"
shell> cd /usr/share/zookeeper
shell> sudo ./zkServer.sh start
shell> sudo ./zkCli.sh

2. 配置codis

这里可以参考官网:codis配置
我这里是直接下载release binary文件安装的,这里就不做详细说明了

//配置步骤,请按顺序配置
//1. codis-dashboard 
//导出配置文件,注意修改zookeeper相关配置
shell> ./codis3.2.2-go1.8.5-linux/codis-dashboard --default-config>dashboard.toml
//启动
shell> ./codis3.2.2-go1.8.5-linux/codis-dashboard --ncpu=4 --config=dashboard.toml --log=dashboard.log --log-level=WARN

//2. codis-proxy
//导出配置文件,注意修改zookeeper相关配置
shell> ./codis3.2.2-go1.8.5-linux/codis-proxy --default-config > proxy.toml
//启动
shell> ./codis3.2.2-go1.8.5-linux/codis-proxy --ncpu=4 --config=proxy.toml --log=proxy.log --log-level=WARN
//开启关闭Proxy:这里的开启是值进入online状态。按照上面介绍的,开启codis-proxy 启动后,处于waitingonline 状态的,需要改成online状态进入zk(jodis)
//(1) 通过 codis-fe 添加:通过 Add Proxy 按钮,将 admin_addr 加入到集群中;
//(2) 通过 codis-admin添加
shell> ./codis3.2.2-go1.8.5-linux/codis-admin --dashboard=127.0.0.1:18080 --create-proxy -x 127.0.0.1:11080

//3. codis-server
shell> ./codis3.2.2-go1.8.5-linux/codis-server

//4. codis-fe
shell> ./codis3.2.2-go1.8.5-linux/codis-fe --ncpu=4 --log=fe.log --log-level=WARN --zookeeper=127.0.0.1:2181 --listen=127.0.0.1:8080
或者
shell> ./codis3.2.2-go1.8.5-linux/codis-fe --ncpu=4 --log=fe.log --log-level=WARN --zookeeper=127.0.0.1:2181 --listen=0.0.0.0:8080

//5. codis.json (如果使用zookeeper 可以不导出配置文件)
shell> ./codis3.2.2-go1.8.5-linux/codis-admin --dashboard-list --zookeeper=127.0.0.1:2181>codis.json

//6. codis-fe网址
http://listen的port:8080/

3. 配置codis展示

codis所有后台进程:
在这里插入图片描述

codis codis-fe GUI界面:
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值