Redis集群部署
Redis作为目前最常用的内存NOSQL数据库,使用的场景非常的广泛.但是在3.0以前官方一直都是没有集群的方案的.相当于是一个单机内存数据库.为了其高可用,集群的部署是非常有必要的.因此,各种第三方厂商都推出了自己的集群方案.使用的最多的就是豌豆荚开源的Codis,Twitter开源的Twemproxy,Netflix的Dynamo.
目前Redis是3.0.4版本,其中已经自带了Redis Cluster.但是官方的方案有一些架构上的问题.
- 首先,官方方案是完全的去中心化的,依靠自己Server的网络通信来进行同步.那么,在节点比较多的情况下,性能上是有影响的.
- 其二,一个redis进程既负责读写数据又负责集群交互,虽然设计者已经尽可能简化了代码和逻辑,但还是让redis从一个内存NoSQL变成了一个分布式NoSQL.
- 其三,官方方案没有采用一致性哈希,而是预分配slot的形式来进行分片.新节点的加入不是自动的,依赖于外部的ruby脚本.
- 其四,集群版本和单机版本数据不兼容,客户端不兼容.它的集群分发依赖于客户端的驱动. 目前只有JAVA的
Jedis Driver支持了Redis Cluster的连接.而spring-data-redis目前也还没有支持官方方案.因此我们不能直接调用. - 其五,集群至少要分三片,加上主从备份.也就是说至少需要6个节点才能组建
Redis集群.
从上面可以看出,目前官方的方案.并不适合我们.它现在还不稳定,开源社区的支持也比较少.
从其他三方的方案中进行对比,最后选择Codis作为我们Redis集群部署的方案.
官方集群方案的部署
虽然目前我们不会使用官方的方案,但是不排除以后会使用.毕竟是官方的东西,应该要靠谱些.
-
下载 并编译最新的Redis. 由于Redis是C写的.并且网上只有源码.因此,最好是直接下载源码到
类unix机器上,然后调用sudo make命令自动的编译出可运行的版本. -
最少集群6个节点,因此在我的磁盘上建立一个
redis-test文件夹.然后建立6个子文件夹,作为6个节点.123mkdir redis-testcd redis-testmkdir 7000 7001 7002 7003 7004 7005 -
然后拷贝6分编译好的redis到各个目录中去.
-
修改redis.conf文件.
1234567port 7005pidfile /Volumes/EXCHANGE/redis-test/7000/redis.pidcluster-enabled yes# 和端口对应cluster-config-file nodes.confcluster-node-timeout 5000appendonly yes -
修改好后,进入每一个的src文件夹,执行
./redis-server ../redis.conf启动6个服务. -
随便找一个节点的src目录,找到
redis-trib.rb文件.然后执行:1./redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005其中的
--replicas 1指的是从服务的数量.执行了这句后,会显示出集群的分布情况.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152>>> Creating clusterConnecting to node 127.0.0.1:7000: OKConnecting to node 127.0.0.1:7001: OKConnecting to node 127.0.0.1:7002: OKConnecting to node 127.0.0.1:7003: OKConnecting to node 127.0.0.1:7004: OKConnecting to node 127.0.0.1:7005: OK>>> Performing hash slots allocation on 6 nodes...Using 3 masters:127.0.0.1:7000127.0.0.1:7001127.0.0.1:7002Adding replica 127.0.0.1:7003 to 127.0.0.1:7000Adding replica 127.0.0.1:7004 to 127.0.0.1:7001Adding replica 127.0.0.1:7005 to 127.0.0.1:7002M: d450eaf8b29ccc57c5ab851868a0e23b41d0f50c 127.0.0.1:7000slots:0-5460 (5461 slots) masterM: b4f505a8bfbc58dcd65c0a106f284ae1fe3efe1b 127.0.0.1:7001slots:5461-10922 (5462 slots) masterM: e81eea0243d2976daca5b349ec0bc2d109ac81d0 127.0.0.1:7002slots:10923-16383 (5461 slots) masterS: 52a634c534ca5db005dbc31494676e08454ebfa4 127.0.0.1:7003replicates d450eaf8b29ccc57c5ab851868a0e23b41d0f50cS: 270c10d1f3b85438b74b8fd5c9d91a3e0ce8a0da 127.0.0.1:7004replicates b4f505a8bfbc58dcd65c0a106f284ae1fe3efe1bS: e6eae15e4883cd408fe889e85565a38f6e030de7 127.0.0.1:7005replicates e81eea0243d2976daca5b349ec0bc2d109ac81d0Can I set the above configuration? (type 'yes' to accept): yes>>> Nodes configuration updated>>> Assign a different config epoch to each node>>> Sending CLUSTER MEET messages to join the clusterWaiting for the cluster to join...>>> Performing Cluster Check (using node 127.0.0.1:7000)M: d450eaf8b29ccc57c5ab851868a0e23b41d0f50c 127.0.0.1:7000slots:0-5460 (5461 slots) masterM: b4f505a8bfbc58dcd65c0a106f284ae1fe3efe1b 127.0.0.1:7001slots:5461-10922 (5462 slots) masterM: e81eea0243d2976daca5b349ec0bc2d109ac81d0 127.0.0.1:7002slots:10923-16383 (5461 slots) masterM: 52a634c534ca5db005dbc31494676e08454ebfa4 127.0.0.1:7003slots: (0 slots) masterreplicates d450eaf8b29ccc57c5ab851868a0e23b41d0f50cM: 270c10d1f3b85438b74b8fd5c9d91a3e0ce8a0da 127.0.0.1:7004slots: (0 slots) masterreplicates b4f505a8bfbc58dcd65c0a106f284ae1fe3efe1bM: e6eae15e4883cd408fe889e85565a38f6e030de7 127.0.0.1:7005slots: (0 slots) masterreplicates e81eea0243d2976daca5b349ec0bc2d109ac81d0[OK] All nodes agree about slots configuration.>>> Check for open slots...>>> Check slots coverage...[OK] All 16384 slots covered.
当出现:Can I set the above configuration? (type 'yes' to accept):的时候,输入yes.然后他就会自动的通知各个节点,自发组成集群.
到此,redis集群的官方方案就部署好了.
如果安装过程中出现:/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:55:in require': cannot load such file -- redis (LoadError).那是ruby缺少redis的依赖.
在控制台输入gem install redis即可.
codis集群方案的部署
Codis 是一个分布式 Redis 解决方案, 对于上层的应用来说, 连接到 Codis Proxy 和连接原生的 Redis Server 没有明显的区别.上层应用可以像使用单机的 Redis 一样使用, Codis 底层会处理请求的转发, 不停机的数据迁移等工作, 所有后边的一切事情, 对于前面的客户端来说是透明的, 可以简单的认为后边连接的是一个内存无限大的 Redis 服务.
Codis 由四部分组成:
- Codis Proxy (codis-proxy)
- Codis Manager (codis-config)
- Codis Redis (codis-server)
- ZooKeeper
codis-proxy 是客户端连接的 Redis 代理服务, codis-proxy 本身实现了 Redis 协议, 表现得和一个原生的 Redis 没什么区别 (就像 Twemproxy), 对于一个业务来说, 可以部署多个 codis-proxy, codis-proxy 本身是无状态的.
codis-config 是 Codis 的管理工具, 支持包括, 添加/删除 Redis 节点, 添加/删除 Proxy 节点, 发起数据迁移等操作. codis-config 本身还自带了一个 http server, 会启动一个 dashboard, 用户可以直接在浏览器上观察 Codis 集群的运行状态.
codis-server 是 Codis 项目维护的一个 Redis 分支, 基于 2.8.21 开发, 加入了 slot 的支持和原子的数据迁移指令. Codis 上层的 codis-proxy 和 codis-config 只能和这个版本的 Redis 交互才能正常运行.
Codis 依赖 ZooKeeper 来存放数据路由表和 codis-proxy 节点的元信息, codis-config 发起的命令都会通过 ZooKeeper 同步到各个存活的 codis-proxy.
需要注意的是,codis的proxy是无状态的,当一个分片的master挂掉的时候,codis不会自动的将某个slave升级成master.不过他提供了一个解决方案:codis-ha.这是一个通过codis开放的api实现自动切换主从的工具。该工具会在检测到master挂掉的时候将其下线并选择其中一个slave提升为master继续提供服务。但是只是在每一个分片是一主一从两台的情况下才有效.否则,该分片内其他slave实例是不会自动改变状态的,这些slave仍将试图从旧的master上同步数据,因而会导致分片内新的master和其他slave之间的数据不一致。因为redis的slave of命令切换master时会丢弃slave上的全部数据,从新master完整同步,会消耗master资源。因此建议在知情的情况下手动操作。使用 codis-config server add <group_id> <redis_addr> slave 命令刷新这些节点的状态即可。codis-ha不会自动刷新其他slave的状态。
-
由于codis是由GO语言写的,因此,要运行codis首先需要的就是安装
go语言环境.在类
unix机器上都有现成的安装包可以安装.
比如Macos在终端中输入brew install go即可. (安装过程中需要访问https://go.googlesource.com/tools.git,方法你懂的) -
设置GO的workspace路径.在
~/.bash_profiler下增加export GOPATH="/Volumes/WORKSPACE/openSourceWorkspace/GoWorkspace"注意$GOPATH是本机所有go项目(包括项目依赖的第三方库)的所在目录,而非单纯codis的所在目录。 - 执行下面的命令下载codis源码并编译.它会自动的下载源码以及依赖包.
|
1
2
3
4
|
go get -u -d github.com/wandoulabs/codis
cd $GOPATH/src/github.com/wandoulabs/codis
./bootstrap.sh
make gotest
|
-
执行完命令后,会在codis/bin下生成三个文件
codis-configcodis-proxycodis-server.assets文件夹里面存放的是dashboard服务所需要的静态文件. -
默认情况下 这些命令都会读取
config.ini里面的配置.配置很简单,按照里面的注释改就可以了. - 启动ZK.
- 启动
dashboard,执行./bin/codis-config dashboard,就会启动dashboard - 初始化 slots , 执行
./bin/codis-config slot init,该命令会在zookeeper上创建slot相关信息. - 开始启动
Codis Redis.执行./bin/codis-server,就启动的.这个就和官网的一样. 配置文件也可以跟在后面.比如:./bin/codis-server redis.config -
添加 Redis Server Group , 每一个 Server Group 作为一个 Redis 服务器组存在, 只允许有一个 master, 可以有多个 slave, group id 仅支持大于等于1的整数.这个步骤可以通过
dashboard来增加,也可以使用命令行.比如:1234bin/codis-config server add 1 localhost:6379 masterbin/codis-config server add 1 localhost:6380 slavebin/codis-config server add 2 localhost:6479 masterbin/codis-config server add 2 localhost:6480 slave这样就增加了4个节点,并且分成两片,每片一主一从.
-
设置 server group 服务的 slot 范围 Codis 采用 Pre-sharding 的技术来实现数据的分片, 默认分成 1024 个 slots (0-1023), 对于每个key来说, 通过以下公式确定所属的 Slot Id : SlotId = crc32(key) % 1024 每一个 slot 都会有一个且必须有一个特定的 server group id 来表示这个 slot 的数据由哪个 server group 来提供.
12$ bin/codis-config slot range-set 0 511 1 online$ bin/codis-config slot range-set 512 1023 2 online同样,可以在界面上进行操作
-
启动 codis-proxy (注意,如果zk的session时间设置太短的话,proxy可能启动不起来.)
1bin/codis-proxy -c config.ini -L ./log/proxy.log --cpu=8 --addr=0.0.0.0:19000 --http-addr=0.0.0.0:11000
到此就集群完毕.
-
但是为了能在master当机的时候自动的升级slave,这就需要codis-ha了.这个同样是
go语言写的.所以直接在终端中输入:1234go get github.com/ngaut/codis-hacd codis-hago buildcodis-ha --codis-config=localhost:18087 --productName=test就搞定了,他会自动的监控dashboard,然后发现节点不正确后,调用restful的接口,提升slave为master
接下来就是客户端的调用了.
由于codis依赖了zk作为服务的发现方.因此,整个集群的节点状态都是在zk中有的.
它自身也提供了一个JAVA的实现,叫jodis.通过这个,就可以关联jedis Driver.并且获取当前可用的codis-server.
不过目前这个jodis还没有提供与spring的集成.这个需要我们自己来开发.

浙公网安备 33010602011771号