DBA Redis 主从复制

功能概述

​ Redis的主从复制与MySQL相同,本身并不提供任何高可用方面的功能,需要借助其他技术进行实现,但却是高可用架构的基础前提。

​ 相较于MySQL来说,Redis的主从复制搭建比较简单,关注的点也比较少,且因内部原因数据同步速率影响较小(如果网速慢另当别论)。

​ 下面我准备使用3台服务器来搭建Redis主从复制,一方面也为后面的高可用架构做基础铺垫。

image-20210331174003518

地址规划

​ 以下是地址规划:

作用 IP地址 服务端口 操作系统 配置
Master 192.168.0.120 6379 Centos7.3 基础设施服务器 2颗CPU 2G内存 20G硬盘
SLAVE1 192.168.0.130 6379 Centos7.3 基础设施服务器 2颗CPU 2G内存 20G硬盘
SLAVE2 192.168.0.140 6379 Centos7.3 基础设施服务器 2颗CPU 2G内存 20G硬盘

​ 所有节点选用Redis版本为6.2.1,也是目前最新版。

安装Redis

​ 为所有服务器安装Redis:

$ cd ~
$ wget https://download.redis.io/releases/redis-6.2.1.tar.gz

​ 配置目录,所有节点都执行:

$ mkdir -p /usr/local/redis_cluster/redis_6379/{conf,pid,logs}

# 目录说明:
/usr/local/redis_cluster/ # redis服务相关文件目录
└── redis_6379            # 6379端口数据文件相关目录
    ├── conf              # 6379端口配置文件存放目录
    ├── logs              # 6379端口日志文件存放目录
    └── pid               # 6379端口pid文件存放目录

​ 进行解压:

$ tar -zxvf redis-6.2.1.tar.gz -C /usr/local/redis_cluster/

​ 编译安装:

$ cd /usr/local/redis_cluster/redis-6.2.1/
$ make            # 在src目录下生成各种服务命令
$ make install  # 添加服务命令软链接至环境变量

​ 书写配置文件:

$ vim /usr/local/redis_cluster/redis_6379/conf/redis.cnf

# 以守护进程模式启动
daemonize yes

# 注意修改不同的地址
# 绑定的主机地址,一般设为本地即可,如设置为0.0.0.0则允许所有地址登录
bind 192.168.0.120   

# 监听端口
port 6379

# pid文件和log文件的保存地址
pidfile /usr/local/redis_cluster/redis_6379/pid/redis_6379.pid
logfile /usr/local/redis_cluster/redis_6379/logs/redis_6379.log

# 设置数据库的数量,默认数据库为0
databases 16

# 指定本地持久化文件的文件名,默认是dump.rdb 
dbfilename redis_6379.rdb

# 本地数据库的目录
dir /usr/local/redis_cluster/redis_6379

​ 配置HOSTS文件:

192.168.0.120 master
192.168.0.130 node1
192.168.0.140 node2

搭建主从

​ 1)启动Master:

$ redis-server /usr/local/redis_cluster/redis_6379/conf/redis.cnf

​ 2)选择链接方式,从库链接主库的方式有3种,选择任意一种:

  • 配置文件中加入 slaveof 主库HOST 主库PORT,Redis服务启动生效
  • 在redis-server启动命令后加入 --slaveof 主库HOST 主库PORT,单次启动生效,重启失效
  • 在redis-shell中使用命令 slaveof 主库HOST 主库PORT 立即生效,重启失效

​ 3)这里我选择第2种,2个从库进行启动即可:

$ redis-server /usr/local/redis_cluster/redis_6379/conf/redis.cnf --slaveof 192.168.0.120 6379

$ ps -ef | grep redis

​ 4)登录主库,查看链接情况:

$ redis-cli -h master -p 6379

master:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.0.130,port=6379,state=online,offset=196,lag=0
slave1:ip=192.168.0.140,port=6379,state=online,offset=196,lag=1
master_failover_state:no-failover
master_replid:aea7f187e94343b82b229d8a5a3c5e407aedc0f2
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:196
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:196

​ 5)主库尝试写入数据:

master:6379> set k1 "v1"
OK

​ 6)从库进行查看:

$ redis-cli -h node1 -p 6379
node1:6379> keys *
1) "k1"
node1:6379>

$ redis-cli -h node2 -p 6379
node2:6379> keys *
1) "k1"
node2:6379>

​ 7)尝试从库写入数据,会发生异常提示,仅允许主库写入:

node2:6379> set k2 "v2"
(error) READONLY You can't write against a read only replica.

关系解除

​ 如果要解除从库与主库的关系,可在从库的redis-shell中使用以下命令:

slaveof no one

复制过程

​ 如图所示:

image-20210331185828502

​ 查看主从节点的日志,为了照顾英文不好的读者,这里使用译文:

$ tail -f /usr/local/redis_cluster/redis_6379/logs/redis_6379.log

