Redis安装之集群-主从复制(replica)模式
官网说明:https://redis.io/docs/management/replication/
一. 背景
单机部署存在单点故障及数据丢失问题,为了实现
- 读写分离
- 容灾恢复
- 数据备份
- 水平扩容支撑高并发
等功能,Redis可基于 主从复制 的特性搭建集群。
二. 方案原理
2.1. 读写分离
- Master主机负责 写操作,Slave从机负责 读操作。
- 当Master数据变化时,程序将采用异步的方式将数据同步给其他 Slave。
2.2. 主从同步
- slave 启动后,向 master 发起加入请求;
- 成功加入 master 后,向 master 发送 sync 命令;
- master 收到 sync 命令后,另起线程执行 bgsave 命令后台保存快照(即RDB持久化,主从复制时会触发RDB),同时缓存所有更新数据库的命令;
- master 执行 RDB 后,一次性将 RDB 和 所有缓存的命令发送到所有 slave,完成一次完全同步;
- slave 接收到 master 同步的数据后,将其存盘并加载到内存,完成复制初始化。 slave 自身拥有数据将会覆盖清除;
- master 为在 backlog 中为每个 slave 维护了一份同步数据偏移量(offset),后续将通过偏移量与每个 slave 实现增量同步。
Tips:
- redis 2.8 以前不支持部分同步。
当主从服务器断接重连后,会再次进行全量数据同步。 - redis 2.8 之后支持部分同步。
原理:
- master 内存中为每个 slave 维护了一份同步日志和同步标识。
- 每个 slave 在同步时会携带 同步标识 和 上次同步的最后位置。
- 当主从断连后,slave 间隔时间内(默认1s)主动尝试和 master 连接。
若 slave 携带的偏移量标识在 master 的同步日志中,则 slave 发送的偏移量开始继续上次的同步操作;
若 slave 发送的偏移量不在 master 的同步日志中,则进行一次全量更新。 - 增量同步时,master 会根据 backlog 中记录的每个 slave 的 offset 将该 slave 未同步的数据增量同步。
可参考:
https://www.cnblogs.com/sparkss/p/14707718.html#_lab20_3
https://developer.aliyun.com/article/1335735
https://developer.aliyun.com/article/1335736
2.3. 相关配置
################################# REPLICATION(主从复制) #################################
# 复制选项,slave复制对应的master。
# replicaof <masterip> <masterport>
#如果master设置了requirepass,那么slave要连上master,需要有master的密码才行。masterauth就是用来
#配置master的密码,这样可以在连上master后进行认证。
# masterauth <master-password>
#当slave同master失去连接 或者 复制正在进行,slave有两种运行方式:
#1) 如果slave-serve-stale-data设置为yes(默认设置),slave会继续响应客户端的请求。
#2) 如果slave-serve-stale-data设置为no,除INFO,replicaOF, AUTH, PING, SHUTDOWN, REPLCONF, ROLE, CONFIG,SUBSCRIBE, UNSUBSCRIBE,
#PSUBSCRIBE, PUNSUBSCRIBE, PUBLISH, PUBSUB,COMMAND, POST, HOST: and LATENCY命令之外的任何请求都会返回一个错误”SYNC with master in progress”。
replica-serve-stale-data yes
#作为从服务器,默认情况下是只读的(yes),可以修改成NO,用于写(不建议)
replica-read-only yes
# 是否使用无磁盘复制(即使用socket方式复制数据),默认是使用disk方式复制数据
repl-diskless-sync no
#diskless复制的延迟时间,防止设置为0。一旦复制开始,节点不会再接收新slave的复制请求直到下一个rdb传输。所以最好等待一段时间,等更多的slave连上来
repl-diskless-sync-delay 5
#slave根据指定的时间间隔向master发送ping请求。时间间隔可以通过 repl_ping_slave_period 来设置,默认10秒。
# repl-ping-replica-period 10
# 复制连接超时时间。master和slave都有超时时间的设置。master检测到slave上次发送的时间超过repl-timeout,即认为slave离线,清除该slave信息。
#slave检测到上次和master交互的时间超过repl-timeout,则认为master离线。需要注意的是repl-timeout需要设置一个比repl-ping-slave-period更大的值,不然会经常检测到超时
# repl-timeout 60
#是否禁止 主从复制tcp连接的 tcp nodelay参数(结尾有解释)。默认是no,即使用tcp nodelay。
#如果master设置了yes来禁止tcp nodelay设置,在把数据复制给slave的时候,会减少包的数量并且更小的网络带宽。
#但是这也可能带来数据的延迟。默认我们推荐更小的延迟,但是在数据量传输很大的场景下,建议选择yes
repl-disable-tcp-nodelay no
#复制缓冲区大小,这是一个环形复制缓冲区,用来保存最新写命令。这样在slave离线的时候,不需要完
#全复制master的数据,如果可以执行部分同步,只需要把缓冲区的部分数据复制给slave,就能恢复正常复制状
#态。缓冲区的大小越大,slave离线的时间可以更长,复制缓冲区只有在有slave连接的时候才分配内存。没有
#slave的一段时间,内存会被释放出来,默认1m
# repl-backlog-size 1mb
# master没有slave一段时间会释放复制缓冲区的内存,repl-backlog-ttl用来设置该时间长度。单位为秒。
# repl-backlog-ttl 3600
# 当master不可用,Sentinel会根据slave的优先级选举一个master。最低的优先级的slave,当选master。而配置成0,永远不会被选举
replica-priority 100
#redis提供了可以让master停止写入的方式,如果配置了min-replicas-to-write,健康的slave的个数小于N,
#mater就禁止写入。master最少得有多少个健康的slave存活才能执行写命令。这个配置虽然不能保证N个slave都一
#定能接收到master的写操作,但是能避免没有足够健康的slave的时候,master不能写入来避免数据丢失。设置为0是关闭该功能
# min-replicas-to-write 3
# 延迟小于min-replicas-max-lag秒的slave才认为是健康的slave
# min-replicas-max-lag 10
三. 集群部署
3.1. 部署实现方案
- 一主二从(配置版)
- 一主二从(命令版)
- 薪火相传
3.2. 环境准备
- 172.19.223.161(主)
- 172.19.223.162(从1)
- 172.19.223.163(从2)
为方便区分,将从机端口分别置为:6380、6381。具体如下:
- 172.19.223.161:6379
- 172.19.223.162:6380
- 172.19.223.163:6381
3.3. 一主二从(配置版)
此处仅redis主要安装步骤,无服务器环境检查及安装步骤。
具体可参照:https://www.cnblogs.com/DeepInThought/p/18059602
架构图:
3.3.1. 安装Redis
执行如下步骤,分别为172.19.223.161、172.19.223.162、172.19.223.163安装Redis。
## 下载
mkdir -p /opt/package
wget https://github.com/redis/redis/archive/7.2.4.tar.gz
## 解压
tar -zxvf 7.2.4.tar.gz -C ../
cd /opt/redis-7.2.4
## 编译
make && make install
cp /opt/redis-7.2.4/redis.conf /opt/redis-7.2.4/redis.conf.bak
3.3.2. 配置主机
配置主机: 172.19.223.161。
配置要点:配从(库)不配(主)库。
vi /opt/redis-7.2.4/redis.conf
## 找到如下配置项,将其参数值修改为如下
daemonize yes
## bind 127.0.0.1
protected-mode no
port 6379
dir /opt/redis-7.2.4/data
pidfile /var/run/redis_6379.pid
logfile /opt/redis-7.2.4/log/redis_6379.log
requirepass 219527
dbfilename dump_6379.rdb
appenddirname "appenddir"
appendfilename "appendonly_6379.aof"
## 退出保存
:wq
3.3.3. 配置从机
配置从机<1>: 172.19.223.162。
vi /opt/redis-7.2.4/redis.conf
## 找到如下配置项,将其参数值修改为如下
daemonize yes
## bind 127.0.0.1
protected-mode no
port 6380
dir /opt/redis-7.2.4/data
pidfile /var/run/redis_6380.pid
logfile /opt/redis-7.2.4/log/redis_6380.log
requirepass 219527
dbfilename dump_6379.rdb
appenddirname "appenddir"
appendfilename "appendonly_6380.aof"
## 从机新增配置
replicaof 172.19.223.160 6379
masteraurh "219527"
## 退出保存
:wq
配置从机<2>: 172.19.223.163。
vi /opt/redis-7.2.4/redis.conf
## 找到如下配置项,将其参数值修改为如下
daemonize yes
## bind 127.0.0.1
protected-mode no
port 6381
dir /opt/redis-7.2.4/data
pidfile /var/run/redis_6381.pid
logfile /opt/redis-7.2.4/log/redis_6381.log
requirepass 219527
dbfilename dump_6379.rdb
appenddirname "appenddir"
appendfilename "appendonly_6381.aof"
## 从机新增配置
replicaof 172.19.223.160 6379
masteraurh "219527"
## 退出保存
:wq
3.3.4 服务启动
## 先启动主机:172.19.223.161
redis-serve /opt/redis-7.2.4/redis.conf
## 再启动备机<1>:172.19.223.162
## 备机日志中出现 Connection to MASTER 172.19.223.161:6379 即OK。
redis-serve /opt/redis-7.2.4/redis.conf
## 再启动备机<2>:172.19.223.163
## 备机日志中出现 Connection to MASTER 172.19.223.161:6379 即OK。
redis-serve /opt/redis-7.2.4/redis.conf
## 待集群同步启动后,连接任意redis实例查看集群状态。
## 主机日主出现 Streamed RDB transfer with replica xxxx:xx succeeded 即连接从机成功。
## 主机日志出现 Synchronization with replica xxxx:xx succeeded 即同步数据至从机成功。
## 此处登录主机:
redis-cli -a 219527 -p 6379
> info replication
3.4. 一主二从(命令版)
此处仅redis主要安装步骤,无服务器环境检查及安装步骤。
具体可参照:https://www.cnblogs.com/DeepInThought/p/18059602
3.4.1. 安装Redis
执行如下步骤,分别为172.19.223.161、172.19.223.162、172.19.223.163安装Redis。
## 下载
mkdir -p /opt/package
wget https://github.com/redis/redis/archive/7.2.4.tar.gz
## 解压
tar -zxvf 7.2.4.tar.gz -C ../
cd /opt/redis-7.2.4
## 编译
make && make install
cp /opt/redis-7.2.4/redis.conf /opt/redis-7.2.4/redis.conf.bak
3.4.2. 配置Redis
- 配置 172.19.223.161 Redis:
vi /opt/redis-7.2.4/redis.conf
## 找到如下配置项,将其参数值修改为如下
daemonize yes
## bind 127.0.0.1
protected-mode no
## 其他两台应用分别为 6380、6381
port 6379
dir /opt/redis-7.2.4/data
pidfile /var/run/redis_6379.pid
logfile /opt/redis-7.2.4/log/redis_6379.log
requirepass 219527
dbfilename dump_6379.rdb
appenddirname "appenddir"
appendfilename "appendonly_6379.aof"
## 退出保存
:wq
- 配置 172.19.223.162 Redis:
vi /opt/redis-7.2.4/redis.conf
## 找到如下配置项,将其参数值修改为如下
daemonize yes
## bind 127.0.0.1
protected-mode no
port 6380
dir /opt/redis-7.2.4/data
pidfile /var/run/redis_6380.pid
logfile /opt/redis-7.2.4/log/redis_6380.log
requirepass 219527
dbfilename dump_6380.rdb
appenddirname "appenddir"
appendfilename "appendonly_6380.aof"
## 从机需要配置主机密码
masteraurh "219527"
## 退出保存
:wq
- 配置 172.19.223.163 Redis:
vi /opt/redis-7.2.4/redis.conf
## 找到如下配置项,将其参数值修改为如下
daemonize yes
## bind 127.0.0.1
protected-mode no
port 6381
dir /opt/redis-7.2.4/data
pidfile /var/run/redis_6381.pid
logfile /opt/redis-7.2.4/log/redis_6381.log
requirepass 219527
dbfilename dump_6381.rdb
appenddirname "appenddir"
appendfilename "appendonly_6381.aof"
## 从机需要配置主机密码
masteraurh "219527"
## 退出保存
:wq
3.4.3 服务启动
## 先启动主机:172.19.223.160
redis-serve /opt/redis-7.2.4/redis.conf
## 再启动备机<1>:172.19.223.161
redis-serve /opt/redis-7.2.4/redis.conf
## 再启动备机<2>:172.19.223.162
redis-serve /opt/redis-7.2.4/redis.conf
## 此时使用 redis-cli 分别登录三个实例执行 info replication 会发现三个实例均为 Master。
## 在备机<1>:172.19.223.161上执行
redis-cli -a 219527 -p 6380
> SLAVEOF 172.19.223.160 6379
## 在备机<2>:172.19.223.162上执行
redis-cli -a 219527 -p 6381
> SLAVEOF 172.19.223.160 6379
## 两台备机Redis启动一段时间后,将会称为 Master 的 Slaver。
## 可使用如下命令使当前实例停止与其他数据库的同步关系,成为 Master:
slaveof no one
Tips:
- 一主二从(配置版)持久稳定,永久生效。
- 一主二从(命令版)当次生效,重启失效。备机 SHUTDOWN 后,再启动后将不会再次成为 Master 的 Slaver。
3.5. 薪火相传
架构图:
## 在 《## 3.3. 一主二从(配置版)》的配置基础上,仅需修改从机 172.19.223.162 的配置项 replicaof 为:
replicaof 172.19.223.161 6380
四. Tips Mark
- Slaver 只能读,不能写。
- Slaver 连接 Master 后,Master 一次性将所有数据同步给 Slaver,后续 Master 会将收到的写操作也一一同步给 Slaver。
- Master 停止服务后,Slaver 依然可以提供读操作,但不会上位接替 Master 的工作,即仍不可写。
- Master 停止服务后,再重启,主从关系依然存在,集群如初运转。
- Slaver 停止服务后,再重启,将于 Master 再次数据同步后,正常提供服务。