Redis-主从复制

主从复制

主从复制,是指将一台Redis服务器中的数据,复制到其他的Redis服务器上。

前者称为主节点(master/leader),后者称为从节点(slave/follower)

数据的复制是单向的,只能由主节点到从节点。Master以写为主,Slave 以读为主。

且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点。

作用

主从复制的作用主要包括:

1、数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
2、故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复
3、负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务,分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。
4、高可用(集群)基石:主从复制还是哨兵模式和部署集群能够实施的基础,因此说主从复制是Redis高可用的基础。

一般来说,要将Redis运用于工程项目中,只使用一台Redis是万万不能的,最少三台(一主二从)

​ 1、从结构上,单个Redis服务器会发生单点故障,并且一台服务器需要处理所有的请求负载,压力较大
​ 2、从容量上,不能将一台服务所有内存用作Redis存储内存,单台Redis最大使用内存不应该超过20G

配置子节点

我们这里使用docker来做

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# 复制两份配置文件给从节点镜像使用
[root@iZbp18qscowpmxk6xpk38iZ redis]# ls
redis-01.conf redis-02.conf redis.conf

# 需要修改这三份文件,将绑定本地的配置注释掉,关闭安全模式

# 分别以后台方式启动两个从节点
[root@iZbp18qscowpmxk6xpk38iZ redis]# docker run -P -it -d -v /home/redis/redis-01.conf:/etc/redis/redis.conf --name=salveRedis01 redis
a593c51bc1100e892f5d18c34ba5a05f637d1b3a4a29e5840cfeb18a633355f5
[root@iZbp18qscowpmxk6xpk38iZ redis]# docker run -P -it -d -v /home/redis/redis-02.conf:/etc/redis/redis.conf --name=salveRedis02 redis
08833de79be2cf719402b4f4cf42bf06d0f0a84a22e188f2b2f4d03f54ca48c1
# 查看映射端口,这里一定一定要注意!!服务器要开安全组!!!不然就是连接失败哎!!!
[root@iZbp18qscowpmxk6xpk38iZ redis]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a593c51bc110 redis "docker-entrypoint.s…" 24 minutes ago Up About a minute 0.0.0.0:49169->6379/tcp salveRedis01
08833de79be2 redis "docker-entrypoint.s…" 24 minutes ago Up About a minute 0.0.0.0:49170->6379/tcp salveRedis02
0e9919007f5d redis "docker-entrypoint.s…" 38 minutes ago Up 2 minutes 0.0.0.0:49168->6379/tcp masterRedis

# 查看主节点的基本信息
[root@iZbp18qscowpmxk6xpk38iZ ~]# docker exec -it masterRedis redis-cli
127.0.0.1:6379> info replication
# Replication
role:master # 当前节点的角色
connected_slaves:0 # 当前节点的子节点
master_failover_state:no-failover
master_replid:f37ca91dd3b3578e83031f9ea087d64f9994dd9a
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

# 进入子节点1号的客户端,并配置父节点
[root@iZbp18qscowpmxk6xpk38iZ redis]# docker exec -it salveRedis01 redis-cli
127.0.0.1:6379> SLAVEOF 116.62.151.26 49168
OK
127.0.0.1:6379> role
1) "slave"
2) "116.62.151.26"
3) (integer) 49168
4) "connected" #说明连接成功,如果没开安全组的话,这一行会是connecting下一行是-1,表示连接失败
5) (integer) 42

# 进入子节点2号的客户端,并配置父节点
[root@iZbp18qscowpmxk6xpk38iZ redis]# docker exec -it salveRedis02 redis-cli
127.0.0.1:6379> SLAVEOF 116.62.151.26 49168
OK
127.0.0.1:6379> role
1) "slave"
2) "116.62.151.26"
3) (integer) 49168
4) "connected"
5) (integer) 112

# 查看父节点的基本信息
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2 # 两个子节点
slave0:ip=116.62.151.26,port=6379,state=online,offset=112,lag=0
slave1:ip=116.62.151.26,port=6379,state=online,offset=112,lag=1
master_failover_state:no-failover
master_replid:92ee701d04326eb2c74d8de1ea0fc2ec010f97df
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:112
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:112

