docker安装Redis三主三从集群
Redis集群分区的方案
1、哈希取余分区
-
介绍:假设有3台机器构成一个集群,用户每次读写操作都是根据公式:hash(key) % N个机器台数,计算出哈希值,用来决定数据映射到哪一个节点上。
-
优点:操作简单,只需要根据公式判断落在哪台机器上
-
缺点:扩缩容麻烦,redis节点数变化后,映射关系需要重新计算。
2.一致性哈希算法分区
-
介绍:主要是解决由于Redis服务器个数变化导致的映射关系变化,尽量少的移动Redis节点上的数据。
一致性Hash算法将整个哈希值空间组织成一个虚拟的圆环,如假设某哈希函数H的值空间为0-2^32-1(即哈希值是一个32位无符号整形),整个哈希环如下图:整个空间按顺时针方向组织,圆环的正上方的点代表0,0点右侧的第一个点代表1,以此类推,2、3、4、……直到2^32-1,也就是说0点左侧的第一个点代表2^32-1, 0和2^32-1在零点中方向重合,我们把这个由2^32个点组成的圆环称为Hash环。
-
节点映射: 将集群中各个IP节点映射到环上的某一个位置。
将各个服务器使用Hash进行一个哈希,具体可以选择服务器的IP或主机名作为关键字进行哈希,这样每台机器就能确定其在哈希环上的位置。假如4个节点NodeA、B、C、D,经过IP地址的哈希函数计算(hash(ip)),使用IP地址哈希后在环空间的位置如下:
- 落键规则: 首先计算key的hash值,hash(key),将这个key使用相同的函数Hash计算出哈希值并确定此数据在环上的位置,从此位置沿环顺时针“行走”,第一台遇到的服务器就是其应该定位到的服务器,并将该键值对存储在该节点上。
-
优点:服务器个数发生变化时需要迁移的数据少,所以增删节点比较方便。
-
缺点:一致性Hash算法在服务节点太少时,容易因为节点分布不均匀而造成数据倾斜(被缓存的对象大部分集中缓存在某一台服务器上)问题,
例如系统中只有两台服务器:
3.哈希槽分区
-
介绍: 一般采用这种方案
-
哈希槽实质就是一个数组,数组[0,2^14 -1]形成hash slot空间。
-
解决均匀分配的问题,在数据和节点之间又加入了一层,把这层称为哈希槽(slot),用于管理数据和节点之间的关系,现在就相当于节点上放的是槽,槽里放的是数据。
-
一个集群只能有16384个槽,编号0-16383(0-2^14-1)。这些槽会分配给集群中的所有主节点,分配策略没有要求。可以指定哪些编号的槽分配给哪个主节点。集群会记录节点和槽的对应关系。解决了节点和槽的关系后,接下来就需要对key求哈希值,然后对16384取余,余数是几key就落入对应的槽里。slot = CRC16(key) % 16384。以槽为单位移动数据,因为槽的数目是固定的,处理起来比较容易,这样数据移动问题就解决了。
-
三主三从集群安装
- 新建6个Redis容器
# 节点1
docker run -d --name redis-node-1 --net host --privileged=true -v /data/redis/share/redis-node-1:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6381
# 节点2
docker run -d --name redis-node-2 --net host --privileged=true -v /data/redis/share/redis-node-2:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6382
# 节点3
docker run -d --name redis-node-3 --net host --privileged=true -v /data/redis/share/redis-node-3:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6383
# 节点4
docker run -d --name redis-node-4 --net host --privileged=true -v /data/redis/share/redis-node-4:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6384
# 节点5
docker run -d --name redis-node-5 --net host --privileged=true -v /data/redis/share/redis-node-5:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6385
# 节点6
docker run -d --name redis-node-6 --net host --privileged=true -v /data/redis/share/redis-node-6:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6386
- 进入容器redis-node-1为6台机器构建集群关系
1、进入容器
docker exec -it redis-node-1 /bin/bash
2、进入docker容器后才能执行一下命令,且注意自己的真实IP地址
redis-cli --cluster create 192.168.111.147:6381 192.168.111.147:6382 192.168.111.147:6383 192.168.111.147:6384 192.168.111.147:6385 192.168.111.147:6386 --cluster-replicas 1
#--cluster-replicas 1 表示为每个master创建一个slave节点
-
查看集群状态
- 进入 6381查看集群状态
1、进入容器 docker exec -it redis-node-1 /bin/bash 2、查看容器状态 redis-cli -p 6381 3、cluster info 4、cluster node
主从容错案例
- 先停止master 6381
docker stop redis-node-1
发现原来6381的从机6385变成了master了
主从扩容
- 新建6387和6388两个节点
#节点7
docker run -d --name redis-node-7 --net host --privileged=true -v /data/redis/share/redis-node-7:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6387
#节点8
docker run -d --name redis-node-8 --net host --privileged=true -v /data/redis/share/redis-node-8:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6388
- 进入6387容器内部
docker exec -it redis-node-7 /bin/bash
- 将新增的6387节点(空槽号)作为master节点加入原集群
redis-cli --cluster add-node IP:6387 IP:6381
- 重新分配槽号
redis-cli --cluster reshard IP:6381
为什么6387是3个新的区间,以前的还是连续?
重新分配成本太高,所以前3家各自匀出来一部分,从6381/6382/6383三个旧节点分别匀出1364个坑位给新节点6387
- 为主节点6387分配从节点6388
命令:
redis-cli --cluster add-node ip:新slave端口 ip:新master端口 --cluster-slave --cluster-master-id 新主机节点ID
redis-cli --cluster add-node 192.168.111.147:6388 192.168.111.147:6387 --cluster-slave --cluster-master-id e4781f644d4a4e4d4b4d107157b9ba8144631451-------这个是6387的编号,按照自己实际情况
- 检查集群信息
#需要进入容器内部
redis-cli --cluster check IP:6382
主从缩容
把刚才加入集群的6387和6388两台机器下线
- 检查集群信息获取6388的ID号
#需要进入容器内部
redis-cli --cluster check IP:6382
- 删除6388
命令:redis-cli --cluster del-node ip:从机端口 从机6388节点ID
redis-cli --cluster del-node 192.168.111.147:6388 5d149074b7e57b802287d1797a874ed7a1a284a8
- 把6387节点中的数据分配到其他节点上(本次全部放到6381中)
redis-cli --cluster reshard IP:6381
- 把6387节点删除
命令:redis-cli --cluster del-node ip:端口 6387节点ID
redis-cli --cluster del-node 192.168.111.147:6387 e4781f644d4a4e4d4b4d107157b9ba8144631451
- 检查集群的状态
redis-cli --cluster check IP:6381