集群

6379:对外服务 16379:节点间通信

数据分布方案:

Redis集群使用了虚拟槽分区:

屏幕截图 2020-10-10 134940屏幕截图 2020-10-10 134956

使用这种方案带来的特点:

由于数据分布于不同的节点, 所以集群功能相比单机有如下限制:

集群方案

集群搭建

节点准备:

# 节点端口
port 6379
#  开启集群模式
cluster-enabled yes
#  节点超时时间,单位毫秒
cluster-node-timeout 15000
#  集群内部配置文件
cluster-config-file "nodes-6379.conf"

节点握手:

cluster meet 127.0.0.1 6380
...

节点建立握手之后集群还不能正常工作 需要为各个节点分配slot:

redis-cli -h 127.0.0.1 -p 6379 cluster addslots {0..5461}
...

作为一个完整的集群,每个负责处理槽的节点应该具有从节点,保证当它出现故障时可以自动进行故障转移:

使用cluster nodes命令查看集群节点

让其他节点做复制:

cluster replicate 41f2232cc928fb61c8a201b7d1cc1e57f029752e
...

使用redis-cli:

redis-cli --cluster create 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384 127.0.0.1:6380 127.0.0.1:6379 --cl
uster-replicas 1

redis-cluster原理

redis cluster 有固定的 16384 个 hash slot,集群中的每个node平均分配得到一定的slot

使用一致性哈希实现

优点: 增加节点,的确可以分担其他节点的压力,不会造成全局洗牌

缺点: 新增节点造成一小部分数据不能命中 1,问题,击穿,压到mysql 2,方案:每次取离我最近的2个物理节点

更倾向于 作为缓存,而不是数据库用!!!!

节点间的通信

节点彼此不断通信交换信息,一段时间后所有的节点都会知道集群完整的信息

redis 维护集群元数据采用了gossip协议,所有节点都持有一份元数据,不同的节点如果出现了元数据的变更,就不断将元数据发送给其它的节点

但是元数据的更新有延时,可能导致集群中的一些操作会有一些滞后

gossip协议

屏幕截图 2020-10-10 143318

节点选择

屏幕截图 2020-10-10 143639

集群伸缩

数据槽点迁移:

屏幕截图 2020-10-11 135638屏幕截图 2020-10-11 142255

扩容:

收缩:

...

请求路由

请求重定向:

屏幕截图 2020-10-11 142527

当的ket的CRC16结果不是本节点时 集群节点就会返回一个MOVED错误 提供实际节点

127.0.0.1:6379> set hello2 value1
(error) MOVED 7486 127.0.0.1:6380

使用redis-cli时 加上-c参数支持自动重定向

ASK重定向:

例如当一个slot数据从源节点迁移到目标节点时,期间可能出现一部分数据在源节点,而另一部分在目标节点 客户端需要自行处理这种情况

ASK重定向说明集群正在进行slot数据迁移,客户端无法知道什么时候迁移 完成,因此只能是临时性的重定向,客户端不会更新slots缓存

故障转移

故障恢复:故障节点变为客观下线后,如果下线节点是持有槽的主节点则需要在它的从节点中选出一个替换它

集群运维

集群完整性:

为了保证集群完整性,默认情况下当集群16384个槽任何一个没有指派到节点时整个集群不可用 当持有槽的主节点下线时,从故障发现到自动完成转移期间整个集群是不可用状态 为了避免这种情况 可以设置cluster-require-full-coverage为no

带宽:

集群带宽消耗主要分为:读写命令消耗+Gossip消息消耗

PUB/SUB问题:Pub/Sub功能应该避免在大量节点的集群内使用,否则会严重消耗集群内网络带宽

集群倾斜:

集群读写分离:

手动故障转移:

cluster failover命令

数据迁移(从单机导入集群):

redis-cli --cluster import命令