# 在父节点测试是否数据同步
127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> set k1 v1
OK

# 子节点1号查询
127.0.0.1:6379> get k1
"v1"

# 子节点2号查询
127.0.0.1:6379> get k1
"v1"

也可以在配置文件中配置父节点

1
2
3
4
5
6
# 配置主节点的ip的端口
slaveof 主机ip 端口

# 如果主机使用了config set masterauth password,或者主机配置文件中 requirepass password
# 则这里配置文件就要加上主机的密码来验证
masterauth password

主机可以写入也可以读取,但是从节点是不可以写入的,只可以读取主节点写入的值

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

主机宕机了之后,从机依旧可以读,但是这样的话,就不能往里面写入数据了。

(这里需要使用哨兵模式,即当主机宕机后,从机中会选举出来一个主机,这样的话就保留了写入操作)

当主机恢复运行,则恢复写入功能

从机宕机的话,对主机没有任何影响

当从机运行后,就恢复主机中的数据

复制原理

Slave 启动成功连接到 master 后会发送一个sync命令

Master 接到命令,启动后台的存盘进程,同时收集所有接收到的用于修改数据集命令,在后台进程执行完毕之后,master将传送
整个数据文件到slave,并完成一次完全同步。

  • 全量复制:slave服务在接收到数据库文件数据后,将其存盘并加载到内存中。

  • 增量复制:Master 继续将新的所有收集到的修改命令依次传给slave,完成同步

但是只要是重新连接master,一次完全同步(全量复制)将被自动执行

主从连接的形式

  1. 一对多
  1. 链状

哨兵(Sentinel)模式

该模式就是为了解决当主机宕机后,从机群无法有写入权限的问题。

该模式下,它会自动监控主机是否故障,当主机宕机后,从机群中会自立一个主机,从而就有了写入的功能

哨兵模式是一种特殊的模式,它是一个独立的进程。

其原理就是哨兵通过发送命令,等待redis服务器响应,从而监控多个Redis实例的功能

这里的哨兵有两个作用

  1. 监控服务器的状态
  2. 当主机宕机后,会自动选择一个子节点作为主机,然后通过发布订阅模式通知其他子节点,修改配置文件

当然,如果哨兵挂了怎么办?所以需要配置多个哨兵,然后这几个哨兵再互相监视

假设主服务器宕机,哨兵1先检测到这个结果,系统并不会马上进行重新选举的过程,仅仅是哨兵1主观的认为主服务器不可用,这个现象称为主观下线。当后面的哨兵也检测到主服务器不可用,并且数量达到一定值时,那么哨兵之间就会进行一次投票,投票的结果由一个哨兵发起,进行failover(故障转移)操作。

切换成功后,就会通过发布订阅模式,让各个哨兵把自己监控的从服务器实现切换主机,这个过程称为客观下线

配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 哨兵进程的端口
port 26379

# 是否以后台运行
daemonize no

# 绑定的线程
pidfile /var/run/redis-sentinel.pid

# 日志名称
logfile ""

# 日志保存目录
dir /tmp

# 配置监视谁
# 2代表至少要有结果哨兵确认主机宕机
sentinel monitor mymaster 127.0.0.1 6379 2

sentinel down-after-milliseconds mymaster 30000

acllog-max-len 128

sentinel parallel-syncs mymaster 1

sentinel failover-timeout mymaster 180000

sentinel deny-scripts-reconfig yes

SENTINEL resolve-hostnames no

SENTINEL announce-hostnames no

启动哨兵进程

1
[root@iZbp18qscowpmxk6xpk38iZ redis]# docker run -d -p 49103:26379 -v /home/redis/sentinel.conf:/etc/redis/sentinel.conf --name=sentinel redis redis-sentinel /etc/redis/sentinel.conf 

优点:

  1. 主从可以自动切换,可用性会更好

缺点:

  1. redis不好在线扩容
  2. 实现哨兵模式的配置优点麻烦
给作者买杯咖啡吧~~~