Redis单机主从复制+多机主从复制的实现(一主两从)
Redis有两种不同的持久化方式,Redis服务器通过持久化,把Redis内存中持久化到硬盘当中,当Redis宕机时,我们重启Redis服务器时,可以由RDB文件或AOF文件恢复内存中的数据。
不过持久化后的数据仍然只在一台机器上,因此当硬件发生故障时,比如主板或CPU坏了,这时候无法重启服务器,有什么办法可以保证服务器发生故障时数据的安全性?或者可以快速恢复数据呢?想做到这一点,我们需要再了解Redis另外一种机制:主从复制。
## 一、主从复制概述
### 1.1 单机问题
#### 1.1.1 机器宕机
如果发生机器宕机(主板烧坏、硬盘损坏、内存损坏等),短时间内我们也无法修复,我们就会考虑将redis迁移到另外一台机器上,并且还要考虑数据同步问题。
#### 1.1.2 容器瓶颈
一台机器内存是16G,redis使用12个G内存,除了redis还要使用其他的应用,这个时候,我们可能需要32个G内存才能使用,但是redis的应用对内存的增加也会提交,我们不能一直去提高单机的内存?
#### 1.1.3 QPS瓶颈
redis官方数据显示redis可以处理达到10w的QPS,如果业务需要50w、100w的QPS时我们怎么办?
关于容量瓶颈、QPS瓶颈和机器宕机,这就是redis分布式和高可用需要解决的问题。
### 1.2 什么是主从复制
Master可以拥有多个slave;多个slave可以连接同一个Master外,还可以连接到其他的slave;主从复制不会阻塞Master,在主从复制时,Master可以处理client请求。
### 1.3 主从复制形式
#### 1.3.1 一主一从
一个是Master节点,一个是slave节点,即主节点和从节点。主节点是数据写入,从节点可以通过复制操作将主节点的数据同步过来,并且随着主节点数据不断写入,从节点数据也会做同步的更新。
#### 1.3.2 一主多从
一个master可以有多个slave,也就相当于有了多份的数据副本。这样可以做一个更加高可用的选择,例如一个master和一个slave挂掉了,还能有其他的slave数据备份。
### 1.4 主从复制作用
**数据备份**
将master的数据,备份到slave
**读写分离**
用master来写入数据,用slave完成备份后,来完成只读的功能。
**注意:**
当master宕机后,不会去选择slave作为master。需要手动将一台slave使用slaveof on one提升为master,要想自动实现提升,我们就需要使用哨兵。
## 二、单机主从(配置一主二从)
### 2.1 复制redis.conf
我的redis放在/opt/module/redis6
在自己redis存放的目录下,将redis.conf复制成三份分别取名为:redis-8000.conf、redis-8001.conf、redis-8002.conf三个配置文件
cp redis.conf redis-8000.conf
cp redis.conf redis-8001.conf
cp redis.conf redis-8002.conf
### 2.2 创建.conf配置文件所需目录/文件
(1)创建log日志路径目录
mkdir -p /opt/module/redis6/logs/
(2)创建不同的pid文件
touch /opt/module/redis6/redis_8000.pid
touch /opt/module/redis6/redis_8001.pid
touch /opt/module/redis6/redis_8002.pid
(3)创建rdb文件和aof文件的路径目录
mkdir -p /opt/module/redis6/data/redis_8000
mkdir -p /opt/module/redis6/data/redis_8001
mkdir -p /opt/module/redis6/data/redis_8002
### 2.3 配置主机
以redis-8000为主机
```
protected-mode no #关掉保护模式
#bind 127.0.0.1 #将bind注释掉 或 bind 0.0.0.0
port 8000 #改变其服务端口
daemonize yes #修改服务为后台运行
注意下面的三个路径都建议写绝对路径,不要写相对路径
pidfile "/opt/module/redis6/redis_8000.pid" #指定不同的pid文件,注意三份配置文件不同。
logfile "/opt/module/redis6/logs/redis_8000.log" #指定log日志绝对路径,自己配,要求不同。
dir "/opt/module/redis6/data/redis_8000" #这个指定rdb文件和aof文件的路径配置,要求改成不同。
masterauth ibethfy #取消注释,并配上从服务到主服务的认证密码(建议用""框上)。
例如:masterauth "abc123"
requirepass ibethfy #三份文件都配置,客户端访问需要密码验证。
例如:requirepass "abc123"
```
### 2.4 配置从机
以redis-8001,redis-8002为从机
```
8001:
protected-mode no #关掉保护模式
#bind 127.0.0.1 #将bind注释掉 或 bind 0.0.0.0
port 8001 #改变其服务端口
daemonize yes #修改服务为后台运行
pidfile "/opt/module/redis6/redis_8001.pid" #指定不同的pid文件,注意三份配置文件不同。
logfile "/opt/module/redis6/logs/redis_8001.log" #指定log日志绝对路径,自己配,要求不同。
dir "/opt/module/redis6/data/redis_8001" #这个指定rdb文件和aof文件的路径配置,要求改成不同。
replicaof 10.1.1.160 8000 #主服务这句话注释,从服务配置的两台需要开启。配置主服务的ip的port。
masterauth ibethfy #取消注释,并配上从服务到主服务的认证密码(建议用""框上)。
例如:masterauth "abc123"
requirepass ibethfy #三份文件都配置,客户端访问需要密码验证。
例如:requirepass "abc123"
8002:
protected-mode no #关掉保护模式
#bind 127.0.0.1 #将bind注释掉 或 bind 0.0.0.0
port 8002 #改变其服务端口
daemonize yes #修改服务为后台运行
pidfile "/opt/module/redis6/redis_8002.pid" #指定不同的pid文件,注意三份配置文件不同。
logfile "/opt/module/redis6/logs/redis_8002.log" #指定log日志绝对路径,自己配,要求不同。
dir "/opt/module/redis6/data/redis_8002" #这个指定rdb文件和aof文件的路径配置,要求改成不同。
replicaof 10.1.1.160 8000 #主服务这句话注释,从服务配置的两台需要开启。配置主服务的ip的port。
masterauth ibethfy #取消注释,并配上从服务到主服务的认证密码(建议用""框上)。
例如:masterauth "abc123"
requirepass ibethfy #三份文件都配置,客户端访问需要密码验证。
例如:requirepass "abc123"
```
**注意:**
replicaof 127.0.0.1 8000 在以前的版本中用的是slaveof 127.0.0.1 8000,这个配置现在也可以使用
### 2.5 启动服务
开启服务
```
./src/redis-server ./redis-8000.conf
./src/redis-server ./redis-8001.conf
./src/redis-server ./redis-8002.conf
```
查看服务是否启动
ps -ef|grep redis
开启三个客户端
```
./src/redis-cli -h 10.1.1.160 -p 8000
./src/redis-cli -h 10.1.1.160 -p 8001
./src/redis-cli -h 10.1.1.160 -p 8002
```
查看主从信息info replication
./src/redis-cli -h 10.1.1.160 -p 8000 -a abc123
10.1.1.160:8000> info replication
### 2.6 读写分离测试
在主上可读可写:
写入set str helloword
在从上可读不可写:
## 三、多机主从(配置一主二从)
为了快速搭建,可以把160单机主从的redis配置打包分发到161和162(161和162未配置什么)
### 3.1 在 Master(10.1.1.160)上打包 Redis
(1) 进入 Redis 安装目录
cd /opt/module/
(2) 打包 Redis 目录
tar -czvf redis6.tar.gz redis6/
这将生成 redis6.tar.gz 压缩包。
### 3.1 将 Redis 分发到 Slave1 和 Slave2
(1) 使用 scp 复制到 Slave1(10.1.1.161)
scp redis6.tar.gz root@10.1.1.161:/opt/module/
(2) 使用 scp 复制到 Slave2(10.1.1.162)
scp redis6.tar.gz root@10.1.1.162:/opt/module/
(3) 在 Slave1 和 Slave2 上解压
在 Slave1(10.1.1.161)执行:
mkdir /opt/module
cd /opt/module/
tar -xzvf redis6.tar.gz
在 Slave2(10.1.1.162)执行:
cd /opt/module/
tar -xzvf redis6.tar.gz
(4)创建软链接方便执行命令
[root@slave1 redis6]# ln -s /opt/module/redis6/src/redis-cli /usr/local/bin/redis-cli
[root@slave2 redis6]# ln -s /opt/module/redis6/src/redis-cli /usr/local/bin/redis-cli
### 3.3 配置 Slave1 和 Slave2 作为从节点
注意:若是直接分发过来,且前面操作都是按照我的来,下面不用修改配置,可直接启动redis。
(1) 修改 Slave1(10.1.1.161)的 Redis 配置
cd /opt/module/redis6/
vim redis-8001.conf # 或直接修改 redis.conf
关键配置(确保和 Master 一致):
ini
protected-mode no
port 8001
daemonize yes
pidfile "./redis_8001.pid"
logfile "./logs/redis_8001.log"
dir "./data/redis_8001"
replicaof 10.1.1.160 8000 # 指向 Master
masterauth "ibethfy" # Master 的密码
requirepass "ibethfy" # 从节点密码(可选)
(2) 修改 Slave2(10.1.1.162)的 Redis 配置
cd /opt/module/redis6/
vim redis-8002.conf # 或直接修改 redis.conf
关键配置(确保和 Master 一致):
ini
protected-mode no
port 8002
daemonize yes
pidfile "./redis_8002.pid"
logfile "./logs/redis_8002.log"
dir "./data/redis_8002"
replicaof 10.1.1.160 8000 # 指向 Master
masterauth "ibethfy" # Master 的密码
requirepass "ibethfy" # 从节点密码(可选)
### 3.4 启动 Redis 服务
(注意:此时master节点自己应该没有8001和8002端口的redis,如果有可以关掉)
# 关闭 8001 端口的 Redis 实例
/opt/module/redis6/src/redis-cli -p 8001 -a abc123 shutdown
# 关闭 8002 端口的 Redis 实例
/opt/module/redis6/src/redis-cli -p 8002 -a abc123 shutdown
(1) 在 Master(10.1.1.160)启动主节点
cd /opt/module/redis6/
./src/redis-server ./redis-8000.conf
(2) 在 Slave1(10.1.1.161)启动从节点
cd /opt/module/redis6/
./src/redis-server ./redis-8001.conf
(3) 在 Slave2(10.1.1.162)启动从节点
cd /opt/module/redis6/
./src/redis-server ./redis-8002.conf
### 3.5 验证主从复制
(1) 在 Master 上检查
redis-cli -h 10.1.1.160 -p 8000 -a ibethfy
INFO replication
预期输出:
role:master
connected_slaves:2
slave0:ip=10.1.1.161,port=8001,state=online
slave1:ip=10.1.1.162,port=8002,state=online
(2) 在 Slave1 和 Slave2 上检查复制状态
redis-cli -h 10.1.1.161 -p 8001 -a ibethfy
redis-cli -h 10.1.1.162 -p 8002 -a ibethfy
INFO replication
预期输出:
role:slave
master_host:10.1.1.160
master_port:8000
master_link_status:up
### 3.6 测试数据同步
(1) 在 Master 写入数据
redis-cli -h 10.1.1.160 -p 8000 -a ibethfy
SET test aaa
(2) 在 Slave1 和 Slave2 读取数据
redis-cli -h 10.1.1.161 -p 8001 -a ibethfy
redis-cli -h 10.1.1.162 -p 8002 -a ibethfy
GET test
预期输出:
"aaa"
注意:因为是读写分离的,所以从只可读不可写
### 3.7 可能遇到的问题
(1) 主从连接失败
检查防火墙:
firewall-cmd --list-ports # 确保 8000-8002 开放
检查密码:masterauth 和 requirepass 必须一致。
检查网络:
ping 10.1.1.160 # 测试连通性
(2) 数据不同步
查看日志:
tail -f /opt/module/redis6/logs/redis_8001.log
检查复制状态:
redis-cli -h 10.1.1.161 -p 8001 -a ibethfy INFO repli
## 四、手动设置主从
(主死机后,从1变主,从2变新主的从)
### 4.1 停掉主(10.1.1.160)
当160虚拟机死机后(停掉8000的redis)
### 4.2 手动设置我们的主从并验证,161为主,162为从
(1)**161执行slaveof no one**
执行命令 SLAVEOF NO ONE 将使得这个从属服务器关闭复制功能,并从从属服务器转变回主服务器,原来同步所得的数据集不会被丢弃。
10.1.1.161:8001> slaveof no one
OK
10.1.1.161:8001> info replication
(2)**162执行slaveof host port**
执行 SLAVEOF host port 将使当前服务器停止对旧主服务器的同步,丢弃旧数据集,转而开始对新主服务器进行同步。
10.1.1.162 8002> slaveof 10.1.1.161 8001
OK
10.1.1.162 8002> info replication
如果报错如下:
连接状态是down
可以先
SLAVEOF NO ONE # 先解除旧配置
SLAVEOF 10.1.1.161 8001 # 重新指向新 Master
如果还是down,可以排查以下问题
故障总结表
现象 | 可能原因 | 解决方案 |
---|---|---|
master_link_status:down | 网络不通 | 检查防火墙/网络 |
主节点无 connected_slaves | 主节点未允许连接 | 修改 bind 和 protected-mode |
认证失败 | 密码不匹配 | 检查 requirepass 和 masterauth |
连接超时 | 端口未开放 | 开放 8001 端口 |