1 主从复制
redis.conf 配置 slaveof 启动成为 slave,只读。并且 slave 本身也可以接受别的 slave 的 PSYNC,减轻 master 负担。
- slave 尝试增量同步失败,发送 PSYNC 到 master
- master 收到 PSYNC,执行 BGSAVE,后台生成rdb文件
- master 收到新的写命令,记录到缓存
- master 发送 rdb文件 到 slave
- master 发送缓存中的写命令到 slave,并一直保持增量同步
1.1 主从延迟
- 从库设置 lave-serve-stale-data=yes 为 no,当从库同主机失去连接,或者复制正在进行时,会拒绝请求
- 外部监控复制偏移量,将流量引导到偏移量较小的从库
2 哨兵
配置 sentinel.conf 启动为哨兵,可以监控集群,并且自动故障转移。
如果 master 挂了,执行主从切换:
- sentinel 每秒向 instance 发送 PING 命令做心跳检测
- sentinel 将超时未响应的 master 标记为 sdown
- sentinel 每2秒向一个 channel 发布、接收拓扑结构
- 当 quorum 个 sentinel 确认 master 进入 sdown,该 master 标记为 odown,其中一个 sentinel 会通过 Raft 算法投票给自己成为本次故障转移的 leader
- leader sentinel 将 offset大的 slave 选为 master,执行主从切换,并广播 channel
3 集群模式
3.1 客户端分片
随手记的 redis 集群于2012年搭建,当时 redis-cluster 还未推出,所以选择了 ShardJedis 实现客户端分片。
集群有4个节点用作JMS,14个节点用作缓存,这些都是 master,位于铜牛机房。
每一个 master 都有对应的一个 slave 在马驹桥机房,3个哨兵分别在铜牛、马驹桥、太和桥。
缺点:集群扩容后,会引起小范围的缓存击穿。
3.2 代理分片
3.3 服务端分片
配置 redis.conf 的 cluster-enabled yes 开启集群模式。
- 命令 cluster addslots 将 16384 个 slot 分配给各节点,分配结果记录在 bitmap
- Redis 收到请求,计算
slot = CRC16(key) mod 16384
,根据 bitmap 找出 slot 对应节点,并告知 client - 扩容、缩容,会引发数据迁移,过程对 client 透明
3.3.1 为什么是 16384 个哈希槽
为了表示 16384 个哈希槽,bitmap 大小为 16384/8 = 2048B = 2KB。
集群内节点之间的心跳包需要携带完整的 bitmap,那么 2KB 刚刚好,再大就会打满宽带了。
4 慢日志
命令执行超过5毫秒记录慢日志
CONFIG SET slowlog-log-slower-than 5000
只保留最近1000条慢日志
CONFIG SET slowlog-max-len 1000
查询最近5条慢日志
SLOWLOG get 5
- 执行时间复杂度高的命令。监控CPU使用率很高,但请求量不大。
- 存储大key。慢查询日志发现低复杂度的命令,比如 SET、DELETE。
- 集中过期
- 实例内存达到上限
- fork耗时严重
- 绑定CPU
- 开启AOF
- 开启Swap
- 网卡负载过高