redis集群搭建

 

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依赖

redis-3.3.0.gem

 使用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

可以看到已经修改成功

 

上一篇:大数据-zookeeper的数据结构及节点操作


下一篇:强连通分量(Strongly Connected Components)