Redis高可用系列
概念
Redis Replication
用于保证多个Redis节点的数据同步,实现缓存数据的读写分离,当主节点故障时,不影响对缓存数据的读取,从而降低故障影响。Redis支持一个主节点和多个副本的复制架构以及级联的复制架构。
工作机制
当我们在Master上写入数据时,Master向副本发送命令流以同步数据。Redis默认使用异步复制以保证性能,并且复制的工作是由单独的进程完成的,不影响对数据的读写操作。
Redis的Master拥有一个随机数作为复制ID,每次实例作为主实例从头开始重新启动或副本被提升为主实例时,都会为该实例生成一个新的复制 ID,并采用偏移量来记录数据的变更历史,从而实现数据的增量同步。
对于设置了过期时间的键,Redis并不依赖于多个节点的时间同步,而是等Master中该键过期时,生成一个DEL命令并同步到副本以达到驱逐的目的。
演示环境
下面演示一个Master和两个副本的复制过程,Redis使用7.0.0
版本。
IP地址 | |
---|---|
主节点 | 192.168.1.201 |
副本1 | 192.168.1.202 |
副本2 | 192.168.1.203 |
安装
下载Redis并解压缩后,使用make install
命令进行安装。
修改配置
Redis默认将端口绑定在127.0.0.1
上,为了方便演示,编辑redis.conf
配置文件,修改端口绑定配置和禁用保护模式。
bind 0.0.0.0
protected-mode no
在副本节点上,还需增加Replication
相关的配置。
replicaof 192.168.1.201 6379
启动Redis
分别启动各节点Redis实例,可以在启动日志中看到主从复制相关的信息。
主节点日志
11172:M 10 Aug 2022 16:56:29.506 * Replica 192.168.1.202:6379 asks for synchronization
11172:M 10 Aug 2022 16:56:29.506 * Full resync requested by replica 192.168.1.202:6379
11172:M 10 Aug 2022 16:56:29.506 * Replication backlog created, my new replication IDs are 'a6a4a41009a1f9ba9bb2817ff11f8ad0f1504d38' and '0000000000000000000000000000000000000000'
11172:M 10 Aug 2022 16:56:29.506 * Delay next BGSAVE for diskless SYNC
11172:M 10 Aug 2022 16:56:34.783 * Starting BGSAVE for SYNC with target: replicas sockets
11172:M 10 Aug 2022 16:56:34.785 * Background RDB transfer started by pid 11410
11410:C 10 Aug 2022 16:56:34.789 * Fork CoW for RDB: current 4 MB, peak 4 MB, average 4 MB
11172:M 10 Aug 2022 16:56:34.789 # Diskless rdb transfer, done reading from pipe, 1 replicas still up.
11172:M 10 Aug 2022 16:56:34.791 * Background RDB transfer terminated with success
11172:M 10 Aug 2022 16:56:34.791 * Streamed RDB transfer with replica 192.168.1.202:6379 succeeded (socket). Waiting for REPLCONF ACK from slave to enable streaming
11172:M 10 Aug 2022 16:56:34.791 * Synchronization with replica 192.168.1.202:6379 succeeded
副本节点日志
6926:S 10 Aug 2022 16:56:29.502 * MASTER <-> REPLICA sync started
6926:S 10 Aug 2022 16:56:29.502 * Non blocking connect for SYNC fired the event.
6926:S 10 Aug 2022 16:56:29.503 * Master replied to PING, replication can continue...
6926:S 10 Aug 2022 16:56:29.504 * Partial resynchronization not possible (no cached master)
6926:S 10 Aug 2022 16:56:34.783 * Full resync from master: a6a4a41009a1f9ba9bb2817ff11f8ad0f1504d38:14
6926:S 10 Aug 2022 16:56:34.786 * MASTER <-> REPLICA sync: receiving streamed RDB from master with EOF to disk
6926:S 10 Aug 2022 16:56:34.787 * MASTER <-> REPLICA sync: Flushing old data
6926:S 10 Aug 2022 16:56:34.787 * MASTER <-> REPLICA sync: Loading DB in memory
6926:S 10 Aug 2022 16:56:34.788 * Loading RDB produced by version 7.0.0
6926:S 10 Aug 2022 16:56:34.788 * RDB age 0 seconds
6926:S 10 Aug 2022 16:56:34.788 * RDB memory usage when created 0.91 Mb
6926:S 10 Aug 2022 16:56:34.788 * Done loading RDB, keys loaded: 0, keys expired: 0.
6926:S 10 Aug 2022 16:56:34.788 * MASTER <-> REPLICA sync: Finished with success
可以从日志内容发现,副本节点发起了复制的请求,主节点生成了新的复制ID,将数据写入了磁盘后开始了主从复制的操作,由于是首次启动,本次复制为全量复制。
测试验证
主节点写入测试数据:
192.168.1.201:6379> set hello world
OK
副本节点读取数据:
192.168.1.202:6379> get hello
"world"
由于副本节点默认是只读的,当我们向副本节点写入数据时,会得到错误提示:
192.168.1.202:6379> set hello redis
(error) READONLY You can't write against a read only replica.