注意⚠️:以下内容为自己理解,可能存在偏差,都是纯文本内容,阅读时间大约为3min。
写在开头:
集群解决的问题:
通过水平扩展,解决大量数据单节点存储对单节点的压力。
redis通过集群管理一批数据,通过分片降低各节点存储数据,从而降低压力。
理论上哈希环数据存储方式:顺序存储,存储完一个节点后存储下一个节点。
存在问题:做了集群但数据还不多,其他节点空闲资源浪费,大量读取数据时存储数据的节点,最终与单机无太多差别。
分区算法:
都是基于哈希算法。分为 节点取余分区、一致性分区算法、虚拟一致性分区算法
节点取余
最简单的哈希分区方式,不支持动态扩容,否则出现全局rehash。适合节点数量固定且规模小的集群。
若还是想要在已有集群节点数量上添加非倍数的节点,采用一致性哈希分区,防止全局rehash问题。
一致性哈希分区
计算hash值后,根据key映射到哈希环上,再顺时针找到第一个节点,将当前数据交给这个节点管理。
若添加了新节点,可能成为下面结构
由新节点添加后,只有N2与N3之间的数据做了迁移,分担了压力,其他节点分布未改变可能出现的负载倾斜。
虚拟一致性哈希分区
基本内容与一致性哈希分区一致。但每个物理节点映射了多个虚拟节点放在哈希环上,这样使数据更均匀的分布在物理节点上
以上为redis做集群时提供的数据分散算法方案。
集群搭建-windows版
目标:搭建三主三从集群
多redis启动bat文件
@echo off
echo 批量启动redis实例中,请稍后...
rem 启动 6个 Redis实例,占用端口 6379~6384
start cmd /k "cd /d Redis-6379 && redis-server.exe redis.conf --port 6379 --cluster-enabled yes --cluster-config-file nodes-6379.conf --cluster-node-timeout 5000 --appendonly yes --appendfilename appendonly-6379.aof"
start cmd /k "cd /d Redis-6380 && redis-server.exe redis.conf --port 6380 --cluster-enabled yes --cluster-config-file nodes-6380.conf --cluster-node-timeout 5000 --appendonly yes --appendfilename appendonly-6380.aof"
start cmd /k "cd /d Redis-6381 && redis-server.exe redis.conf --port 6381 --cluster-enabled yes --cluster-config-file nodes-6381.conf --cluster-node-timeout 5000 --appendonly yes --appendfilename appendonly-6381.aof"
start cmd /k "cd /d Redis-6382 && redis-server.exe redis.conf --port 6382 --cluster-enabled yes --cluster-config-file nodes-6382.conf --cluster-node-timeout 5000 --appendonly yes --appendfilename appendonly-6382.aof"
start cmd /k "cd /d Redis-6383 && redis-server.exe redis.conf --port 6383 --cluster-enabled yes --cluster-config-file nodes-6383.conf --cluster-node-timeout 5000 --appendonly yes --appendfilename appendonly-6383.aof"
start cmd /k "cd /d Redis-6384 && redis-server.exe redis.conf --port 6384 --cluster-enabled yes --cluster-config-file nodes-6384.conf --cluster-node-timeout 5000 --appendonly yes --appendfilename appendonly-6384.aof"
echo 已启动所有实例
pause
做集群搭建⬇️
./redis-cli.exe --cluster create 127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384 --cluster-replicas 1
失败问题
搭建时可能存在失败情况,一般来说是节点之间通信出现异常导致的。
下面搭建失败时,一直在等待集群中节点加入做通信。
解决方式
需要开启redis之间通信接口,一般是在端口基础上+10000,按照上面就是16379~16384
开启后重新执行集群搭建命令⬆️,成功后如下
验证
未连接时,通过 redis-cli --cluster info [任意主节点]即可查看分区情况。
其他命令
重建集群关系:
redis-cli -h 127.0.0.1 -p 6379 cluster reset
集群中相关问题
如何写入数据
按照传统使用命令行方式设置数据时,将会出现异常情况
这是因为在写入数据时存在分区算法,按照分槽算法应该插入指定槽中。
那我就是想用命令设置数据到集群中,又不想了解集群中分槽算法下的数据落下方式,那就只有强制写入,计算和写操作都交给redis自己完成。
首先通过 redis-cli.exe -p [port] -c指定连接的节点,再通过set命令完成数据写入。
这个表示写入的数据将重定向到5798这个槽,这个槽由6380管理
为什么集群块为16384
搭建集群时可看到,搭建中最后一个节点是16384。
Redis中采用CRC16 % 16384计算分槽位置。
16384为 ,做位运算比任意数字更快。
槽位过少如1024,分区粒度过大,分区接管难度大。
槽位过多,节点协商复杂
作者说过:
16384 is big enough to split data in small enough parts, but small enough to make cluster map not memory-intensive and easy to manage.
通信原理
协议:集群中各个节点交流基于Gossip协议
通信节点:主节点每1s对外发送一次通信,一次通信中优先选择最久未做通信的节点,为了确保所有节点都能周期性被检查,实际选择数量为集群节点数/10 + 随机三节点。
流程:
A.向目标节点发送ping命令,并将自己的节点信息 与 其他节点信息一并告诉
B.目标节点收到ping后返回pong,同样携带自己节点信息 与 其他节点信息。
C.新节点加入集群时,将自己信息发送给已有节点,已有节点将新节点信息广播出去。
D.若ping超时,标记该节点为PFAIL(主观下线);大多数节点都为PFAIL时,为客观下线。
下线
主观下线:
客观下线
故障转移
故障转移一句话概括为:资格检查、挑选等待、准备选举、选举投票、节点替换
每个步骤具体做了什么内容如下:
资格检查 当主节点断开连接,且被标记为了PFAIL,主节点宕机时间是否超过阈值,对应的从节点将放入选举列表。并判断从节点是否在集群中、判断从节点是否分槽
挑选等待 将满足条件的节点进行二轮筛选,筛选条件为同步的偏移量,偏移量越高,这个节点晋升为主节点的概率越大,每个从节点随机增加一个时间,防止每个节点同时发起。
准备选举 从节点向其他主节点发送请求,请求中携带自身数据,每个主节点只能做一次投票
选举投票 主节点拿到信息后,判断该节点是不是挂了的主节点下的从节点,判断自己是否为第一次收到请求,若都满足就可投票
节点替换 当前从节点成为主节点后,广播自己主节点信息,其他节点更新结构,其他从节点挂载到该节点上