docker版redis集群-哈希槽分区
一、理论
1.什么是哈希槽分区
1 为什么出现
哈希槽实质就是一个数组,数组[0,2^14 -1]形成hash slot空间。 2 能干什么 解决均匀分配的问题,在数据和节点之间又加入了一层,把这层称为哈希槽(slot),用于管理数据和节点之间的关系,现在就相当于节点上放的是槽,槽里放的是数据。
槽解决的是粒度问题,相当于把粒度变大了,这样便于数据移动。 哈希解决的是映射问题,使用key的哈希值来计算所在的槽,便于数据分配。 3 多少个hash槽 一个集群只能有16384个槽,编号0-16383(0-2^14-1)。这些槽会分配给集群中的所有主节点,分配策略没有要求。
可以指定哪些编号的槽分配给哪个主节点。集群会记录节点和槽的对应关系。解决了节点和槽的关系后,接下来就需要对key求哈希值,然后对16384取余,
余数是几key就落入对应的槽里。slot = CRC16(key) % 16384。
以槽为单位移动数据,因为槽的数目是固定的,处理起来比较容易,这样数据移动问题就解决了。
2.哈希槽计算
Redis 集群中内置了 16384 个哈希槽,redis 会根据节点数量大致均等的将哈希槽映射到不同的节点。
当需要在 Redis 集群中放置一个 key-value时,redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数,
这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,也就是映射到某个节点上。如下代码,key之A 、B在Node2, key之C落在Node3上
二、3主3从redis集群扩缩容配置
1.新建6个docker容器redis实例
docker run -d --name redis-node-1 --net host --privileged=true -v /zgbo/redis/cluster/redis-node-1:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6381 docker run -d --name redis-node-2 --net host --privileged=true -v /zgbo/redis/cluster/redis-node-2:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6382 docker run -d --name redis-node-3 --net host --privileged=true -v /zgbo/redis/cluster/redis-node-3:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6383 docker run -d --name redis-node-4 --net host --privileged=true -v /zgbo/redis/cluster/redis-node-4:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6384 docker run -d --name redis-node-5 --net host --privileged=true -v /zgbo/redis/cluster/redis-node-5:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6385 docker run -d --name redis-node-6 --net host --privileged=true -v /zgbo/redis/cluster/redis-node-6:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6386
参数解释
docker run 创建并运行docker容器实例
--name redis-node-6 容器名字
--net host 使用宿主机的IP和端口,默认
--privileged=true 获取宿主机root用户权限
-v /data/redis/share/redis-node-6:/data 容器卷,宿主机地址:docker内部地址
redis:6.0.8 redis镜像和版本号
--cluster-enabled yes 开启redis集群
--appendonly yes 开启持久化
--port 6386 redis端口号
2.进入redis-node-1容器并为6台机器构建集群关系
docker exec -it redis-node-1 bash
构建关系
//注意,进入docker容器后才能执行一下命令,且注意自己的真实IP地址 redis-cli --cluster create 172.16.15.187:6381 172.16.15.187:6382 172.16.15.187:6383 172.16.15.187:6384 172.16.15.187:6385 172.16.15.187:6386 --cluster-replicas 1
--cluster-replicas 1 表示为每个master创建一个slave节点
3主3从已完成
3.链接进入6382作为切入点,查看集群状态
redis-cli -p -6382
//查询集群的消息
cluster info
//查看集群的节点信息
cluster nodes
集群信息
cluster_state:状态是ok节点是否能够接收查询。fail状态表示有哈希槽没有被绑定到任意一个节点或者节点可以提供服务但是带有fail标记,
或者该节点无法连续到多数master节点
cluster_slots_assigned:与某个节点关联的槽数(不是未绑定的)。这个数字应该是16384,节点才能正常工作,这意味着每个散列槽应该映射到一个节点。
cluster_slots_ok:哈希槽状态不是Fail和PFail的数量
cluster_slots_pfail:哈希槽状态是PFAIL的数量。请注意,只要PFAIL状态不由FAIL故障检测算法提升,这些散列槽仍可正常工作。
PFAIL仅意味着我们目前无法与节点通话,但可能只是一个暂时的错误。
cluster_slots_fail:哈希槽状态是FAIL的数量。如果此数字不为零,则该节点无法提供查询,除非在配置中cluster-require-full-coverage设置为no。
cluster_known_nodes:群集中已知节点的总数,包括处于握手(HANDSHAKE)状态还没有称为集群正式成员的节点
cluster_size:至少包含一个哈希槽而且能够提供服务的master节点数量
cluster_current_epoch:集群本地Current Epoch变量的值,这个值在节点故障转移期间创建的独特的自增版本号
cluster_my_epoch:我们正在与之交谈的Config Epoch节点。这是分配给此节点的当前配置版本。
cluster_stats_messages_sent:通过node-to-node二进制总线发送的消息数量
cluster_stats_messages_received:通过node-to-node二进制总线接收的消息数量
节点信息
每项含义如下:
id 节点ID,是一个40字节的随机字符串,这个值在节点启动的时候创建,并且永远不会改变(除非使用CLUSTER RESET HARD命令)
ip:port 客户端与节点通信使用的地址
flags 逗号分割的标记位,可能的值有: myself, master, slave, fail?, fail, handshake, noaddr, noflags. 之后将详细介绍这些标记
myself: 当前连接的节点
master: 节点是master
slave: 节点是slave
fail?: 节点处于PFAIL 状态。 当前节点无法联系,但逻辑上是可达的 (非 FAIL 状态)
fail: 节点处于FAIL 状态. 大部分节点都无法与其取得联系将会将改节点由 PFAIL 状态升级至FAIL状态
handshake: 还未取得信任的节点,当前正在与其进行握手
noaddr: 没有地址的节点(No address known for this node)
noflags: 连个标记都没有(No flags at all)
master 如果节点是slave,并且已知master节点,则这里列出master节点ID,否则的话这里列出"-"
ping-sent 最近一次发送ping的时间,这个时间是一个unix毫秒时间戳,0代表没有发送过
pong-recv 最近一次收到pong的时间,使用unix时间戳表示
config-epoch 节点的epoch值(如果该节点是从节点,则为其主节点的epoch值)。每当节点发生失败切换时,都会创建一个新的,
独特的,递增的epoch。如果多个节点竞争同一个哈希槽时,epoch值更高的节点会抢夺到
link-state node-to-node集群总线使用的链接的状态,我们使用这个链接与集群中其他节点进行通信.值可以是 connected 和 disconnected
slot 哈希槽值或者一个哈希槽范围. 从第9个参数开始,后面最多可能有16384个 数(limit never reached)。
代表当前节点可以提供服务的所有哈希槽值。如果只是一个值,那就是只有一个槽会被使用。如果是一个范围,
这个值表示为起始槽-结束槽,节点将处理包括起始槽和结束槽在内的所有哈希槽
三、主从容错切换迁移
1.数据读写存储
1)进入6382节点 添加数据
docker exec -it redis-node-2 bash
redis-cli -p 6382 -c
-c 一定要加 这个是路由模式开启
2)查看集群信息
redis-cli --cluster check 172.16.15.187:6382
2.容错切换迁移、
1)理论:停止6382节点容器,看看从节点6384是否能成为主 替代6382
2)停止6382节点容器
docker stop redis-node-2
3)查看集群信息
// 进入容器
docker exec -it redis-node-1 bash // 连接redis redis-cli -p 6381 -c // 查看集群信息 cluster nodes
从图中可以看到6384成为主 6382一宕机
四、主从扩容
1.新建两个节点
docker run -d --name redis-node-7 --net host --privileged=true -v /zgbo/redis/cluster/redis-node-7:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6387 docker run -d --name redis-node-8 --net host --privileged=true -v /zgbo/redis/cluster/redis-node-8:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6388
2.进入6387节点
docker exec -it redis-node-7 bash
3.将新增的6387作为master节点加入集群
redis-cli --cluster add-node 172.16.15.187:6387 172.16.15.187:6381
add-node 加入节点 6387 就是将要作为master新增节点 6381 就是原来集群节点里面的领路人,相当于6381是6387引路人而找到组织加入集群
4.检查集群信息
redis-cli --cluster check 172.16.15.187:6381
5.重新分派槽号
命令:redis-cli --cluster reshard IP地址:端口号
redis-cli --cluster reshard 172.16.15.187:6381
输入想要分入的插槽数量,插槽给哪个节点的id,all是所有插槽分到节点
6.检查集群信息
redis-cli --cluster check 172.16.15.187:6381
分配说明:从三个旧节点分别平均出1364个插槽给新节点6387,从头数1364个插槽
7.为主节点6387分配从节点6388,并检查集群信息
命令:redis-cli --cluster add-node ip:新slave端口 ip:新master端口 --cluster-slave --cluster-master-id 新主机节点ID
redis-cli --cluster add-node 172.16.15.187:6388 172.16.15.187:6387 --cluster-slave --cluster-master-id 3489c0493b2bd31fd67960b113b00eaad7c25cc6
3489c0493b2bd31fd67960b113b00eaad7c25cc6-------这个是6387的编号ID,按照自己实际情况
五、主从缩容
1.查看容器信息和集群信息(缩掉6387(redis-node-7)和6388(redis-node-8))
2.从集群中将从节点6388删除
命令:redis-cli --cluster del-node ip:从机端口 从机6388节点ID redis-cli --cluster del-node 172.16.15.187:6388 a6c534ce94fc24a23f0e47a0f4f6c23a15942226
a6c534ce94fc24a23f0e47a0f4f6c23a15942226----6388节点编码ID
//删除后在检查集群信息 redis-cli --cluster check 172.16.15.187:6381
3.将6387的槽号清空,重新分配(先给6381分配1364个插槽,在给6382分配2732)
redis-cli --cluster reshard 172.16.15.187:6381
给6381分配1364个插槽
再次执行redis-cli --cluster reshard 172.16.15.187:6381给6382分配2732个插槽
检查集群信息 执行redis-cli --cluster reshard 172.16.15.187:6381
4.删除6387节点
命令:redis-cli --cluster del-node ip:端口 6387节点ID redis-cli --cluster del-node 172.16.15.187:6387 3489c0493b2bd31fd67960b113b00eaad7c25cc6
删除成功后检查集群信息 执行redis-cli --cluster reshard 172.16.15.187:6381