当前位置:网站首页>redis集群系列四
redis集群系列四
2022-07-03 08:19:00 【快乐划水程序猿】
输出是多么快乐的一件事情,hurray~
1 集群的完整性
- 如果参数cluster-require-full-coverage设置为yes(默认值),则所有槽都需要并指派到节点上,保护集群的完整性。
- 如果参数cluster-require-full-coverage设置为no,在某些分片故障切换的时候,其他节点还是可用的
# cluster-require-full-coverage yes
2 大集群的带宽消耗
2.1 大集群的带宽消耗主要有三方面
- 消息频率:节点发现与其他节点最后通讯时间超过cluster-node-timeout/2时会直接发送ping消息
- 消息数据量:slots槽数组(2KB)+ 整个集群1/10的状态数据(1个节点的状态数据104bytes)
- 物理机器上的节点规模
2.2 大集群的带宽消耗预估量
以200个节点为例子,20台物理机器,每台物理机器10个节点。
实际通信的过程中, AB两个节点进行ping/pong,A会通过一个随机的端口向节点B的集群通讯端口发送ping消息,节点B通过集群通信端口向A发送pong消息。所以A节点的入口带宽,不仅包含本身的集群端口,也包含随机端口,而随机端口正是其他节点的集群通讯端口的出口带宽。
那么可以计算出来,1台机器的入口带宽:
每个消息是2kb+20*104bytes=4kb
1台机器集群端口的入口带宽:4kb*190*2*10/15=1203kb
实际的1台机器的入口带宽=所有机器集群端口的出口带宽+本台机器的集群端口的入口带宽=1203kb*20=24mb左右
有人做了一个抓包统计gossip消息实验及分析,很细致,感兴趣或者自己想抓包分析的可参考:https://github.com/moooofly/MarkSomethingDown/blob/master/Redis/Redis%20%E4%BD%BF%E7%94%A8%E9%97%AE%E9%A2%98%E6%B1%87%E6%80%BB%EF%BC%88%E7%BD%91%E6%96%87%EF%BC%89.md
集群的带宽消耗,主要由读写命令和gossip消息消耗;所以搭建redis集群要注意根据业务规模和消息通信成本做好规划。
官方建议集群的最大规模在1000以内。建议合理选择哦
3 pub/sub 广播问题
- 对集群所有的主节点执行subscribe订阅test频道
- 连接集群发布test频道的消息
- 集群内所有节点订阅test频道的都收到了消息
集群模式下的publish广播问题,也会消耗集群内的网络带宽。这种情况建议使用sentinel来专门用于pub/sub来规避
4 集群倾斜
4.1 数据倾斜
一般分为以下几种情况
- 节点和槽分配不均匀
- 不同的槽对应的键值差异较大
- case:大量使用hash_tag,会产生不同的键映射到同一个槽
- 可以使用command: cluster countkeysinslot {slot}获取slot的键值数目,然后使用command: cluster getkeysinslot {slot} {count} 循环迭代出槽下所有的键
- 集合对象包含大量元素(大key)
- 可以使用命令:redis-cli --bigkeys
- 大key,比如几百M,可能会在migrate过程中超时失败
- 内存配置不一致
- 有些压缩数据结构的配置不一致(hash-max-ziplist-value、set-max-intset-entries等)
4.2 请求倾斜
可能情况:热key对应高算法复杂度的命令,或者大对象操作hegtall、smembers
建议:使用hmget代替hgetall避免全部读取
5 读写分离
5.1 只读连接
- 集群模式下,从节点是不接受任何读写请求的,从节点接收到的读写命令会重定向到负责槽的主节点。
- 需要使用从节点分担读压力,需要连接从节点,输入readonly,从节点接收到的读命令,如果key属于自己正在复制的主节点则直接返回,否则返回重定向信息
- readonly是连接级别生效的,每次新建连接都需要执行readonly
- readwrite命令可以关闭连接只读状态
- 可以通过client list查看客户端连接的状态:flags=N表示普通客户端
/data # redis-cli
127.0.0.1:6379> client list
id=28 addr=10.0.129.186:6379 fd=21 name= age=19730 idle=5 flags=M db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=ping
id=20058 addr=127.0.0.1:34716 fd=23 name= age=8 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=26 qbuf-free=32742 obl=0 oll=0 omem=0 events=r cmd=client
127.0.0.1:6379> get 100
(error) MOVED 339 10.0.129.186:6379
127.0.0.1:6379> readonly
OK
127.0.0.1:6379> client list
id=28 addr=10.0.129.186:6379 fd=21 name= age=19753 idle=8 flags=M db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=ping
id=20058 addr=127.0.0.1:34716 fd=23 name= age=31 idle=0 flags=r db=0 sub=0 psub=0 multi=-1 qbuf=26 qbuf-free=32742 obl=0 oll=0 omem=0 events=r cmd=client
127.0.0.1:6379> get 100
"100"
127.0.0.1:6379> readwrite
OK
127.0.0.1:6379> get 100
(error) MOVED 339 10.0.129.186:6379
5.2 读写分离
- 实现方式,需要对客户端进行以下修改
- 维护每个主节点可用的从节点列表(cluster slave master-nodeId 可以获取到主节点下所有从节点的信息)
- 读命令进行路由到从节点
- 从节点新建的连接开启readonly状态
- 其他替代方案
- 部署多套redis集群,客户端多写来维护;读选择距离最近的redis集群
6 手动故障转移
6.1 操作方式
在从节点上执行cluster failover,客户端请求会有短暂的阻塞,但不会丢失数据。流程如下:
- 从节点通知主节点停止处理请求
- 主节点发送给对应从节点,延迟复制的数据
- 从节点同步了该数据,直到主从复置的偏移量一致【保证数据不丢失】
- 从节点立刻发起投票选举(因为这个执行cluster failover的从节点是唯一的,所以不需要延迟选举)。选举成功之后变成主节点,并向集群广播
- 旧节点收到消息后更新自身配置为从节点,解除客户端请求阻塞,这些请求会被重定向到新的主节点上
- 旧节点向新的主节点发起全量复制流程
6.2 应用场景
- 主节点所在机器要迁移到新的机器
- 自动故障转移失败,通过手动转移故障可以恢复部分节点。自动故障转移失败的场景:
- 主节点和对应的从节点全部故障了
- 健康的从节点没有故障转移的资格,主从复制的短线时间超过:(server.repl_ping_slave_period * 1000) +
(server.cluster_node_timeout * server.cluster_slave_validity_factor) - 从节点的故障选举失败,没有在cluster_node_timeout*2时间内完成
- 集群内超过半数以上的主节点同时故障了
6.3 操作命令
cluster failover:没有实际的failure,但是希望master发生主从切换(具体哪一个从提升为主,看在哪一个主上执行cluster failover),切换是一个安全的方式,没有任何数据丢失。工作的流程见下。最终,旧的master的client连接会自动地转移到新的master;只有旧master的所有replication stream同步完成,副本才会变成新的master。
- step1 副本告诉主:停止接受来自client的查询请求
- step2 主回复副本当前的replication offset
- step3 副本等待replication offset和主的一致,保证主的数据都被同步过来了
- step4 副本开始failover,包含一个来自多数master的configuration epoch,然后广播新的配置文件
- step5 老的master 收到配置文件的更新:解锁他的client,开始回复redirection messages告诉client去找新的master
cluster failover force:
- 从节点收到该请求,直接发起选举,不需要跟主确定主从偏移量(从节点复制延迟的数据会丢失)
- 从节点选举成功之后成为主并开启广播
cluster failover takeover:
集群内超过半数以上的主都挂了,没法投票。从节点收到该请求,不再进行选举流程而是直接更新本地配置纪元并替换主节点
因为takeover模式没有通过领导选举,可能配置纪元会存在冲突
- 如果有冲突,集群会以nodeId更大的为准,可能会导致丢数据(网络分区恢复后,会出现拥有相同slot的两个主节点)
附录
不好意思,我又要推荐了哈哈
发现github上一个分析的很细致的资料,这个人总结的东西有点深度和不同,喜欢的可以自取:
https://github.com/moooofly/MarkSomethingDown
边栏推荐
- Redis的数据结构
- swagger文档配置
- Haproxy+kept cluster setup 02
- Minimap plug-in
- Three characteristics
- 简易入手《SOM神经网络》的本质与原理
- Ilruntime learning - start from scratch
- Golang time format sorting
- [set theory] order relation (the relation between elements of partial order set | comparable | strictly less than | covering | Haas diagram)
- 【云原生】微服务之Feign的介绍与使用
猜你喜欢
php-fpm软件的安装+openresty高速缓存搭建
Mall management system of database application technology course design
Display terrain database on osgearth ball
the installer has encountered an unexpected error installing this package
Unity2019_ Lighting system
Unity2019_ Natural ambient light_ Sky box
Flex flexible box layout
unity2019_ Input management
Youyou1 of xlua knapsack system
jupyter远程服务器配置以及服务器开机自启
随机推荐
[K & R] Chinese Second Edition personal questions Chapter1
php-fpm软件的安装+openresty高速缓存搭建
Delete the last character of the string in golang
C language - Introduction - essence Edition - take you into programming (I)
数据库应用技术课程设计之商城管理系统
The general trend of data news releases the power of visual reporting ----- essays after reading
Golang的range
使用 FileChannel 进行文件的复制拷贝
unity2019_ Input management
Dotween plug-in
WPF:解决MaterialDesign:DialogHost 无法关闭问题
GIS实战应用案例100篇(七十八)-多规合一数据库设计及数据入库
Are you still watching the weather forecast on TV?
My touch screen production "brief history" 1
What does (+) in Oracle mean
Golang 字符串分割,替换和截取
Flex flexible box layout
YOLO系列 --- xml2txt脚本
Display terrain database on osgearth ball
freetype库的移植