28788:M 2021年3月31日06:26:15.229 *副本192.168.0.130:6379要求同步
28788:M 2021年3月31日06:26:15.229 *接受了来自192.168.0.130:6379的部分重新同步请求。从偏移量15开始发送0字节的积压。  # 这里是因为主库本身没有任何数据而做的主从关系
28788:M 2021年3月31日06:26:16.607 *副本192.168.0.140:6379要求同步
28788:M 2021年3月31日06:26:16.607 *副本192.168.0.140:6379请求完全重新同步
28788:M 2021年3月31日06:26:16.607 *使用目标:磁盘启动BGSAVE for SYNC
28788:M 2021年3月31日06:26:16.608 *通过pid 33284开始后台保存
33284:C 2021年3月31日06:26:16.610 * DB保存在磁盘上
33284:C 2021年3月31日06:26:16.611 * RDB:0写入时复制使用的内存
28788:M 2021年3月31日06:26:16.687 *背景保存成功终止
28788:M 2021年3月31日06:26:16.688 *与副本192.168.0.140:6379的同步成功
28788:M 2021年3月31日06:26:15.229 *副本192.168.0.130:6379要求同步
28788:M 2021年3月31日06:26:15.229 *接受了来自192.168.0.130:6379的部分重新同步请求。从偏移量15开始发送0字节的积压。
28788:M 2021年3月31日06:26:16.607 *副本192.168.0.140:6379要求同步
28788:M 2021年3月31日06:26:16.607 *副本192.168.0.140:6379请求完全重新同步
28788:M 2021年3月31日06:26:16.607 *使用目标:磁盘启动BGSAVE for SYNC
28788:M 2021年3月31日06:26:16.608 *通过pid 33284开始后台保存
33284:C 2021年3月31日06:26:16.610 * DB保存在磁盘上
33284:C 2021年3月31日06:26:16.611 * RDB:0写入时复制使用的内存
28788:M 2021年3月31日06:26:16.687 *背景保存成功终止
28788:M 2021年3月31日06:26:16.688 *与副本192.168.0.140:6379的同步成功

​ 查看从节点的日志,为了照顾英文不好的读者,这里使用译文:

$ tail -f /usr/local/redis_cluster/redis_6379/logs/redis_6379.log

28108:S 2021年3月31日06:26:15.225 * DB从磁盘加载:0.000秒
28108:S 2021年3月31日06:26:15.225 *在变成副本之前,使用我自己的master参数合成一个缓存的master:通过部分传输,我也许可以与新master同步。
28108:S 2021年3月31日06:26:15.225 *准备接受连接
28108:S 2021年3月31日06:26:15.225 *连接至主192.168.0.120:6379
28108:S 2021年3月31日06:26:15.225 * MASTER <-> REPLICA同步开始
28108:S 2021年3月31日06:26:15.226 * SYNC的非阻塞连接触发了该事件。
28108:S 2021年3月31日06:26:15.226 *主服务器回复为PING,复制可以继续...
28108:S 2021年3月31日06:26:15.227 *尝试进行部分重新同步(请求aea7f187e94343b82b229d8a5a3c5e407aedc0f2:15)。
28108:S 2021年3月31日06:26:15.228 *与主机成功完成部分重新同步。
28108:S 2021年3月31日06:26:15.228 * MASTER <-> REPLICA sync:Master接受了部分重新同步。

主库宕机

​ 如果主库宕机后会发生什么?进行操作:

$ redis-cli -h master -p 6379 shutdown

​ 查看从库日志:

$ tail -f /usr/local/redis_cluster/redis_6379/logs/redis_6379.log

28108:S 2021年3月31日06:40:55.037#SYNC套接字上的错误情况:连接被拒绝
28108:S 2021年3月31日06:40:56.043 *连接至主192.168.0.120:6379
28108:S 2021年3月31日06:40:56.043 * MASTER <-> REPLICA同步开始
28108:S 2021年3月31日06:40:56.044#SYNC套接字上的错误情况:连接被拒绝
28108:S 2021年3月31日06:40:57.052 *连接至主192.168.0.120:6379
28108:S 2021年3月31日06:40:57.052 * MASTER <-> REPLICA同步开始
28108:S 2021年3月31日06:40:57.053#SYNC套接字上的错误情况:连接被拒绝
28108:S 2021年3月31日06:40:58.058 *连接至主192.168.0.120:6379
28108:S 2021年3月31日06:40:58.059 * MASTER <-> REPLICA同步开始
28108:S 2021年3月31日06:40:58.059#SYNC套接字上的错误情况:连接被拒绝
28108:S 2021年3月31日06:40:59.065 *连接至主192.168.0.120:6379
28108:S 2021年3月31日06:40:59.066 * MASTER <-> REPLICA同步开始
28108:S 2021年3月31日06:40:59.067#SYNC套接字上的错误情况:连接被拒绝
28108:S 2021年3月31日06:41:00.070 *连接至主192.168.0.120:6379
28108:S 2021年3月31日06:41:00.072 * MASTER <-> REPLICA同步开始
28108:S 2021年3月31日06:41:00.072#SYNC套接字上的错误情况:连接被拒绝
28108:S 2021年3月31日06:41:01.080 *连接至主192.168.0.120:6379

​ 它会不断的请求主库,永不间断。

故障恢复

​ 主库发生故障后,应当将其中一个从库立马转换为主库身份。

​ 如下,将node1转换为主库身份,首先,node1的slaveof要设置为空:

$ redis-cli -h node1 -p 6379
node1:6379> slaveof no one
OK
node1:6379>

其次,你应该登录node2,然后进行设置node1为新主库:

$ redis-cli -h node2 -p 6379
node2:6379> slaveof 192.168.1.130 6379
OK
node2:6379>

查看复制信息:

node2:6379> info replication
# Replication
role:slave
master_host:192.168.1.130
master_port:6379
master_link_status:down
master_last_io_seconds_ago:-1
master_sync_in_progress:0
slave_repl_offset:1270
master_link_down_since_seconds:348
slave_priority:100
slave_read_only:1
connected_slaves:0
master_failover_state:no-failover
master_replid:aea7f187e94343b82b229d8a5a3c5e407aedc0f2
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:1270
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:15
repl_backlog_histlen:1256

然后将原主库master进行修复后作为从库链接至node1,这里我不再进行演示了。

另外,如果application原本接入的是已宕机主库master,你还需要通知开发人员进行手动切换。

为了后续章节,我这里再将master上线并设置为主库。

posted @ 2021-03-31 18:59  云崖君  阅读(87)  评论(0编辑  收藏  举报