Redis 主从复制

Redis 集群有三种模式,分别是主从同步/复制、哨兵模式、Cluster(集群)。本章节将介绍 Redis 的主从复制,主从复制是高可用 Redis 的基础,哨兵和集群都是在主从复制基础上实现高可用的。主从复制主要实现了数据的多机备份,以及对读操作的负载均衡和简单的故障恢复。

Redis 通过持久化特性,保证了即使在服务器重启的情况下也不会丢失(或少量丢失)数据。因为持久化会把内存中的数据保存到硬盘上,重启 Redis 会从硬盘上加载数据到内存,恢复数据。但是由于数据是存储在一台服务器上的,如果这台服务器出现硬盘故障等问题,也会导致数据丢失。

为了避免单点故障,通常的做法是将数据库复制多个副本以部署在不同的服务器上,这样即使有一台服务器出现故障,其他服务器依然可以继续提供服务。为此,Redis 提供了复制功能,可以实现当一台数据库中的数据更新后,自动将更新的数据同步到其他服务器上的数据库中。

在主从复制的概念中,数据库分为两类,一类是主数据库(master),另一类是从数据(slave)。主数据可以进行读写操作,当写操做导致数据变化时自动将数据同步给从数据库。从数据库一般是只读的,并接收主数据同步过来的数据。一个主数据库可以拥有多个从数据库,而一个从数据库只能拥有一个主数据库。如下图:

主从复制的优点:

(1)主从结构具有读写分离,提高效率、数据备份,提供多个副本等优点

主从复制的缺点:

(1)不具备自动容错和恢复功能,主节点故障,集群则无法进行工作,可用性比较低,从节点升主节点需要人工手动干预

(2)写操作无法进行负载均衡

(3)存储能力受到单机的限制

主从复制流程

主从复制主要流程如下:

(1)从节点连接主节点,发送 SYNC 命令,请求同步数据。

(2)主节点收到 SYNC 命令后,启动后台线程,将自己的数据快照写入 RDB 文件,并将这段时间内的所有写命令缓存到内存中,这个时候主节点进入阻塞状态,等待快照文件写入磁盘并发送给从节点。

(3)当主节点的 RDB 文件写入磁盘后,将 RDB 文件发送给从节点。

(4)从节点接收到 RDB 文件后,将 RDB 文件载入内存中,再将主节点缓存的写命令依次执行。

(5)从节点每隔一段时间会发送 PSYNC 命令,请求主节点增量同步数据,主节点将从缓存中的增量命令发送给从节点。

(6)从节点执行增量命令,完成数据同步。

主从复制配置

该实例将在单台 Windows 环境服务器下演示 Redis 主从复制的配置,主从复制信息如下:

Master   127.0.0.1:6379
Slave1   127.0.0.1:6378
Slave2   127.0.0.1:6377

注意:下面默认你的 Redis 服务是全新安装的,笔者将给出最简单、最少的配置去开启 Redis 主从复制。

Master主服务

Master 服务器配置,只需要设置密码和端口。当如果你是在不同机器上面部署主从复制,则端口都不需要修改。配置如下:

# 设置端口
port 6379

# 设置 Master 密码,为了安全还是设置一下密码
requirepass "aaaaaa"

Slave从服务

下面配置两个从服务器,如下:

Slave1配置

如果 Master 服务器没有设置密码,则可以不用配置 masterauth。配置如下:

# 设置端口
port 6378

# 主从复制,使用 replicaof 使一个 Redis 实例成为另一个 Redis 服务器的副本。
#
#   +------------------+      +---------------+
#   |      Master      | ---> |    Replica    |
#   | (receive writes) |      |  (exact copy) |
#   +------------------+      +---------------+
#
# 1) Redis 复制是异步的,但你可以将主站配置为停止接受写入
# 2) 如果复制链接丢失的时间相对较短,Redis 复制能够与主站进行部分重新同步
# 3) 复制是自动的,不需要用户干预
#
# 下面语句表面当前 Redis 实例为 Slave 节点,它从 Master 节点 127.0.0.1:6379 同步数据
replicaof 127.0.0.1 6379

# 如果 Master 通过 requirepass 设置了保护密码,我们可以通过
# masterauth 告诉 Slave 在开始复制同步过程之前使用指定密码进行认证,否则主站会拒绝复制请求
masterauth "aaaaaa"

Slave2配置

如果 Master 服务器没有设置密码,则可以不用配置 masterauth。配置如下:

port 6377
replicaof 127.0.0.1 6379
masterauth "aaaaaa"

启动主从复制

启动 Master 服务

使用 redis-server.exe redis.windows.conf 命令启动 Redis 服务,启动日志如下:

[9636] 03 Apr 13:01:53.224 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
[9636] 03 Apr 13:01:53.224 # Redis version=5.0.14.1, bits=64, commit=ec77f72d, modified=0, pid=9636, just started
[9636] 03 Apr 13:01:53.224 # Configuration loaded
               _._
          _.-``__ ''-._
     _.-``    `.  `_.  ''-._           Redis 5.0.14.1 (ec77f72d/0) 64 bit
 .-`` .-```.  ```\/    _.,_ ''-._
