高可用 Redis 集群部署
Mar 18, 2021 14:00 · 1399 words · 3 minute read

Linux 操作系统设置
-
修改 Linux backlog 设置
backlog 参数描述的是服务器端 TCP ESTABELLISHED 状态对应的全连接队列长度。
$ echo "net.core.somaxconn=65535" >> /etc/sysctl.conf $ sysctl -p -
关掉透明大页(THP)
$ echo never | sudo tee /sys/kernel/mm/transparent_hugepage/defrag $ echo never | sudo tee /sys/kernel/mm/transparent_hugepage/enabled
搭建主从 Redis 集群
Redis 原生支持主从库模式,保证数据副本的一致,主从库读写分离。
-
将 server1 设置为 Redis 集群主库,修改 redis 配置文件 /etc/redis.conf:
bind 0.0.0.0 appendonly yes appendfsync everysecappendonly打开 AOF 日志,开启持久化appendfsync设置 AOF 日志落盘时机always同步写盘,可靠性高但是对性能影响较大everysec每秒写盘,性能适中,宕机会丢失 1s 内的数据no先把日志写入缓冲区,又操作系统代理写盘,性能最好但是宕机会丢失比较多的数据
-
将 server2 和 server3 设置为 Redis 集群从库,修改 redis 配置文件 /etc/redis.conf:
bind 0.0.0.0 appendonly yes appendfsync everysec slaveof ${server1_ip} 6379 -
在所有节点上启动 redis 进程:
$ systemctl start redis && systemctl enable redis
主从库模式虽然通过读写分离避免了数据不一致的问题,但还是面临主库故障的风险。
从库第一次与主库同步会全量复制,此时主库会生成和传输 RDB 文件,如果从库数量很多而且都和主库全量复制,会导致主库忙于 fork 子进程生成 RDB 文件,阻塞主线程处理请求,从而导致主库响应速度变慢,而且 RDB 文件传输还会占用大量网络带宽。可以选用“主-从-从”模式将主库生成和传输 RDB 文件的压力以级联的方式分散到从库上。
搭建哨兵集群
哨兵是 redis 一种特殊的运行模式,负责监控、选主与通知。
- 监控:周期性地给所有主从库发送心跳(PING 命令),如果从库未正常响应,就将其标记为“下线状态”;如果主库未正常响应,除标记下线外还会切换主库。
- “主观下线(sdown)”:当前哨兵主库/从库对心跳响应超时。
- “客观下线(odown)”:大多数哨兵实例都判断主库已经主观下线,只有主库被标记为客观下线时才会触发主从切换
- 选主:按一定的规选择一个从库实例作为新的主库。
- 通知:哨兵将新主库的信息发送给其他从库,让它们与新主库建立主从关系和复制数据;将新主库的连接信息发送给客户端。
为了避免哨兵故障后无法切换主从库,以及降低主库下线的误判几率,我们也需要多个哨兵实例组成哨兵集群。
-
在所有节点上修改 redis 哨兵配置文件 /etc/redis-sentinel.conf:
bind 0.0.0.0 sentinel monitor mymaster ${server1_ip} 6379 2 sentinel down-after-milliseconds mymaster 5000 sentinel failover-timeout mymaster 10000sentinel monitor <master-name> <ip> <redis-port> <quorum>master-name主库名称<ip> <redis-port>哨兵监控的主库 IP 与端口<quorum>赞成票数,一般为哨兵数量 / 2 + 1
down-after-milliseconds主观下线判断时间failover-timeout故障切换超时时间
-
在所有节点上启动 redis 哨兵进程:
$ systemctl start redis-sentinel && systemctl enable redis-sentinel
通过 SENTINEL get-master-addr-by-name <master-name> 来查询当前主库:
$ redis-cli -p 26379
127.0.0.1:26379> ping
PONG
SENTINEL get-master-addr-by-name mymaster
1) "10.211.55.33"
2) "6379"
手动关掉当前主库 systemctl stop redis
$ tail -f /var/log/redis/sentinel.log
1538:X 15 Mar 22:15:26.179 # +sdown master mymaster 10.211.55.33 6379
1538:X 15 Mar 22:15:26.271 # +new-epoch 48
1538:X 15 Mar 22:15:26.272 # +vote-for-leader 6e4877799e0fd14c5d2ae4b92d3d13fcd5ae47d5 48
1538:X 15 Mar 22:15:27.287 # +odown master mymaster 10.211.55.33 6379 #quorum 3/2
1538:X 15 Mar 22:15:27.287 # Next failover delay: I will not start a failover before Mon Mar 15 22:15:47 2021
1538:X 15 Mar 22:15:27.331 # +config-update-from sentinel 6e4877799e0fd14c5d2ae4b92d3d13fcd5ae47d5 10.211.55.34 26379 @ mymaster 10.211.55.33 6379
1538:X 15 Mar 22:15:27.331 # +switch-master mymaster 10.211.55.33 6379 10.211.55.32 6379
1538:X 15 Mar 22:15:27.331 * +slave slave 10.211.55.34:6379 10.211.55.34 6379 @ mymaster 10.211.55.32 6379
1538:X 15 Mar 22:15:27.331 * +slave slave 10.211.55.33:6379 10.211.55.33 6379 @ mymaster 10.211.55.32 6379
1538:X 15 Mar 22:15:32.378 # +sdown slave 10.211.55.33:6379 10.211.55.33 6379 @ mymaster 10.211.55.32 6379
从哨兵的日志中看到主库从 10.211.55.33 切换到了 10.211.55.32。
哨兵选主过程
-
筛选
-
检查从库的网络连接状况
down-after-milliseconds就是最大连接超时时间,当断连次数超过一定阈值,此从库会被筛掉。
-
-
打分,一共三轮,只要有一轮某个从库得分最高就会直接被选为主库,不会进入下一轮
-
从库优先级
通过
slave-priority参数给从库设置优先级,优先级最高的从库得分高 -
从库复制进度
和主库同步进度最接近的从库得分高
-
从库 ID 号
ID 号最小的从库得分高
-
-
通知
哨兵将新主库的地址写入自己实例的 pub/sub (switch-master)中,客户端需要订阅这个 pub/sub,可以感知到主库发生切换并拿到最新的主库地址。所以 redis 客户端一般会连接哨兵来获取主库相关信息。