redis集群如何做故障转移
redis sentinel
sentinel对redis数据节点和其他sentinel节点做定时监控,客户端连sentinel节点以获取数据节点的信息。如果心跳超过一段时间没回复,sentinel认为该节点主观下线,只有主节点主观下线,且sentinel之间互相通气发现超过一定数量的sentinel都判定为主观下线,则该主节点客观下线,才会开始故障转移。
- sentinel节点根据raft协议,先选取一个leader节点来操作本次的故障转移。
- sentinel leader节点根据从节点的priority,复制偏移量最大等判断选择runid最小的节点作为新的主节点,并通知,该从节点接到升级为主节点恢复后,再通知其他从节点更新主节点。
redis cluster
多个数据主节点也充当sentinel角色,互相之间心跳机制,然后根据主观下线,客观下线,再做failover, 类似。
redis集群主从同步的过程
- 第一次全量复制,master生成RDB发送给slave
- 增量复制,master,slave都维护一个环形的数据更新缓冲区,master记录写的位置,slave记录读的位置,两个位置的偏移差就是主从延迟的体现,从库会发送主库自己读的位置,主库会把这个位置到自己写位置间偏移量的数据都发送给从库
(redis-主从)[https://www.cnblogs.com/rachel-aoao/p/redis_master_slave.html]
redis大key问题如何应对
大key有哪些情况
- 单个key的value值很大
- 集合key(list, hash, set, zset)的数量很大(>5000)
- key本身数量很大(上亿)
大key有哪些危害
- 内存占用,大量占用内存资源
- 网络传输,大key在网络传输时需要消耗更多的时间和带宽,增加网络延时
- 阻塞,大key可能导致redis单线程阻塞,影响其他客户端的请求处理速度
治理方法
拆分:将一个string或者一个hash,根据不同field拆成多个hash,原key作为key前缀,添加其他的为后缀(预分桶);将一个大集合拆成多个小集合。
分页获取:使用lrange
命令分页获取列表key的数据
设置过期时间
使用压缩算法,如gzip
redis zset的应用
延时队列
zset按照score进行排序,当score表示该操作预期进行的时间戳时,可用作延时队列。consumer起一个线程循环取zset第一个值,若当前时间戳大于该值,则取出消费。
排行榜
一小时最热门榜单,score是评论点击数。
限流
todo
线上规范,最佳实践
key设计
- 不要包含特殊字符如空格,换行,单双引号
- 严格控制key的生命周期,redis不是垃圾桶,设置过期时间,防止集中过期,不过期数据关注idletime
- 以业务名为前缀防止key冲突,用冒号分割
- 尽量简洁,key数量大时,内存占用也不容忽视
value设计
- 不要有bigKey(防止网卡流量和慢查询),字符串控制在10KB,集合控制在5000内
- 非字符串的bigKey,不要使用
DEL
删除,使用hscan
,sscan
,zscan
方式渐进式删除
命令使用
- O(N)命令关注N,如
hgetall
,lrange
,smembers
,zrange
,sinter
,遍历需求使用hscan
,sscan
,zscan
- 慎用Pub/Sub机制, 不能保证消息的可靠性,服务器重启,客户端断连都可能造成消息丢失,大集群使用publish消息会在集群间广播,可能形成集群间流量风暴
客户端接入
- sentinel模式,使用sentinel节点发现数据节点,禁止直连
- 集群模式,客户端必须配置路由更新规则
- 集群默认淘汰策略为volatile-lru
- 避免打开读写分离,redis性能极高,单点qps可达到10w,读写分离只会造成业务同时受到主从节点影响,redis采用异步复制机制,可能数据不一致。
- jedis资源池配置
maxTotal/maxActive
:资源池中最大连接数,默认8,建议根据需要设置( qps/主节点数/ (1000/每条命令的预计耗时ms)*(3/2))与maxIdle、minIdle相同,且不超过业务线程数量;原则上不要超过50;例如: 主节点数:10,命令耗时:0.33ms, 10个连接的qps为: 10 * (1000ms/0.33ms) * 10 = 30w
connectionTimeout
:连接超时,默认500ms,合理配置,连接超时最好不要低于500ms,线上出现多起因为连接超时过短,造成大量建连引发Redis雪崩
|