(    '      ,       .-`  | `,    )     Running in standalone mode
|`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
|    `-._   `._    /     _.-'    |     PID: 9636
 `-._    `-._  `-./  _.-'    _.-'
|`-._`-._    `-.__.-'    _.-'_.-'|
|    `-._`-._        _.-'_.-'    |           http://redis.io
 `-._    `-._`-.__.-'_.-'    _.-'
|`-._`-._    `-.__.-'    _.-'_.-'|
|    `-._`-._        _.-'_.-'    |
 `-._    `-._`-.__.-'_.-'    _.-'
     `-._    `-.__.-'    _.-'
         `-._        _.-'
             `-.__.-'

[9636] 03 Apr 13:01:53.242 # Server initialized
[9636] 03 Apr 13:01:53.286 * DB loaded from disk: 0.039 seconds
[9636] 03 Apr 13:01:53.288 * Ready to accept connections
# Slave1 服务连接到 Master
[9636] 03 Apr 13:01:59.621 * Replica 127.0.0.1:6378 asks for synchronization
[9636] 03 Apr 13:01:59.622 * Partial resynchronization not accepted: Replication ID mismatch (Replica asked for '79f4f005072ad284bcbb016803009ac3651a9695', my replication IDs are '4644b3e486ba2de4f17119ff02d3d6ca18175256' and '0000000000000000000000000000000000000000')
[9636] 03 Apr 13:01:59.622 * Starting BGSAVE for SYNC with target: disk
[9636] 03 Apr 13:01:59.686 * Background saving started by pid 6708
[9636] 03 Apr 13:02:00.055 # fork operation complete
[9636] 03 Apr 13:02:00.071 * Background saving terminated with success
[9636] 03 Apr 13:02:00.128 * Synchronization with replica 127.0.0.1:6378 succeeded
# Slave2 服务连接到 Master
[9636] 03 Apr 13:02:05.907 * Replica 127.0.0.1:6377 asks for synchronization
[9636] 03 Apr 13:02:05.907 * Partial resynchronization not accepted: Replication ID mismatch (Replica asked for '79f4f005072ad284bcbb016803009ac3651a9695', my replication IDs are '70698914343964c3f04b9d117f95efdc2f8a9e89' and '0000000000000000000000000000000000000000')
[9636] 03 Apr 13:02:05.908 * Starting BGSAVE for SYNC with target: disk
[9636] 03 Apr 13:02:05.953 * Background saving started by pid 28896
[9636] 03 Apr 13:02:06.341 # fork operation complete
[9636] 03 Apr 13:02:06.354 * Background saving terminated with success
[9636] 03 Apr 13:02:06.362 * Synchronization with replica 127.0.0.1:6377 succeeded

启动 Slave1 服务

使用 redis-server.exe redis.windows.conf 命令启动 Redis 服务,启动日志如下:

[38284] 03 Apr 13:01:58.528 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
[38284] 03 Apr 13:01:58.529 # Redis version=5.0.14.1, bits=64, commit=ec77f72d, modified=0, pid=38284, just started
[38284] 03 Apr 13:01:58.529 # Configuration loaded
               _._
          _.-``__ ''-._
     _.-``    `.  `_.  ''-._           Redis 5.0.14.1 (ec77f72d/0) 64 bit
 .-`` .-```.  ```\/    _.,_ ''-._
(    '      ,       .-`  | `,    )     Running in standalone mode
|`-._`-...-` __...-.``-._|'` _.-'|     Port: 6378
|    `-._   `._    /     _.-'    |     PID: 38284
 `-._    `-._  `-./  _.-'    _.-'
|`-._`-._    `-.__.-'    _.-'_.-'|
|    `-._`-._        _.-'_.-'    |           http://redis.io
 `-._    `-._`-.__.-'_.-'    _.-'
|`-._`-._    `-.__.-'    _.-'_.-'|
|    `-._`-._        _.-'_.-'    |
 `-._    `-._`-.__.-'_.-'    _.-'
     `-._    `-.__.-'    _.-'
         `-._        _.-'
             `-.__.-'

[38284] 03 Apr 13:01:58.534 # Server initialized
[38284] 03 Apr 13:01:58.547 * DB loaded from disk: 0.012 seconds
[38284] 03 Apr 13:01:58.547 * Before turning into a replica, using my master parameters to synthesize a cached master: I may be able to synchronize with the new master with just a partial transfer.
[38284] 03 Apr 13:01:58.547 * Ready to accept connections
# 开始和 Master 进行数据同步
[38284] 03 Apr 13:01:58.547 * Connecting to MASTER 127.0.0.1:6379
[38284] 03 Apr 13:01:59.617 * MASTER <-> REPLICA sync started
[38284] 03 Apr 13:01:59.617 * Non blocking connect for SYNC fired the event.
[38284] 03 Apr 13:01:59.618 * Master replied to PING, replication can continue...
[38284] 03 Apr 13:01:59.620 * Trying a partial resynchronization (request 79f4f005072ad284bcbb016803009ac3651a9695:1).
[38284] 03 Apr 13:01:59.687 * Full resync from master: 70698914343964c3f04b9d117f95efdc2f8a9e89:0
[38284] 03 Apr 13:01:59.689 * Discarding previously cached master state.
[38284] 03 Apr 13:02:00.116 * MASTER <-> REPLICA sync: receiving 569074 bytes from master
[38284] 03 Apr 13:02:00.134 * MASTER <-> REPLICA sync: Flushing old data
[38284] 03 Apr 13:02:00.148 * MASTER <-> REPLICA sync: Loading DB in memory
[38284] 03 Apr 13:02:00.162 * MASTER <-> REPLICA sync: Finished with success

启动 Slave2 服务

使用 redis-server.exe redis.windows.conf 命令启动 Redis 服务,启动日志如下:

[23216] 03 Apr 13:02:04.904 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
[23216] 03 Apr 13:02:04.906 # Redis version=5.0.14.1, bits=64, commit=ec77f72d, modified=0, pid=23216, just started
[23216] 03 Apr 13:02:04.907 # Configuration loaded
               _._
          _.-``__ ''-._
     _.-``    `.  `_.  ''-._           Redis 5.0.14.1 (ec77f72d/0) 64 bit
 .-`` .-```.  ```\/    _.,_ ''-._
(    '      ,       .-`  | `,    )     Running in standalone mode
|`-._`-...-` __...-.``-._|'` _.-'|     Port: 6377
|    `-._   `._    /     _.-'    |     PID: 23216
 `-._    `-._  `-./  _.-'    _.-'
|`-._`-._    `-.__.-'    _.-'_.-'|
|    `-._`-._        _.-'_.-'    |           http://redis.io
 `-._    `-._`-.__.-'_.-'    _.-'
|`-._`-._    `-.__.-'    _.-'_.-'|
|    `-._`-._        _.-'_.-'    |
 `-._    `-._`-.__.-'_.-'    _.-'
     `-._    `-.__.-'    _.-'
         `-._        _.-'
             `-.__.-'

[23216] 03 Apr 13:02:04.922 # Server initialized
[23216] 03 Apr 13:02:04.939 * DB loaded from disk: 0.016 seconds
[23216] 03 Apr 13:02:04.940 * Before turning into a replica, using my master parameters to synthesize a cached master: I may be able to synchronize with the new master with just a partial transfer.
[23216] 03 Apr 13:02:04.942 * Ready to accept connections
# 开始和 Master 进行数据同步
[23216] 03 Apr 13:02:04.944 * Connecting to MASTER 127.0.0.1:6379
[23216] 03 Apr 13:02:05.905 * MASTER <-> REPLICA sync started
[23216] 03 Apr 13:02:05.905 * Non blocking connect for SYNC fired the event.
[23216] 03 Apr 13:02:05.906 * Master replied to PING, replication can continue...
[23216] 03 Apr 13:02:05.906 * Trying a partial resynchronization (request 79f4f005072ad284bcbb016803009ac3651a9695:15).
[23216] 03 Apr 13:02:05.954 * Full resync from master: 70698914343964c3f04b9d117f95efdc2f8a9e89:14
[23216] 03 Apr 13:02:05.956 * Discarding previously cached master state.
[23216] 03 Apr 13:02:06.357 * MASTER <-> REPLICA sync: receiving 569074 bytes from master
[23216] 03 Apr 13:02:06.363 * MASTER <-> REPLICA sync: Flushing old data
[23216] 03 Apr 13:02:06.367 * MASTER <-> REPLICA sync: Loading DB in memory
[23216] 03 Apr 13:02:06.379 * MASTER <-> REPLICA sync: Finished with success

主从复制验证

使用 redis-cli 客户端工具连接到 Master 服务,查看主从复制信息,如下:

C:\Users\Administrator>redis-cli
127.0.0.1:6379> auth aaaaaa
OK
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
# 下面时两个 slave 服务的信息
slave0:ip=127.0.0.1,port=6378,state=online,offset=98,lag=1
slave1:ip=127.0.0.1,port=6377,state=online,offset=98,lag=0
# 主服务信息
master_replid:70698914343964c3f04b9d117f95efdc2f8a9e89
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:98
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:98

在 Master 服务上面创建一个 master 字符串键,命令如下:

# 在 Master 服务上写入一个 master 键
C:\Users\Administrator> redis-cli
127.0.0.1:6379> set master "hello world"
OK
127.0.0.1:6379>

# 从 Slave1 中获取 master 键的值
C:\Users\Administrator> redis-cli -p 6378
127.0.0.1:6378> get master
"hello world"
127.0.0.1:6378>

# 从 Slave2 中获取 master 键的值
C:\Users\Administrator> redis-cli -p 6377
127.0.0.1:6377> get master
"hello world"
127.0.0.1:6377>

到这里,Redis 主从复制就介绍完了,如果有问题请留言指正。

说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号