集群总结:
1、Redis Cluster数据分区规则采用虚拟槽方式(16384个槽),每个节点负责一个部分槽和相关数据,实现数据和请求的负载均衡。
2、搭建集群划分四个步骤:准备节点、节点握手、分配槽、复制。redis-trib.rb工具用于快速搭建集群。
3、集群伸缩通过在节点之间移动槽和相关数据实现
- 扩展时根据槽迁移计划把槽从源节点迁移到新节点
- 收缩时如果下线的节点有负责的槽需要迁移到其他节点,在通过cluster forget命令让集群内所有节点忘记被下线节点
4、使用smart客户端操作集群达到通信效率最大化,客户端内部负责计算维护键值-> 槽 -> 节点的映射,用于快速定位到目标节点。
5、集群自动故障转移过程分为故障发现和节点恢复,节点下线分为主观下线和客户下线,当超过半数主节点认为故障节点为主观下线时标记它为客观下线状态。从节点负责对客观下线的主节点触发故障恢复流程,保证集群的可用性。
6、开发运维常见问题包括:超大规模集群带宽消耗、pub/sub广播问题,集群倾斜问题,单机和集群对比等。
思考-分布式Redis不一定好
1、Redis Cluster:满足容量和性能的扩展性,很多业务“不需要”
大多数是客户端性能会“降低”
命令无法跨节点使用:mget、keys、scan、flush、sinter等
Lua和事务无法跨节点使用
客户端维护更复杂:SDK和应用本身消耗(例如更多的连接池)
2、很多场景Redis Sentinel 已经足够好
1、节点和槽分配不均
redis-trib.rb info ip:port 查看节点、槽、键值分布
redis-trib.rb rebalance ip:port 进行均衡(谨慎使用)
2、不同槽对应键值数量差异较大
CRC16 正常情况下比较均匀
可能存在 hash_tag
cluster countkeysinslot {slot} 获取槽对应键值个数
3、包含bikey
bigkey :例如大字符串、几百万的元素的hash、set等
从节点 :redis-cli --bigkeys
优化 :优化数据结构
4、请求倾斜
热点key:重要的key或者bigkey
优化:
避免bigkey
热键不要用hash_tag
当一致性不高时,可以用本地缓存 + MQ
5、集群读写分离
(1)只读链接:集群模式的从节点不接受任何读写请求
-重定向到负责槽的主节点
-readonly命令可以读:连接级别命令
(2)读写分离:更加复杂
- 同样的问题:复制延迟、读取过期数据、从节点故障
- 修改客户端:cluster slaves {nodeId}
6、离线/在线迁移
(1)官方迁移工具:redis-trib.rb import
- 只能从单机迁移到集群
- 不支持在线迁移:source需要停写
- 不支持断点续传
- 单线程迁移:影响速度
./redis-trib.rb import --form 127.0.0.1:6388 --copy 127.0.0.1:7000
(2)在线迁移
- 唯品会 redis-migrate-tool
- 豌豆荚:redis-port
7、集群限制
key批量操作支持有限:例如mget、mset必须在一个slot
key事物和Lua支持有限:操作的key必须在一个节点
key是数据分区的最小粒度:不支持bigkey分区
不支持多个数据库:几圈模式下只有一个db 0
复制只支持一层:不支持树形复制结构