1. redis环境
下载redis工具包和源代码
https://github.com/microsoftarchive/redis/releases
redis-trib.rb在源码的src目录下,后面需要用到
2. ruby环境
redis的集群创建工具redis-trib.rb需要ruby环境才能运行,windows安装包如下,安装时勾选添加的环境变量
下载ruby安装文件
(windows)62位:rubyinstaller-2.3.3-x64.exe
(windows)32位:rubyinstaller-2.3.3.exe
能显示如下即安装完成
#ruby -v ruby 2.3.3p222 (2016-11-21 revision 56859) [x64-mingw32] #gem -v 2.5.2
下载ruby的redis依赖
使用gem命令完成安装
#gem install -l redis-3.3.0.gem
现在redis-trib.rb已经能正常运行
#ruby redis-trib.rb sage: redis-trib <command> <options> <arguments ...> create host1:port1 ... hostN:portN --replicas <arg> check host:port fix host:port reshard host:port --from <arg> --to <arg> --slots <arg> --yes add-node new_host:new_port existing_host:existing_port --slave --master-id <arg> del-node host:port node_id set-timeout host:port milliseconds call host:port command arg arg .. arg import host:port --from <arg> --copy --replace 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.
3.集群搭建
创建集群前准备
准备搭建3主节点A、B、C,每个主节点都有一个备用节点A1、B2、C3,总共6个节点。由于条件有限,用一个主机模拟6个节点,需要6个不同端口号7000,7001,7002,7003,7004,7005
创建目录cluster,在其下面创建7000-7005六个目录用于表示6个节点
└─cluster ├─7000 ├─7001 ├─7002 ├─7003 ├─7004 └─7005
将redis-server.exe拷贝的cluster目录下
这是集群需要最小redis.conf配置文件
port 7000 cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes
在7000-7005目录下创建redis.conf,配置如上,但是端口号要和目录名一样
在每个目录下运行..\redis-server redis.conf,这样就已经运行了6个redis实例
创建集群
使用redis集群命令行工具redis-trib.rb创建集群
ruby 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
命令解释:create表示要创建一个新的集群,--replicas 1表示为每个主节点创建一个从节点,后面的就是实例列表
16384个槽都有至少一个主节点在处理,现在集群已经创建好了,可以用client连接看一下效果
# redis-cli -c -p 7000 127.0.0.1:7000> 127.0.0.1:7000> set name pengliangyuan -> Redirected to slot [5798] located at 127.0.0.1:7001 OK 127.0.0.1:7001> set age 25 -> Redirected to slot [741] located at 127.0.0.1:7000 OK 127.0.0.1:7000> get name -> Redirected to slot [5798] located at 127.0.0.1:7001 "pengliangyuan" 127.0.0.1:7001> get age -> Redirected to slot [741] located at 127.0.0.1:7000 "25"
集群使用公式 CRC16(key) % 16384来计算键 key 属于哪个槽, 其中 CRC16(key) 语句用于计算键key的CRC16校验和,可以看到name存储在节点7001中,age存储在节点7000中
使用redis-py-cluster编写一个示例应用
redis集群客户端:
- redis-rb-cluster
- redis-py-cluster
- redis-cli
redis-cli只支持基本的集群操作,redis-rb-cluster需要用ruby编程,redis-py-cluster是redis-rb-cluster的一个python版本,对于不熟悉ruby的我,只能选择redis-py-cluster了。
安装redis-py-cluster
pip install redis-py-cluster
示例:example.py
from rediscluster import RedisCluster import time startup_nodes = [{"host": "127.0.0.1", "port": "7000"}] rc = RedisCluster(startup_nodes=startup_nodes, decode_responses=True) for value in range(3600): key = 'foo{0}'.format(value) try: rc.set(key, value) print(rc.get(key)) except Exception as e: print(e) time.sleep(1)
运行结果:
持续3600s,每隔1s执行
set foo0 0 set foo1 1 set foo2 2
对集群进行重新分片
集群的重新分片是在不影响集群运行情况下重新改变槽与主节点的对应关系
比如,目前我的槽与主节点对应关系如下:nodes.conf
991ec642c74afd0b95b3d0e0cb6e5081fa390d0a 127.0.0.1:7000 myself,master - 0 0 7 connected 0-6007 10923-11455 dae08d34ba0233f1ac9676eb147dfb6f3633cbac 127.0.0.1:7003 slave 991ec642c74afd0b95b3d0e0cb6e5081fa390d0a 0 1567338412047 7 connected f3cb39f0b5aa81faa1ddf3c25665ec1d5f0bc855 127.0.0.1:7002 master - 0 1567338413054 3 connected 11456-16383 aa7539ba2672513310c7d0286f8219a9e0f17be3 127.0.0.1:7004 slave c81721f806a099a51b70ae539cee08c6f321a99e 0 1567338413054 5 connected c81721f806a099a51b70ae539cee08c6f321a99e 127.0.0.1:7001 master - 0 1567338413658 2 connected 6008-10922 97692ea933ff1c3460fd418f29205ec98e55871d 127.0.0.1:7005 slave f3cb39f0b5aa81faa1ddf3c25665ec1d5f0bc855 0 1567338413656 6 connected vars currentEpoch 7 lastVoteEpoch 0
让example.py保持运行状态,这样你就会看到, 重新分片并不会对正在运行的集群程序产生任何影响
执行以下命令可以开始一次重新分片操作:
ruby redis-trib.rb reshard 127.0.0.1:7000
需要移动100个槽
How many slots do you want to move (from 1 to 16384)? 100
将这100个槽移动到ID为f3cb39f0b5aa81faa1ddf3c25665ec1d5f0bc855的节点,即端口为7002的节点
What is the receiving node ID? f3cb39f0b5aa81faa1ddf3c25665ec1d5f0bc855
指定这100个槽的源节点,all表示除了目标节点的所有节点
Source node #1:all
此时重新分片已经完成,在看一下nodes.conf:
991ec642c74afd0b95b3d0e0cb6e5081fa390d0a 127.0.0.1:7000 myself,master - 0 0 7 connected 58-6007 10923-11455 dae08d34ba0233f1ac9676eb147dfb6f3633cbac 127.0.0.1:7003 slave 991ec642c74afd0b95b3d0e0cb6e5081fa390d0a 0 1567339089245 7 connected f3cb39f0b5aa81faa1ddf3c25665ec1d5f0bc855 127.0.0.1:7002 master - 0 1567339088237 8 connected 0-57 6008-6049 11456-16383 aa7539ba2672513310c7d0286f8219a9e0f17be3 127.0.0.1:7004 slave c81721f806a099a51b70ae539cee08c6f321a99e 0 1567339087734 5 connected c81721f806a099a51b70ae539cee08c6f321a99e 127.0.0.1:7001 master - 0 1567339087734 2 connected 6050-10922 97692ea933ff1c3460fd418f29205ec98e55871d 127.0.0.1:7005 slave f3cb39f0b5aa81faa1ddf3c25665ec1d5f0bc855 0 1567339089747 8 connected vars currentEpoch 8 lastVoteEpoch 0
可以看到7000减少了58个槽,7001减少了42个槽,7002增加了100个槽
验证集群数据有无破环
example.py的执行没有被打断,set,get操作均正常,现在来看一下数据是否正常:example-check.py
from rediscluster import RedisCluster startup_nodes = [{"host": "127.0.0.1", "port": "7000"}] rc = RedisCluster(startup_nodes=startup_nodes, decode_responses=True) for value in range(3600): key = 'foo{0}'.format(value) assert(int(rc.get(key)) == value)
程序运行没触发断言,说明集群切片操作不会对正在运行的集群程序产生任何影响
添加新节点到集群
创建一个新节点7006,过程如前面7000 - 7005,
将新节点添加到集群:
./redis-trib.rb add-node 127.0.0.1:7006 127.0.0.1:7000
前面ip:port为新节点,后面的ip:port为集群中任意一节点
通过命令查看是否添加成功
#redis-cli -p 7000 cluster nodes 991ec642c74afd0b95b3d0e0cb6e5081fa390d0a 127.0.0.1:7000 myself,master - 0 0 7 connected 58-6007 10923-11455 dae08d34ba0233f1ac9676eb147dfb6f3633cbac 127.0.0.1:7003 slave 991ec642c74afd0b95b3d0e0cb6e5081fa390d0a 0 1567341757291 7 connected f3cb39f0b5aa81faa1ddf3c25665ec1d5f0bc855 127.0.0.1:7002 master - 0 1567341756788 8 connected 0-57 6008-6049 11456-16383 7855966e30f860ada9ac4934c073043c87bbbcf2 127.0.0.1:7006 master - 0 1567341756285 0 connected aa7539ba2672513310c7d0286f8219a9e0f17be3 127.0.0.1:7004 slave c81721f806a099a51b70ae539cee08c6f321a99e 0 1567341755784 5 connected c81721f806a099a51b70ae539cee08c6f321a99e 127.0.0.1:7001 master - 0 1567341755784 2 connected 6050-10922 97692ea933ff1c3460fd418f29205ec98e55871d 127.0.0.1:7005 slave f3cb39f0b5aa81faa1ddf3c25665ec1d5f0bc855 0 1567341757794 8 connected
可以看到新增加的节点是主节点,没有对应哈希槽,可以通过前面分片操作分配相应的哈希槽
如果希望这个节点成为某个主节点的从节点可以这么做:
#redis-cli -p 7006 127.0.0.1:7006> 127.0.0.1:7006>cluster replicate 991ec642c74afd0b95b3d0e0cb6e5081fa390d0a
OK
id 991ec642c74afd0b95b3d0e0cb6e5081fa390d0a是主节点7000的ID,即将7006变为7000的从节点
# redis-cli -p 7000 cluster nodes 991ec642c74afd0b95b3d0e0cb6e5081fa390d0a 127.0.0.1:7000 myself,master - 0 0 7 connected 58-6007 10923-11455 dae08d34ba0233f1ac9676eb147dfb6f3633cbac 127.0.0.1:7003 slave 991ec642c74afd0b95b3d0e0cb6e5081fa390d0a 0 1567342165665 7 connected f3cb39f0b5aa81faa1ddf3c25665ec1d5f0bc855 127.0.0.1:7002 master - 0 1567342167173 8 connected 0-57 6008-6049 11456-16383 7855966e30f860ada9ac4934c073043c87bbbcf2 127.0.0.1:7006 slave 991ec642c74afd0b95b3d0e0cb6e5081fa390d0a 0 1567342167675 7 connected aa7539ba2672513310c7d0286f8219a9e0f17be3 127.0.0.1:7004 slave c81721f806a099a51b70ae539cee08c6f321a99e 0 1567342167173 5 connected c81721f806a099a51b70ae539cee08c6f321a99e 127.0.0.1:7001 master - 0 1567342165665 2 connected 6050-10922 97692ea933ff1c3460fd418f29205ec98e55871d 127.0.0.1:7005 slave f3cb39f0b5aa81faa1ddf3c25665ec1d5f0bc855 0 1567342166670 8 connected
可以看到已经修改成功