近几年,随着互联网的飞速发展,作为程序员,我们需要处理的数据规模也在不断扩大。如果你使用Redis作为数据库时,面临大数据高并发的场景时,单个Redis实例就会显得力不从心。这时Redis的集群方案应运而生,他将众多Redis实例综合起来,共同应对大数据高并发的场景。
Codis是Redis集群方案的一种。它是由豌豆荚的中间件团队开发的,所以,它有一套详细的中文版README,方便大家学习。
它的架构如上图所示,由codis-proxy对外提供Redis的服务。ZooKeeper用来存储数据路由表和codis-proxy节点的元信息。codis-proxy会监听所有的redis集群,当Redis集群处理能力达到上限时,可以动态增加Redis实例来实现扩容的需求。
组件介绍
- Codis Proxy:像刚才所说的,它对外提供Redis服务,除了一些不支持的命令外(不支持的命令列表),表现的和原生的Redis没有区别。由于它是无状态的,所以我们可以部署多个节点,从而保证了可用性。
- Codis Dashboard:集群管理工具,支持Codis Proxy的添加删除以及数据迁移等操作。对于一个Codis集群,Dashboard最多部署一个
- Codis Admin:集群管理的命令行工具
- Codis FE:集群管理界面,多个Codis集群可以共用一个Codis FE,通过配置文件管理后端的codis-dashboard
- Storage:为集群提供外部存储,目前支持ZooKeeper、Etcd、Fs三种。
- Codis Server:基于3.2.8分支开发,增加额外的数据结构,用来支持slot有关的操作及数据迁移指令。
Codis分片原理
现在我们已经知道了Codis会将指定key的Redis命令转发给下层的Redis。那么Codis如何知道某个key在哪个Redis上呢。
Codis采用Pre-sharding的技术来实现数据分片,默认分为1024个slot(0-1023)。Codis在接收到命令时,先对key进行crc32运算,然后再对1024取余,得到的结果就是对应的slot。然后就可以将命令转发给slot对应的Redis实例进行处理了。
扩容操作
Codis的动态扩容/缩容能力是它的一大亮点之一。它可以对Redis客户端透明。在扩容时,Codis提供了SLOTSSCAN指令,这个指令可以扫描指定的slot上的所有key,然后对每个key进行迁移。在扩容过程中,如果有新的key需要转发到正在迁移的slot上,那么codis会判断这个key是否需要迁移,如果需要,则对指定的key进行强制迁移,迁移完成后,再将命令转发到新的Redis上。
看了上面的介绍是不是觉得扩容是一件很麻烦的事情,Codis已经为我们考虑到这点了,它提供了自动均衡的功能,只需要在界面上点一下”Auto Rebalance”按钮,就可以自动实现slot迁移(可以说非常贴心了)。缩容也比较简单,只需要将需要下线的实例的slot迁移到其他实例上,然后删除group就可以了。
Codis的缺点
当Redis Group的master挂掉时,codis不会自动将某个slave升为master,codis提供了一个叫做codis-ha的工具,这个工具通过dashboard提供RESTful API来实现自动主从切换。但是,当codis将某个slave升为master时,其他的slave并不会改变状态,仍然会从旧的master上同步数据,这就导致了主从数据不一致。因此,当出现主从切换时,需要管理员手动创建新的sync action来完成数据同步。
此外,Codis还面临一个比较尴尬的情况就是,由于它不是Redis“亲生”的,因此,当Redis发布了new feature时,它总会慢一步,因此,它需要在Redis发布new feature后迅速赶上,以保持竞争力。
搭建Codis
- 安装Go运行环境
安装好以后,验证一下是否安装成功
1 | $ go version |
- 下载Codis源码
需要下载到指定目录:$GOPATH/src/github.com/CodisLabs/codis
1 | $ mkdir -p $GOPATH/src/github.com/CodisLabs |
- 编译源码
进入源码的codis目录,直接执行make命令即可。编译完成后,bin目录下的结构应该是这样的
1 | $ ll bin |
到这里为止,我们的准备工作已经完成了。接下来我们来看一下如何在单机环境启动测试集群。
- 启动codis-dashboard
进入admin目录,执行codis-dashboard-admin.sh脚本
1 | $ ./codis-dashboard-admin.sh start |
然后查看日志,观察是否启动成功
1 | $ tail -100 ../log/codis-dashboard.log.2018-11-21 |
- 启动codes-proxy
执行codis-proxy-admin.sh脚本
1 | $ ./codis-proxy-admin.sh start |
查看是否启动成功
1 | $ tail -100 ../log/codis-proxy.log.2018-11-21 |
- 启动codis-server
执行codis-server-admin.sh脚本
1 | $ ./codis-server-admin.sh start |
查看是否启动成功
1 | $ tail -100 /tmp/redis_6379.log |
如果执行报错,请先确认使用的用户是否有/tmp/redis_6379.log文件的读写权限。
这里我为了测试Codis的Auto Rebalance功能,所以启动了两个实例。方法很简单,只需要分别将admin/codis-server-admin.sh和config/redis.conf这两个文件复制一份,修改文件中的端口等信息,然后再以同样的方法执行一下新的脚本。
- 启动codis-fe
执行codis-fe-admin.sh脚本
1 | $ ./codis-fe-admin.sh start |
查看是否执行成功
1 | $ tail -100 ../log/codis-fe.log.2018-11-21 |
全部启动成功之后,就可以访问http://127.0.0.1:9090,开始设置集群了。
- 添加group
刚刚我们启动了两个codis-server,因此,我们可以new两个group,然后分别将codis-server加入到两个group中
- 初始化slot
一开始所有的slot都是offline状态。
点击下方的Rebalance All Slots按钮,codis会自动把1024个slot分配给两个group(每个分512个)。
当然,也可以手动分配slot,比如,我们将group-1的10个slot分配给group-2,只需要点击Migrate Some按钮即可。
小结
Codis的动态扩容能力简直好用到爆 ,不过目前也存在一些问题(前面我们也介绍过了)。所以你的集群是否要使用Codis还需要看具体的需求。最后还是要为Codis的开发团队点赞,另外他们还开发出了一套分布式数据库——TiDB。有兴趣的同学可以学习一下。