一、集群完整性
cluster-require-full-coverage yes
- 要求集群中所有节点都在线
- 集群中所有16384个槽都在服务
才认为集群是完整的,才对外提供服务,默认值是yes
- 节点故障或正在故障转移时报如下❌:
(error)CLUSTERDOWN The Cluster is down - 大多数业务无法容忍,建议设置为no
新建集群中都设置为yes
shutdown 其中2个节点
cluster info
state:ok
#过一会儿
cluster info
state : fail
# 完整性只是针对key的操作不可用:
set hello world
(error)CLUSTERDOWN The Cluster is down
ping
PONG
二、带宽消耗
Gossip英[ˈɡɒsɪp]流言飞语; 闲言碎语; 说长道短; 闲聊;-
官方建议:上限1000个节点
-
节点间会交换 PING / PONG消息
-
不容忽视的带宽消耗
2. 取决于三个方面
- 消息发送频率:节点发现与其它节点最后通信时间超过cluster- node-timeout / 2时会直接发送ping消息
- 消息数据量:slots槽数组(2KB空间)和整个集群1/10的状态数据 (10个节点状态数据约1KB)
- 节点部署的机器规模:集群分布的机器越多且每台机器划分的 节点数越均匀,则集群内整体的可用带宽越高。
3. 一个例子
规模:节点200个、20台物理机(每台10个节点)
cluster- node-timeout = 15000,PING / PONG带宽为25M/b
cluster- node-timeout = 20000,PING / PONG带宽低于15M/b
4. 优化
- 避免使用集群:避免多业务使用集群,大业务可以集群。
- cluster- node-timeout : 考虑带宽和故障转移速率的均衡
- 尽量分配到多机器上:保证高可用和带宽
三、Pub / Sub广播
Pub / Sub 广播publish在集群每个节点广播:加重带宽
单独走一套Redis Sentinel
# 发布一条消息
redis-cli -p 7001 publish cluster_pubsub_test "hello"
#所有订阅了的节点都会受到如下消息
redis-cli -p [7000 ~ 7005] subscribe cluster_pubsub_test
1) "message"
2) "cluster_pubsub_test"
3) "hello"
四、数据倾斜
1. 数据倾斜:内存不均
数据倾斜1.1 原因
- 节点和槽分配不均
redis-cli --cluster info ip:port 查看节点、槽、键值的分布
redis-cli --cluster rebalance ip:port : 进行均衡(谨慎使用,会影响到客户端)
- 手动均衡实例:
$ redis-cli --cluster rebalance localhost:7000
>>> Performing Cluster Check (using node localhost:7000)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
*** No rebalancing needed! All nodes are within the 2.00% threshold.
- 不同槽对应的键值数不均匀,差异较大
1)CRC16正常情况下比较均匀
2)可能存在hash_tag
3) cluster contkeysinslot {slot} 获取槽对应键值个数
-
包含bigkey:hash、set、zset
1) 例如:大字符串,几百万元素 的hash、set等
2) 从节点:redis-cli --bigkeys
3)优化:优化数据结构
(1)大列表拆分:按日期、按hash -
内存相关配置不一致
ziplist,整数集合的优化;set,list,zset都有一些内存配置的优化参数,这会对redis来说节省一定的内存,但是没有再所有节点做优化,就会出现不均匀。
hash-max-ziplist-value
set-max-inset-entries 等
优化:定期检查配置的一致性
-
某节点的客户端缓冲区高,被执行了monitor这样的命令,也会出现类似不均匀。
-
key-value存在hash表中,key多的时候会存在扩容,rehash,会多出一个hash表,指针量很大,短暂的不均匀。
2. 请求倾斜:热点问题
1)热点key:重要的key或bigKey
2)优化
(1)避免bigkey
(2)热键不要用hash_tag
(3)当一致性不高时,可以用本地缓存 ➕ MQ
五、读写分离
1. 从节点只读连接:readonly
集群模式的从节点默认不接受任何请求
- 默认请求从节点上的key会重定向到负责槽的主节点
- 命令可以使从节点读:连接级别命令
#7004是7001的从节点
$ redis-cli -c -p 7004
127.0.0.1:7004> get world
-> Redirected to slot [9059] located at 127.0.0.1:7001
"hello"
127.0.0.1:7001> exit #重定向:注意标识变成7001
$ redis-cli -c -p 7004
127.0.0.1:7004> readonly
OK
127.0.0.1:7004> get world #未重定向:标识还是7004从节点
"hello"
2. 读写分离:更加复杂
- 同样的问题:复制延迟、读取过期数据、从节点故障
- 修改客户端:cluster.slaves {nodeId}
- 使用Redis Cluster进行读写分离成功很高。建议把节点规模扩大,而不是使用从节点(成本高)。或者是去维护一个NB的客户端(JedisCluster,也许JedisCluster已经实现可用了呢?): 维护一个池子,要清楚节点-槽之间的关系,跟redis-sentinel读写分离思想相同。
六、数据迁移
1.命令
$ redis-cli --cluster help
import host:port
--cluster-from <arg>
--cluster-copy
--cluster-replace
2.说明
- 只能从单机迁到集群
- 不支持在线迁移:source需要停写,否则迁移期间写入源节点数据无法传到集群中
- 不支持断点续传
- 单线程迁移:数据量大时影响速度
3.第三方工具在线迁移:
- 唯品会:redis-migrate-tool 「需要编译安装」
- 豌豆荚:redis-port。「GO 语言」
原理:单独起一个redis节点:伪装成被迁移节点的slave,即可以拿到全量数据,又可以得到更新数据,然后将更新数据同步给target节点,相当于source和target中间一个中转站,缓存更新。
七、集群 VS 单机
1. 集群限制
1)key批量操作支持有限:例如mget、mset必须在一个slot
2)key事物和Lua的支持有限:操作的key必须在一个节点。
3)key是数据分区的最小粒度:不支持bigKey分区。
4)不支持多个数据库:集群模式下只有一个db0。单机模式下不建议使用多数据库模式。
5)复制只支持一层,不支持树型复制结构。
2. 分布式Redis不一定好
1)Redis Cluster:满足容量和性能的拓展性,很多业务”不需要“
(1)大多数时,客户端性能会”降低“
(2)命令无法跨节点使用:mget、keys、scan、flush、sinter等
(3)Lua和事物无法跨节点使用
(4)客户端维护更复杂,SDK和应用本身消耗(例如更多的连接池)
2)很多场景Redis Sentinel已经足够好了
八、集群总结
- Redis cluster数据分区规则采用虚拟槽方式(16384个槽),每个节点负责一
部分槽和相关数据,实现数据和请求的负载均衡。 - 搭建集群划分四个步骤:准备节点、节点握手、分配槽、复制。
- redis-trib.rb工具用于快速搭建集群。Redis5.0版本中已内置集成。 - 集群伸缩通过在节点之间移动槽和相关数据实现。
- 扩容时根据槽迁移计划把槽从源节点迁移到新节点。
- 收缩时如果下线的节点有负责的槽需要迁移至其它节点,再通过cluster forget命令让集群内所有节点忘记被下线节点。
- 使用smart客户端操作集群达到通信效率最大化(非代理,直连),客户端内部负责计算维 护键->槽->节点的映射,用于快速定位到目标节点。
- 集群自动故障转移过程分为故障发现和节点恢复。节点下线分为主观下线和客观下线,当超过半数主节点认为故障节点为主观下线时标记它为客观下线状态。从节点负责对客观下线的主节点触发故障恢复流程,保证集群的可用性。
- 开发运维常见问题包括:超大规模集群带宽消耗,pub/sub广播问题,集
群倾斜问题,单机和集群对比等
网友评论