Redis Cluster终于出了Stable,这让人很是激动,等Stable很久了,所以还是先玩玩。
Redis 集群是一个可以在多个 Redis 节点之间进行数据共享的设施(installation)。
Redis 集群不支持那些需要同时处理多个键的 Redis 命令, 因为执行这些命令需要在多个 Redis 节点之间移动数据, 并且在高负载的情况下, 这些命令将降低 Redis 集群的性能, 并导致不可预测的行为。
Redis 集群通过分区(partition)来提供一定程度的可用性(availability): 即使集群中有一部分节点失效或者无法进行通讯, 集群也可以继续处理命令请求。
Redis 集群提供了以下两个好处:
Redis 集群使用数据分片(sharding)而非一致性哈希(consistency hashing)来实现: 一个 Redis 集群包含 16384 个哈希槽(hash slot), 数据库中的每个键都属于这 16384 个哈希槽的其中一个, 集群使用公式 CRC16(key) % 16384 来计算键 key 属于哪个槽, 其中 CRC16(key) 语句用于计算键 key 的 CRC16 校验和 。
集群中的每个节点负责处理一部分哈希槽。 举个例子, 一个集群可以有三个哈希槽, 其中:
这种将哈希槽分布到不同节点的做法使得用户可以很容易地向集群中添加或者删除节点。 比如说:
因为将一个哈希槽从一个节点移动到另一个节点不会造成节点阻塞, 所以无论是添加新节点还是移除已存在节点, 又或者改变某个节点包含的哈希槽数量, 都不会造成集群下线。
为了使得集群在一部分节点下线或者无法与集群的大多数(majority)节点进行通讯的情况下, 仍然可以正常运作, Redis 集群对节点使用了主从复制功能: 集群中的每个节点都有 1 个至 N 个复制品(replica), 其中一个复制品为主节点(master), 而其余的 N-1 个复制品为从节点(slave)。
在之前列举的节点 A 、B 、C 的例子中, 如果节点 B 下线了, 那么集群将无法正常运行, 因为集群找不到节点来处理 5501 号至 11000号的哈希槽。
另一方面, 假如在创建集群的时候(或者至少在节点 B 下线之前), 我们为主节点 B 添加了从节点 B1 , 那么当主节点 B 下线的时候, 集群就会将 B1 设置为新的主节点, 并让它代替下线的主节点 B , 继续处理 5501 号至 11000 号的哈希槽, 这样集群就不会因为主节点 B 的下线而无法正常运作了。
不过如果节点 B 和 B1 都下线的话, Redis 集群还是会停止运作。
架构图如下:
架构细节:
(1)所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽.
(2)节点的fail是通过集群中超过半数的节点检测失效时才生效.
(3)客户端与redis节点直连,不需要中间proxy层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可
(4)redis-cluster把所有的物理节点映射到[0-16383]slot上,cluster负责维护node<->slot<->value
要让集群正常工作至少需要3个主节点,在这里我们要创建6个redis节点,其中三个为主节点,三个为从节点,对应的redis节点的ip和端口对应关系如下(为了简单演示都在同一台机器上面)
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
wget http://download.redis.io/releases/redis-3.0.0.tar.gz
tar xf redis-3.0.0.tar.gz cd redis-3.0.0 make && make install
mkdir /data/cluster -p cd /data/cluster mkdir 7000 7001 7002 7003 7004 7005
cp redis-3.0.0/redis.conf /data/cluster/7000/
修改配置文件中下面选项
port 7000 daemonize yes cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes
文件中的 cluster-enabled 选项用于开实例的集群模式, 而 cluster-conf-file 选项则设定了保存节点配置文件的路径, 默认值为nodes.conf 。其他参数相信童鞋们都知道。节点配置文件无须人为修改, 它由 Redis 集群在启动时创建, 并在有需要时自动进行更新。
修改完成后,把修改完成的redis.conf复制到7001-7005目录下,并且端口修改成和文件夹对应。
查看进程否存在。
首先安装依赖,否则创建集群失败。
yum install ruby rubygems -y
安装gem-redis
下载地址:https://rubygems.org/gems/redis/versions/3.0.0
gem install redis -v 3.0.0
复制集群管理程序到/usr/local/bin
cp redis-3.0.0/src/redis-trib.rb /usr/local/bin/redis-trib
创建集群:
redis-trib 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
命令的意义如下:
简单来说, 以上命令的意思就是让 redis-trib 程序创建一个包含三个主节点和三个从节点的集群。
接着, redis-trib 会打印出一份预想中的配置给你看, 如果你觉得没问题的话, 就可以输入 yes , redis-trib 就会将这份配置应用到集群当中:
输入 yes 并按下回车确认之后, 集群就会将配置应用到各个节点, 并连接起(join)各个节点 —— 也即是, 让各个节点开始互相通讯:
一切正常输出以下信息:
[OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered.
Redis 集群现阶段的一个问题是客户端实现很少。 以下是一些我知道的实现:
集群比较简单的办法就是使用 redis-rb-cluster 或者 redis-cli , 接下来我们将使用 redis-cli 为例来进行演示:
[root@redis-server ~]# redis-cli -c -p 7001 127.0.0.1:7001> set name yayun OK 127.0.0.1:7001> get name "yayun" 127.0.0.1:7001>
我们可以看看还有哪些命令可以用:
可以看见有add-node,不用想了,肯定是添加节点。那么del-node就是删除节点。还有check肯定就是检查状态了。
检查集群,我们通过check cluster的一个节点,就知道整个集群的状况,可以看出来哪些节点是主,哪些是从。由上可以看到7000-7002是master,7003-7005是slave。
[root@redis-cluster-yang 7001]# redis-trib del-node 127.0.0.1:7001 '518a8abc4a64578a51323492a8c79c29a1354f4f' >>> Removing node 518a8abc4a64578a51323492a8c79c29a1354f4f from cluster 127.0.0.1:7001 Connecting to node 127.0.0.1:7001: OK Connecting to node 127.0.0.1:7004: OK Connecting to node 127.0.0.1:7000: OK Connecting to node 127.0.0.1:7005: OK Connecting to node 127.0.0.1:7002: OK Connecting to node 127.0.0.1:7003: OK >>> Sending CLUSTER FORGET messages to the cluster... >>> SHUTDOWN the node. [root@redis-cluster-yang 7001]# redis-trib check 127.0.0.1:7000 Connecting to node 127.0.0.1:7000: OK Connecting to node 127.0.0.1:7005: OK Connecting to node 127.0.0.1:7003: OK Connecting to node 127.0.0.1:7004: OK Connecting to node 127.0.0.1:7002: OK >>> Performing Cluster Check (using node 127.0.0.1:7000) M: 9c12c07dfbf10e56fea928ff7125f095b28a99d7 127.0.0.1:7000 slots:0-5460 (5461 slots) master 1 additional replica(s) S: 85dde9c952d3a6ffa7fbfe733734bc3a9113091c 127.0.0.1:7005 slots: (0 slots) slave replicates d666a74d5bfce0d0cdeaab26fec4a1bed8beae62 S: cda1b9a0e4242188f3296ed8d3ff0dbe5388dcb7 127.0.0.1:7003 slots: (0 slots) slave replicates 9c12c07dfbf10e56fea928ff7125f095b28a99d7 M: b59cfdc50d347695d5fa22ac0a2f10a4c1b398a7 127.0.0.1:7004 slots:5461-10922 (5462 slots) master 0 additional replica(s) M: d666a74d5bfce0d0cdeaab26fec4a1bed8beae62 127.0.0.1:7002 slots:10923-16383 (5461 slots) master 1 additional replica(s) [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered.
[root@redis-cluster-yang 7001]# redis-trib check 127.0.0.1:7004 Connecting to node 127.0.0.1:7004: OK Connecting to node 127.0.0.1:7000: OK Connecting to node 127.0.0.1:7002: OK Connecting to node 127.0.0.1:7005: OK Connecting to node 127.0.0.1:7003: OK >>> Performing Cluster Check (using node 127.0.0.1:7004) M: b59cfdc50d347695d5fa22ac0a2f10a4c1b398a7 127.0.0.1:7004 slots:5461-10922 (5462 slots) master 0 additional replica(s) M: 9c12c07dfbf10e56fea928ff7125f095b28a99d7 127.0.0.1:7000 slots:0-5460 (5461 slots) master 1 additional replica(s) M: d666a74d5bfce0d0cdeaab26fec4a1bed8beae62 127.0.0.1:7002 slots:10923-16383 (5461 slots) master 1 additional replica(s) S: 85dde9c952d3a6ffa7fbfe733734bc3a9113091c 127.0.0.1:7005 slots: (0 slots) slave replicates d666a74d5bfce0d0cdeaab26fec4a1bed8beae62 S: cda1b9a0e4242188f3296ed8d3ff0dbe5388dcb7 127.0.0.1:7003 slots: (0 slots) slave replicates 9c12c07dfbf10e56fea928ff7125f095b28a99d7 [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered. [root@redis-cluster-yang 7001]# redis-trib add-node 127.0.0.1:7001 127.0.0.1:7004 >>> Adding node 127.0.0.1:7001 to cluster 127.0.0.1:7004 Connecting to node 127.0.0.1:7004: OK Connecting to node 127.0.0.1:7000: OK Connecting to node 127.0.0.1:7002: OK Connecting to node 127.0.0.1:7005: OK Connecting to node 127.0.0.1:7003: OK >>> Performing Cluster Check (using node 127.0.0.1:7004) M: b59cfdc50d347695d5fa22ac0a2f10a4c1b398a7 127.0.0.1:7004 slots:5461-10922 (5462 slots) master 0 additional replica(s) M: 9c12c07dfbf10e56fea928ff7125f095b28a99d7 127.0.0.1:7000 slots:0-5460 (5461 slots) master 1 additional replica(s) M: d666a74d5bfce0d0cdeaab26fec4a1bed8beae62 127.0.0.1:7002 slots:10923-16383 (5461 slots) master 1 additional replica(s) S: 85dde9c952d3a6ffa7fbfe733734bc3a9113091c 127.0.0.1:7005 slots: (0 slots) slave replicates d666a74d5bfce0d0cdeaab26fec4a1bed8beae62 S: cda1b9a0e4242188f3296ed8d3ff0dbe5388dcb7 127.0.0.1:7003 slots: (0 slots) slave replicates 9c12c07dfbf10e56fea928ff7125f095b28a99d7 [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered. Connecting to node 127.0.0.1:7001: OK [ERR] Node 127.0.0.1:7001 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0.
[root@redis-cluster-yang 7001]# redis-trib add-node 127.0.0.1:7001 127.0.0.1:7004 >>> Adding node 127.0.0.1:7001 to cluster 127.0.0.1:7004 Connecting to node 127.0.0.1:7004: OK Connecting to node 127.0.0.1:7000: OK Connecting to node 127.0.0.1:7002: OK Connecting to node 127.0.0.1:7005: OK Connecting to node 127.0.0.1:7003: OK >>> Performing Cluster Check (using node 127.0.0.1:7004) M: b59cfdc50d347695d5fa22ac0a2f10a4c1b398a7 127.0.0.1:7004 slots:5461-10922 (5462 slots) master 0 additional replica(s) M: 9c12c07dfbf10e56fea928ff7125f095b28a99d7 127.0.0.1:7000 slots:0-5460 (5461 slots) master 1 additional replica(s) M: d666a74d5bfce0d0cdeaab26fec4a1bed8beae62 127.0.0.1:7002 slots:10923-16383 (5461 slots) master 1 additional replica(s) S: 85dde9c952d3a6ffa7fbfe733734bc3a9113091c 127.0.0.1:7005 slots: (0 slots) slave replicates d666a74d5bfce0d0cdeaab26fec4a1bed8beae62 S: cda1b9a0e4242188f3296ed8d3ff0dbe5388dcb7 127.0.0.1:7003 slots: (0 slots) slave replicates 9c12c07dfbf10e56fea928ff7125f095b28a99d7 [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered. Connecting to node 127.0.0.1:7001: OK >>> Send CLUSTER MEET to node 127.0.0.1:7001 to make it join the cluster. [OK] New node added correctly.
默认add-node是添加主master节点,确认一下新添加的节点为master角色了。哈可以通过使用redis-trib.rb add-node –slave –master-id master-id 给指定的redis master节点添加从节点。
[root@redis-cluster-yang 7001]# redis-trib check 127.0.0.1:7000 Connecting to node 127.0.0.1:7000: OK Connecting to node 127.0.0.1:7005: OK Connecting to node 127.0.0.1:7003: OK Connecting to node 127.0.0.1:7004: OK Connecting to node 127.0.0.1:7001: OK Connecting to node 127.0.0.1:7002: OK >>> Performing Cluster Check (using node 127.0.0.1:7000) M: 9c12c07dfbf10e56fea928ff7125f095b28a99d7 127.0.0.1:7000 slots:0-5460 (5461 slots) master 1 additional replica(s) S: 85dde9c952d3a6ffa7fbfe733734bc3a9113091c 127.0.0.1:7005 slots: (0 slots) slave replicates d666a74d5bfce0d0cdeaab26fec4a1bed8beae62 S: cda1b9a0e4242188f3296ed8d3ff0dbe5388dcb7 127.0.0.1:7003 slots: (0 slots) slave replicates 9c12c07dfbf10e56fea928ff7125f095b28a99d7 M: b59cfdc50d347695d5fa22ac0a2f10a4c1b398a7 127.0.0.1:7004 slots:5461-10922 (5462 slots) master 0 additional replica(s) M: 96f7aeaa57bf974be8eac4df54deeb96b66ff689 127.0.0.1:7001 slots: (0 slots) master 0 additional replica(s) M: d666a74d5bfce0d0cdeaab26fec4a1bed8beae62 127.0.0.1:7002 slots:10923-16383 (5461 slots) master 1 additional replica(s) [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered.
redis-trib reshard 127.0.0.1:7000你只需要指定集群中其中一个节点的地址,
redis-trib
就会自动找到集群中的其他节点。
How many slots do you want to move (from 1 to 16384)? 4000
除了移动的哈希槽数量之外,redis-trib
还需要知道重新分片的目标(target node),也即是,负责接收这些
哈希槽的节点。指定目标需要使用节点的 ID ,而不是 IP 地址和端口
Please enter all the source node IDs. Type 'all' to use all the nodes as source nodes for the hash slots. Type 'done' once you entered all the source nodes IDs. Source node #1:all
输入 all
并按下回车之后,redis-trib
将打印出哈希槽的移动计划,如果你觉得没问题的话,就可以输入yes
并再次按下回车:
$ ./redis-trib.rb reshard 127.0.0.1:7000 ... Moving slot 11421 from 393c6df5eb4b4cec323f0e4ca961c8b256e3460a Moving slot 11422 from 393c6df5eb4b4cec323f0e4ca961c8b256e3460a Moving slot 5461 from e68e52cee0550f558b03b342f2f0354d2b8a083b Moving slot 5469 from e68e52cee0550f558b03b342f2f0354d2b8a083b ... Moving slot 5959 from e68e52cee0550f558b03b342f2f0354d2b8a083b Do you want to proceed with the proposed reshard plan (yes/no)? yes确认分片后集群是否正常
[root@redis-cluster-yang 7001]# redis-trib check 127.0.0.1:7000 Connecting to node 127.0.0.1:7000: OK Connecting to node 127.0.0.1:7005: OK Connecting to node 127.0.0.1:7003: OK Connecting to node 127.0.0.1:7004: OK Connecting to node 127.0.0.1:7001: OK Connecting to node 127.0.0.1:7002: OK >>> Performing Cluster Check (using node 127.0.0.1:7000) M: 9c12c07dfbf10e56fea928ff7125f095b28a99d7 127.0.0.1:7000 slots:1333-5460 (4128 slots) master 1 additional replica(s) S: 85dde9c952d3a6ffa7fbfe733734bc3a9113091c 127.0.0.1:7005 slots: (0 slots) slave replicates d666a74d5bfce0d0cdeaab26fec4a1bed8beae62 S: cda1b9a0e4242188f3296ed8d3ff0dbe5388dcb7 127.0.0.1:7003 slots: (0 slots) slave replicates 9c12c07dfbf10e56fea928ff7125f095b28a99d7 M: b59cfdc50d347695d5fa22ac0a2f10a4c1b398a7 127.0.0.1:7004 slots:6795-10922 (4128 slots) master 0 additional replica(s) M: 96f7aeaa57bf974be8eac4df54deeb96b66ff689 127.0.0.1:7001 slots:0-1332,5461-6794,10923-12255 (4000 slots) master 0 additional replica(s) M: d666a74d5bfce0d0cdeaab26fec4a1bed8beae62 127.0.0.1:7002 slots:12256-16383 (4128 slots) master 1 additional replica(s) [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered.
127.0.0.1:7001> KEYS * 1) "name" 127.0.0.1:7001> get name "yayun" 127.0.0.1:7001>
可以看见7001是正常的,并且获取到了key,value,现在kill掉7000实例,再进行查询。
可以正常获取到value,现在看看状态。
原来的7000端口实例已经显示fail,原来的7003是slave,现在自动提升为master。
关于更多的在线添加节点,删除节点,以及对集群进行重新分片请参考官方文档。
redis-cluster是个好东西,只是stable才出来不久,肯定坑略多,而且现在使用的人比较少,前期了解学习一下是可以的,生产环境肯定要慎重考虑。且需要进行严格的测试。生产环境中redis的集群可以考虑使用Twitter开源的twemproxy,以及豌豆荚开源的codis,这两个项目都比较成熟,现在使用的公司很多。已经向业界朋友得到证实。后面也会写博客介绍twemproxy和codis。
参考资料:
http://redis.readthedocs.org/en/latest/topic/cluster-tutorial.html
http://hot66hot.iteye.com/blog/2050676
http://redisdoc.com/topic/cluster-tutorial.html
http://xiaorui.cc/2015/05/16/%E9%80%9A%E8%BF%87redis-trib-rb%E8%84%9A%E6%9C%AC%E6%9E%84%E5%BB%BA%E5%B9%B6%E5%A2%9E%E5%88%A0%E6%94%B9%E6%9F%A5redis-cluster%E9%9B%86%E7%BE%A4/
作者:Atlas
出处:Atlas的博客 http://www.cnblogs.com/gomysql
您的支持是对博主最大的鼓励,感谢您的认真阅读。本文版权归作者所有,欢迎转载,但请保留该声明。