Redis:复制,第二部分 – 主从复制和 Redis Sentinel
Redis 复制设置示例,包含基本的主从复制和 Redis Sentinel
第一部分 – Redis:复制,第一部分 – 概述。复制与分片。Sentinel 与 Cluster。Redis 拓扑。
整个故事始于我们决定摆脱 memcached
。
目前,我们的后端服务器上运行着 memcached
和 Redis。
memcached
和 Redis 实例都作为独立应用程序运行,即它们没有连接到任何类型的复制,这会导致一个问题
- 我们有三个后端主机,位于 AWS Application Load Balancer 后面
- ALB 启用了 粘性会话,但它使用的是我们的移动应用程序(iOS/Android)忽略的 cookie
- 因此,当客户端向后端发出请求时 – 有时,它可能会获得已在 Redis 或
memcached
的另一个后端主机上被删除/更新的缓存数据
自从我们从只有一个主机且尚未更新的旧基础设施迁移了后端应用程序以来,我们一直采用这种方案,尽管它早已在我们的计划中。
目前,为了解决这些问题,我们在后端有一堆“技巧”,它们会进行额外的检查以确保数据是最新的,现在为了摆脱它们,我们决定
- 完全摆脱
memcached
,因为 Redis 可以用于memcached
现在使用的功能 - 在所有主机上配置 Redis 复制
下面的帖子将描述这样的设置。
第一个示例 – 使用基本的 Master-Slave 复制,第二个示例 – Sentinel 的设置和配置。
这里将使用带有 Debian 9 的 AWS EC2 实例。
为了与 Redis 主机协同工作,将使用三个域名 – redis-0.setevoy.org.ua 作为主节点,redis-1.setevoy.org.ua 和 redis-2.setevoy.org.ua 作为其两个从节点。
在最小的设置中,可以只有一个从节点,但由于第二个示例将是 Sentinel – 让我们从一开始就设置三个。
基本主从复制
通过这种方式,从节点将是主节点的只读副本,保留添加到主节点上的相同数据。
主节点会将所有数据更新发送给其从节点 – 新的键过期等。
如果主节点和从节点之间的链接断开 – 从节点将尝试重新连接到主节点并进行部分同步,以更新从上一个同步中断的地方开始的数据。
如果无法进行部分同步 – 从节点将请求主节点进行完全同步,主节点将执行其数据全快照并将其发送给该从节点,之后,将恢复正常的同步。
这里有几点需要注意
- 一个主节点可以有多个从节点
- 从节点可以接受来自其他从节点的连接,形成一种“级联”复制节点 – 顶层是主节点,中间是(一个或多个)从节点,底层是(一个或多个)从节点
- 强烈建议在主节点上启用数据持久化以避免数据丢失 – 请参阅 主节点关闭持久化时的复制安全性
- 从节点默认将以只读模式工作,请参阅 只读从节点
Redis 主节点配置
安装 Redis
root@redis-0:/home/admin# apt -y install redis-server
编辑 /etc/redis/redis.conf,并在 bind
中设置要监听的接口
...
bind 0.0.0.0
...
您可以在此处指定多个 IP,用空格分隔
...
bind 127.0.0.1 18.194.229.23
...
其他有价值的选项
port 6379
– 很明显,但请记住slave-read-only yes
– 从节点将以只读模式工作,不影响主节点requirepass foobared
– 主节点授权密码appendonly yes
和appendfilename "appendonly.aof"
– 降低数据丢失的风险,请参阅 Redis 持久化
重启服务
root@redis-0:/home/admin# systemctl restart redis
使用 -a
加上密码进行检查
root@redis-0:/home/admin# redis-cli -a foobared ping
PONG
检查数据复制状态
root@redis-0:/home/admin# redis-cli -a foobared info replication
Replication
role:master
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
添加新数据
root@redis-0:/home/admin# redis-cli -a foobared set test 'test'
OK
取回数据
root@redis-0:/home/admin# redis-cli -a foobared get test
"test"
好的 – 这里一切正常。
Redis 从节点配置
在剩下的两个主机上,进行从节点配置。
对两者来说都将是相同的 – 只需重复即可。
安装 Redis
root@redis-1:/home/admin# apt -y install redis-server
编辑 /etc/redis/redis.conf
...
slaveof redis-0.setevoy.org.ua 6379
...
masterauth foobared
...
requirepass foobared
...
这里
slaveof
– 设置主节点的 IP 地址和端口masterauth
– 主节点的认证密码requirepass
– 此副本的认证密码
重启服务
root@redis-1:/home/admin# systemctl restart redis
检查其状态
root@redis-1:/home/admin# redis-cli -a foobared info replication
Replication
role:slave
master_host:redis-0.setevoy.org.ua
master_port:6379
master_link_status:up
master_last_io_seconds_ago:5
master_sync_in_progress:0
...
检查日志
root@redis-1:/home/admin# tail -f /var/log/redis/redis-server.log
16961:S 29 Mar 10:54:36.263 * Connecting to MASTER redis-0.setevoy.org.ua:6379
16961:S 29 Mar 10:54:36.308 * MASTER <-> SLAVE sync started
16961:S 29 Mar 10:54:36.309 * Non blocking connect for SYNC fired the event.
16961:S 29 Mar 10:54:36.309 * Master replied to PING, replication can continue...
16961:S 29 Mar 10:54:36.310 * Partial resynchronization not possible (no cached master)
16961:S 29 Mar 10:54:36.311 * Full resync from master: 93585eeb7e32c0550c35f8d4935c9a18c4177ab9:1
16961:S 29 Mar 10:54:36.383 * MASTER <-> SLAVE sync: receiving 92 bytes from master
16961:S 29 Mar 10:54:36.383 * MASTER <-> SLAVE sync: Flushing old data
16961:S 29 Mar 10:54:36.383 * MASTER <-> SLAVE sync: Loading DB in memory
16961:S 29 Mar 10:54:36.383 * MASTER <-> SLAVE sync: Finished with success
与主节点的连接已建立,同步已完成 – 好的,检查数据
root@redis-1:/home/admin# redis-cli -a foobared get test
"test"
数据存在 – 这里也一切正常。
更改从节点 => 主节点角色
如果主节点发生故障 – 您需要切换一个从节点来成为新的主节点。
如果您尝试在当前的从节点上添加任何数据 – Redis 将会报错,因为从节点处于只读模式
...
slave-read-only yes
...
尝试添加一些内容
root@redis-1:/home/admin# redis-cli -a foobared set test2 'test2'
(error) READONLY You can't write against a read only slave.
现在连接到从节点
root@redis-1:/home/admin# redis-cli
Authorize
127.0.0.1:6379> auth foobared
OK
禁用从节点角色
127.0.0.1:6379> slaveof no one
OK
现在检查其状态
127.0.0.1:6379> info replication
Replication
role:master
connected_slaves:0
master_repl_offset:1989
repl_backlog_active:0
repl_backlog_size:1048576
再次添加一个新键
127.0.0.1:6379> set test2 'test2'
OK
并取回它
127.0.0.1:6379> get test2
"test2"
请记住,由于我们直接在 Redis 节点上进行了这些更改 – 在其重启后,它将再次成为从节点,因为它仍在其 /etc/redis/redis.conf 文件中通过 slaveof
参数设置。
Redis Sentinel
现在让我们在复制中添加 Sentinel,它将监控 Redis 节点并自动执行角色切换。
整体方案如下
这里
- M1 = 主节点
- R1 = 副本 1 / 从节点 1
- R2 = 副本 2 / 从节点 2
- S1 = Sentinel 1
- S2 = Sentinel 2
- S3 = Sentinel 3
M1 和 S1 – 将在 redis-0 上,R1 和 S2 – 在 redis-1 上,R2 和 S3 – 在 redis-2 上。
运行 Sentinel
要运行 Sentinel 守护进程,可以使用 redis-server
加上单独的配置文件 – /etc/redis/sentinel.conf。
首先,让我们在 Redis 主节点上创建这样的配置文件
sentinel monitor redis-test redis-0.setevoy.org.ua 6379 2
sentinel down-after-milliseconds redis-test 6001
sentinel failover-timeout redis-test 60000
sentinel parallel-syncs redis-test 1
bind 0.0.0.0
sentinel auth-pass redis-test foobared
这里
monitor
– 要监控的主节点地址,2 是 Sentinel 实例数量,用于做出决策down-after-milliseconds
– 主节点被视为出现故障后经过的时间failover-timeout
– 更改从节点=>主节点角色后等待的时间parallel-syncs
– 主节点更改后同步从节点的并行数量
运行它:
root@redis-0:/home/admin# redis-server /etc/redis/sentinel.conf --sentinel
...
10447:X 29 Mar 14:15:53.193 # WARNING: The TCP backlog setting of 511 cannot be enforced
because /proc/sys/net/core/somaxconn is set to the lower value of 128.
10447:X 29 Mar 14:15:53.195 # Sentinel ID is e9fb72c8edb8ec2028e6ce820b9e72e56e07cf1e
10447:X 29 Mar 14:15:53.195 # +monitor master redis-test 35.158.154.25 6379 quorum 2
10447:X 29 Mar 14:15:53.196 * +slave slave 3.121.223.95:6379 3.121.223.95 6379
@ redis-test 35.158.154.25 6379
10447:X 29 Mar 14:16:43.402 * +slave slave 18.194.45.17:6379 18.194.45.17 6379
@ redis-test 35.158.154.25 6379
使用 26379 端口检查 Sentinel 的状态
root@redis-0:/home/admin# redis-cli -p 26379 info sentinel
Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=redis-test,status=ok,address=35.158.154.25:6379,slaves=2,sentinels=1
这里
master0:name=redis-test,status=ok
– 主节点 UPslaves=2
– 它有两个从节点sentinels=1
– 目前只有一个 Sentinel 实例在运行
您可以在这里获得一些基本信息,例如 – 主节点的 IP
root@redis-0:/home/admin# redis-cli -p 26379 sentinel get-master-addr-by-name redis-test
1) "35.158.154.25"
2) "6379"
现在,在两个从节点上重复 Sentinel 的启动,使用与我们在主节点上相同的配置,在 Sentinel 的日志中,您应该会看到新的实例连接
...
10447:X 29 Mar 14:18:40.437 * +sentinel sentinel fdc750c7d6388a6142d9e27b68172f5846e75d8c
172.31.36.239 26379 @ redis-test 35.158.154.25 6379
10447:X 29 Mar 14:18:42.725 * +sentinel sentinel ecddb26cd27c9a17c4251078c977761faa7a3250
172.31.35.218 26379 @ redis-test 35.158.154.25 6379
...
再次检查状态
root@redis-0:/home/admin# redis-cli -p 26379 info sentinel
Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=redis-test,status=ok,address=18.194.229.23:6379,slaves=2,sentinels=3
sentinels=3
– 好的。
此外,Sentinel 将在需要时执行其自身的设置更新
root@redis-1:/home/admin# cat /etc/redis/sentinel.conf
sentinel myid fdc750c7d6388a6142d9e27b68172f5846e75d8c
sentinel monitor redis-test 35.158.154.25 6379 2
sentinel down-after-milliseconds redis-test 6001
bind 0.0.0.0
sentinel failover-timeout redis-test 60000
Generated by CONFIG REWRITE
port 26379
dir "/home/admin"
sentinel auth-pass redis-test foobared
sentinel config-epoch redis-test 0
sentinel leader-epoch redis-test 0
sentinel known-slave redis-test 18.194.45.17 6379
sentinel known-slave redis-test 3.121.223.95 6379
sentinel known-sentinel redis-test 172.31.35.218 26379 ecddb26cd27c9a17c4251078c977761faa7a3250
sentinel known-sentinel redis-test 172.31.47.184 26379 e9fb72c8edb8ec2028e6ce820b9e72e56e07cf1e
sentinel current-epoch 0
这里添加了 sentinel myid fdc750c7d6388a6142d9e27b68172f5846e75d8c 行,以及 #Generated by CONFIG REWRITE 之后的整个块。
Redis Sentinel 自动故障转移
现在让我们看看如果主节点出现故障会发生什么。
您可以通过调用 kill -9
手动执行此操作,或者使用 redis-cli
并发送带有秒数的 DEBUG
命令使主节点“下线”,或者发送信号来杀死主节点。
root@redis-0:/home/admin# redis-cli -a foobared DEBUG sleep 30
主节点上的 Sentinel 日志
...
10447:X 29 Mar 14:24:56.549 # +sdown master redis-test 35.158.154.25 6379
10447:X 29 Mar 14:24:56.614 # +new-epoch 1
10447:X 29 Mar 14:24:56.615 # +vote-for-leader ecddb26cd27c9a17c4251078c977761faa7a3250 1
10447:X 29 Mar 14:24:56.649 # +odown master redis-test 35.158.154.25 6379 #quorum 3/2
10447:X 29 Mar 14:24:56.649 # Next failover delay:
I will not start a failover before Fri Mar 29 14:26:57 2019
10447:X 29 Mar 14:24:57.686 # +config-update-from sentinel
ecddb26cd27c9a17c4251078c977761faa7a3250 172.31.35.218 26379 @ redis-test 35.158.154.25 6379
10447:X 29 Mar 14:24:57.686 # +switch-master redis-test 35.158.154.25 6379 3.121.223.95 6379
10447:X 29 Mar 14:24:57.686 * +slave slave 18.194.45.17:6379 18.194.45.17 6379
@ redis-test 3.121.223.95 6379
10447:X 29 Mar 14:24:57.686 * +slave slave 35.158.154.25:6379 35.158.154.25 6379
@ redis-test 3.121.223.95 6379
10447:X 29 Mar 14:25:03.724 # +sdown slave 35.158.154.25:6379 35.158.154.25 6379
@ redis-test 3.121.223.95 6379
...
目前,我们对这里这两行感兴趣
...
10384:X 29 Mar 14:24:57.686 # +config-update-from sentinel
ecddb26cd27c9a17c4251078c977761faa7a3250 172.31.35.218 26379 @ redis-test 35.158.154.25 6379
10384:X 29 Mar 14:24:57.686 # +switch-master redis-test 35.158.154.25 6379 3.121.223.95 6379
...
Sentinel 执行了从节点到主节点的重新配置。
35.158.154.25 – 是旧的主节点,现在已失效,而 3.121.223.95 是一个新的主节点,从从节点中选举产生 – 它运行在 redis-1 主机上。
尝试在这里添加数据
root@redis-1:/home/admin# redis-cli -a foobared set test3 'test3'
OK
而对旧主节点(现在变成从节点)的类似尝试将导致错误
root@redis-0:/home/admin# redis-cli -a foobared set test4 'test4'
(error) READONLY You can't write against a read only slave.
让我们完全杀死一个节点,看看 Sentinel 现在会做什么
root@redis-0:/home/admin# redis-cli -a foobared DEBUG SEGFAULT
Error: Server closed the connection
Log
...
10447:X 29 Mar 14:26:21.897 * +reboot slave 35.158.154.25:6379 35.158.154.25 6379
@ redis-test 3.121.223.95 6379
嗯 – Sentinel 刚刚重启了那个节点
Sentinel 命令
命令 | 描述 |
sentinel masters | 列出所有主节点及其状态 |
sentinel master | 一个主节点的状态 |
sentinel slaves | 列出所有从节点及其状态 |
sentinel sentinels | 列出所有 Sentinel 实例及其状态 |
sentinel failover | 手动运行故障转移 |
sentinel flushconfig | 强制 Sentinel 将其配置重写到磁盘 |
sentinel monitor | 添加一个新主节点 |
sentinel remove | 从监视中删除主节点 |
相关链接
- Redis 复制
- Sentinel 配置文件的示例
- Redis Sentinel — 高可用性:从开发到生产您需要知道的一切:完整指南
- Redis Sentinel:使您的数据集高可用
- 如何运行 Redis Sentinel