背景
redis cluster 是基于redis3.0出的redis 集群架构,从网上down 了一张图可以比较清晰的说明redis cluster的工作方式:
- 有几点比较重要,redis cluster 内部使用二进制协议优化传输速度和带宽。
- 节点是否fail 是根据半数以上的node 投票决定的。
- 客户端与redis节点直连,理论上随便选个端口和IP就能连接
- redis cluster是将所有node 映射到16383 个solt 上。
此外基本条件必须满足3+3的模式,也就是说集群最少也必须要有3主3从的redis 才能构建,另外redis所在服务器需要安装配置ruby。搭建redis cluster前需要把redis 老的数据清空,每台必须都执行flushall。
搭建配置
测试环境在debian下搭建配置,用了最简单的3+3的架构,分别分布在3台服务器上,每个服务器2个redis 实例。
redis-server 10.1.99.163:7011
redis-server 10.1.99.163:7012
redis-server 10.1.99.164:7013
redis-server 10.1.99.164:7014
redis-server 10.1.99.165:7015
redis-server 10.1.99.165:7016
redis 版本使用的3.02 stable 。
1.安装组建:
apt-get install ruby
gem install redis #gem 是ruby的一个打包工具
然后下载编译安装redis ,过程老样子,不复述了。
修改redis 配置文件,除了端口和bind 地址需要修改外,主要需要打开redis 集群的开关配置:
cluster-enabled yes #打开redis cluster
cluster-config-file nodes_7012.conf #这个文件在redis 集群启动后会自己生成 ,里面记录的是redis的集群节点信息
647 cluster-node-timeout 15000 #超时时间
然后一样,依次启动6个redis 实例。
root 9121 5757 0 19:45 pts/1 00:00:11 redis-server 10.1.99.163:7011 [cluster]
每个redis进程后会都带一个cluster 的标识。
此时6个redis 都是单独的redis 实例,然后在运行
redis-trib.rb create --replicas 1 10.1.99.163:7011 10.1.99.163:7012 10.1.99.164:7013 10.1.99.164:7014 10.1.99.165:7015 10.1.99.165:7016
redis-trib.rb 是管理redis集群的一个脚本,检查,添加,删除节点都可以使用该脚本:
root@:redis-3.0.2# redis-trib.rb help
Usage: redis-trib
create host1:port1 ... hostN:portN
--replicas
check host:port
fix host:port
reshard host:port
--from
--to
--slots
--yes
add-node new_host:new_port existing_host:existing_port
--slave
--master-id
del-node host:port node_id
set-timeout host:port milliseconds
call host:port command arg arg .. arg
import host:port
--from
help (show this help)
For check, fix, reshard, del-node, set-timeout you can specify the host and port of any working node in the cluster.
运行该脚本后,会生成redis的集群,同样可以使用该脚本进行检查
root@:redis-3.0.2# redis-trib.rb check 10.1.99.163:7011
Connecting to node 10.1.99.163:7011: OK
Connecting to node 10.1.99.164:7014: OK
Connecting to node 10.1.99.165:7016: OK
Connecting to node 10.1.99.164:7013: OK
Connecting to node 10.1.99.163:7012: OK
Connecting to node 10.1.99.165:7015: OK
>>> Performing Cluster Check (using node 10.1.99.163:7011)
M: 2db3baa186f7530e12f48049b81ede908616896b 10.1.99.163:7011
slots:0-5460 (5461 slots) master
1 additional replica(s)
S: 1f747e75d5eb2be8a23d52544c7f70c22fb3765a 10.1.99.164:7014
slots: (0 slots) slave
replicates 2db3baa186f7530e12f48049b81ede908616896b
S: 17616b78741a3d5748dedfc556c23da7823fa924 10.1.99.165:7016
slots: (0 slots) slave
replicates fe26cc474c10ee2b94e926a53d9270cb5777cef1
M: 5a55e25026ce1c9941220320b096f3854bf4038c 10.1.99.164:7013
slots:5461-10922 (5462 slots) master
1 additional replica(s)
S: 8ffcbd674da0bdf51ad1963a5612309693d8066d 10.1.99.163:7012
slots: (0 slots) slave
replicates 5a55e25026ce1c9941220320b096f3854bf4038c
M: fe26cc474c10ee2b94e926a53d9270cb5777cef1 10.1.99.165:7015
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.
哪些是slave ,哪些是master 一目了然。此时不出意外的话redis cluster 集群已经在工作了。连接随便一个redis node 查看相关信息:
root@:redis-3.0.2# redis-cli -c -h 10.1.99.163 -p 7011
10.1.99.163:7011> cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:1
cluster_stats_messages_sent:14371
cluster_stats_messages_received:14371
10.1.99.163:7011> cluster nodes
1f747e75d5eb2be8a23d52544c7f70c22fb3765a 10.1.99.164:7014 slave 2db3baa186f7530e12f48049b81ede908616896b 0 1488807713360 4 connected
17616b78741a3d5748dedfc556c23da7823fa924 10.1.99.165:7016 slave fe26cc474c10ee2b94e926a53d9270cb5777cef1 0 1488807711357 6 connected
5a55e25026ce1c9941220320b096f3854bf4038c 10.1.99.164:7013 master - 0 1488807714363 3 connected 5461-10922
8ffcbd674da0bdf51ad1963a5612309693d8066d 10.1.99.163:7012 slave 5a55e25026ce1c9941220320b096f3854bf4038c 0 1488807715367 3 connected
fe26cc474c10ee2b94e926a53d9270cb5777cef1 10.1.99.165:7015 master - 0 1488807712358 5 connected 10923-16383
2db3baa186f7530e12f48049b81ede908616896b 10.1.99.163:7011 myself,master - 0 0 1 connected 0-5460
10.1.99.163:7011>
此时验证redis cluster 是否正常工作,登录7011端口实例,查看对应主从信息:
10.1.99.163:7011> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=10.1.99.164,port=7014,state=online,offset=9629,lag=1
master_repl_offset:9629
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:9628
他是主,从是7014实例。然后插入一条数据:
10.1.99.163:7011> set barney redis
OK
10.1.99.163:7011> keys *
1) "barney"
10.1.99.163:7011> get barney
"redis"
10.1.99.163:7011>
插入后发现有对应的key 以及value,然后登录该master 对应的salve 7014 进行查看:
10.1.99.164:7014> keys *
1) "barney"
10.1.99.164:7014> get barney
-> Redirected to slot [5059] located at 10.1.99.163:7011
"redis"
10.1.99.163:7011>
该势中能找到对应的keys 但是get value的时候session 去跳到了7011 上,然后再登录其他node 进行检查。
10.1.99.163:7012> keys *
(empty list or set)
10.1.99.163:7012> get barney
-> Redirected to slot [5059] located at 10.1.99.163:7011
"redis"
10.1.99.163:7011>
可以看到,再其他node 上无法通过类似keys * 来查到所有node 上的key值,但是直接取值的话是可以取到的,但是需要跳转到对应端口的node的session 上。同理删除操作也一样。
那么这样的话,当7011实例挂了会如何,手动kill 这个进程。
然后经过大约30秒左右,发现7011的从节点变为了主:
10.1.99.164:7014> info replication
# Replication
role:master
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
说明此时redis cluster 重新将他推举为新的master:
root@:redis-3.0.2# redis-cli -c -h 10.1.99.163 -p 7012
10.1.99.163:7012> keys *
(empty list or set)
10.1.99.163:7012> get barney
(error) CLUSTERDOWN The cluster is down
10.1.99.163:7012> 9124:S 06 Mar 21:54:53.573 # Cluster state changed: ok
10.1.99.163:7012> get barney
-> Redirected to slot [5059] located at 10.1.99.164:7014
"redis"
10.1.99.164:7014>
然后重新启动挂掉的redis node ,redis cluster 会将盖节点重新加入集群,但此时已经变为slave 了。
附上一些常用的redis cluster cli 命令
CLUSTER INFO 打印集群的信息
CLUSTER NODES 列出集群当前已知的所有节点(node),以及这些节点的相关信息。
节点
CLUSTER MEET 将 ip 和 port 所指定的节点添加到集群当中,让它成为集群的一份子。
CLUSTER FORGET 从集群中移除 node_id 指定的节点。
CLUSTER REPLICATE 将当前节点设置为 node_id 指定的节点的从节点。
CLUSTER SAVECONFIG 将节点的配置文件保存到硬盘里面。
槽(slot)
CLUSTER ADDSLOTS [slot ...] 将一个或多个槽(slot)指派(assign)给当前节点。
CLUSTER DELSLOTS [slot ...] 移除一个或多个槽对当前节点的指派。
CLUSTER FLUSHSLOTS 移除指派给当前节点的所有槽,让当前节点变成一个没有指派任何槽的节点。
CLUSTER SETSLOT NODE 将槽 slot 指派给 node_id 指定的节点,如果槽已经指派给另一个节点,那么先让另一个节点删除该槽>,然后再进行指派。
CLUSTER SETSLOT MIGRATING 将本节点的槽 slot 迁移到 node_id 指定的节点中。
CLUSTER SETSLOT IMPORTING 从 node_id 指定的节点中导入槽 slot 到本节点。
CLUSTER SETSLOT STABLE 取消对槽 slot 的导入(import)或者迁移(migrate)。
键
CLUSTER KEYSLOT 计算键 key 应该被放置在哪个槽上。
CLUSTER COUNTKEYSINSLOT 返回槽 slot 目前包含的键值对数量。
CLUSTER GETKEYSINSLOT 返回 count 个 slot 槽中的键。