什么是Codis

Codis 是一个分布式的redis解决方案,对于前端来说,Codis类似一个内存很大的redis服务,对于上层的请求,Codis会处理请求的转发,数据的迁移等,对于上层来说和操作单台redis服务差不多。

Codis集群
Codis集群

Codis就是起着一个中间代理的作用,能够把所有的Redis实例当成一个来使用,在客户端操作着SDK的时候和操作Redis的时候是一样的,没有差别。

因为Codis是一个无状态的,所以可以增加多个Codis来提升QPS,同时也可以起着容灾的作用。


Codis组成部分

  1. Codis-proxy

    实现redis协议,本身是无状态的,所以可以部署很多节点

  2. Codis-config

    Codis的管理工具,包括添加、删除redis节点,添加、删除proxy节点,发起数据迁移等操作,自带httpserver,支持管理后台方式管理配置(会启动一个dashboard,用户可以直接在浏览器上观察Codis集群的状态)

Codis后台管理页面
Codis后台管理页面
  1. Codis-server

    由Codis维护的redis的分支,加入了slot的支持和原子的数据迁移指令;codis-proxy和codis-config只能和对应版本的redis交互才能正常运行

  2. Zookeeper

    用于Codis集群元数据的存储,维护codis集群节点,用来存放数据路由表和codis-proxy节点的元信息,codis-config发起的命令都会通过ZooKeeper同步到各个存活的codis-proxy


Codis架构

Codis架构图
Codis架构图

Codis分片原理

在Codis中,Codis会把所有的key分成1024个槽,这1024个槽对应着的就是Redis的集群,这个在Codis中是会在内存中维护着这1024个槽与Redis实例的映射关系。这个槽是可以配置,可以设置成2048或者是4096个。看你的Redis的节点数量有多少,偏多的话,可以设置槽多一些。

Codis中key的分配算法,先是把key进行CRC32 后,得到一个32位的数字,然后再hash%1024后得到一个余数,这个值就是这个key对应着的槽,这槽后面对应着的就是redis的实例。(可以思考一下,为什么Codis很多命令行不支持,例如KEYS操作)

KEY分配算法

1
2
3
4
5
//Codis中Key的算法
hash = crc32(command.key)
slot_index = hash % 1024
redis = slots[slot_index].redis
redis.do(command)

Codis 槽位同步

如果这个Codis节点只在自己的内存里面维护着槽位与实例的关系,那么它的槽位信息怎么在多个实例间同步呢?

Codis把这个工作交给了ZooKeeper来管理,当Codis的Codis Dashbord 改变槽位的信息的时候,其他的Codis节点会监听到ZooKeeper的槽位变化,会及时同步过来。如图:

Codis同步槽位
Codis同步槽位

Codis的优缺点

优点

  • 对客户端透明,与codis交互方式和redis本身交互一样
  • 支持在线数据迁移,迁移过程对客户端透明有简单的管理和监控界面
  • 支持高可用,无论是redis数据存储还是代理节点
  • 自动进行数据的均衡分配
  • 最大支持1024个redis实例,存储容量海量
  • 高性能

缺点

  • 采用自有的redis分支,不能与原版的redis保持同步
  • 如果codis的proxy只有一个的情况下, redis的性能会下降20%左右
  • Codis上是不支持事务的,同时也会有一些命令行不支持,在官方的文档上有(Codis不支持的命令),比如事务命令muti、命令行命令KEYS等
  • 官方的建议是单个集合的总容量不要超过1M,否则在迁移的时候会有卡顿感。在Codis中,增加了proxy来当中转层,所以在网络开销上,是会比单个的Redis节点的性能有所下降的,所以这部分会有些的性能消耗。可以增加proxy的数量来避免掉这块的性能损耗。
  • 国内开源产品,活跃度相对弱一些