记录生活中的点点滴滴

0%

redis学习6:主从复制

这一篇文章写一下 redis 的主从复制,再介绍一下哨兵模式。

概念

主从复制,是指将一台 redis 服务器的数据,复制到其他的redis服务器,前者称为 主节点(master/leader),后者称为从节点(slave/follower);数据的复制是单向的,只能由主节点到从节点。Master 以写为主,Slave 以读为主。

默认情况下,每台 redis 服务器都是主节点;且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点。

主从复制的作用:

1、数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。

2、故障恢复:当主节点出现问题时,可以有从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余。

3、负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即redis 数据应用连接主节点,读 redis 数据时应用连接从节点),分担服务器负载;尤其是在写少读多的情况下,通过多个从节点分担负载,可以大大提高 redis 服务器的并发量。

4、高可用基石:除了上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是 redis 高可用的基础。

一般来说,要将 redis 运用到工程项目中,只使用一台 redis 是万万不能的,原因如下:

1、从结构上看,单个 redis 服务器会发生单点故障,并且一台服务器需要处理所有的负载请求,压力较大;

2、从容量上看,单个 redis 服务器内存容量有限,就算一台 redis 服务器内存容量为256G,也不能将所有内存用作 redis 存储内存,一般来说,单台 redis 最大使用内存不应该超过20G。

主从复制,读写分离!80%的情况都是读!减缓服务器的压力。

https://www.cnblogs.com/sxdcgaq8080/p/9178926.html)

搭建集群

下面我们以一主二从为例(一个master,两个slave),我们先搭建一个集群,我这边有三个 linux ,三台中全部装好 redis。

安装 redis 可以参考 CentOS 7安装redis

在VMware中,这些虚拟机全部选择桥接网络。

其中ssh连接可以参照博客:ssh连接CentOS 7

1
2
3
4
5
6
7
8
9
10
11
12
13
127.0.0.1:6379> info replication # 查看当前库的信息
# Replication
role:master # 角色 master
connected_slaves:0 # 没有从机
master_replid:599307b26a05885a49e473a9349c24bdaf09f5e3
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
127.0.0.1:6379>

一主二从

默认三台机器全部都是主机,即查看库信息默认都是 master。

我的三台 linux 机器的 ip 分别是:192.168.43.94192.168.43.40192.168.43.122

下面我们让 94 这台主机做主机,40 122这两台主机做从机。

当然在开始下面的操作前,我们要确定我们这三台机器能相互 ping 通。

下面我们修改配置文件

主机配置如下:

从机配置如下:

这个时候启动我们的主机和从机的redis服务器,再启动客户端并查看 info replication

主机的情况如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:1 # 这一点很重要,1表示与我们主机相连接的从机有1个
slave0:ip=192.168.43.122,port=6379,state=online,offset=1622,lag=1 # 这个就是对应的从机0的信息
master_replid:324732102fc57a0394600cb50a49616f71ce02a0
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:1622
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:1622

一定要确保 connected_slaves 的值不是0,是0的话说明没有从机和我们的主机建立好连接,先不着急,后续有解决方法。先继续查看从机的情况。

从机的情况如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
127.0.0.1:6379> info replication
# Replication
role:slave
master_host:192.168.43.206
master_port:6379
master_link_status:up # 这个很重要,up代表连接通了,如果是down说明还没连通
master_last_io_seconds_ago:10
master_sync_in_progress:0
slave_repl_offset:1608
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:324732102fc57a0394600cb50a49616f71ce02a0
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:1608
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1075
repl_backlog_histlen:534

一定要确保我们的参数显示是正确的,如果不正确说明 主机、从机建立连接失败。

我们可以通过查看日志去看看是什么原因,一般是从机这边会报错误,所以我们可以设置从机的配置信息,把日志文件改成一个文件,让日志输出到这个文件夹,便于我们后续查看。

这样如果觉得麻烦的话,还有一种方法,就是把从机的守护线程关闭,这样 redis 服务器运行的时候就会一直在终端界面上,我们再另开一个终端登录 redis 的客户端,这样我们就能看到是什么原因了。

下面我们分析一些常见的错误:

1、 Connection refused

说了一大推,就是主机拒绝我们从机的连接,应该是主机配置文件中的 bind ,我们要设置成 0.0.0.0,绑定所有ip,确保从机可以连接到它。

2、No route to host

主机、从机的路由出现了问题,看能不能ping通,我的能ping通。但是就是不能建立连接,上网查了一下,看到下面的解决方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
1.关闭防火墙:service iptables stop

2.如果出现以下异常

Redirecting to /bin/systemctl stop iptables.service

Failed to stop iptables.service: Unit iptables.service not loaded.

(其他异常也可以试下)

3.进入/etc/sysconfig/目录下查询有没有iptables文件

4.如果没有,使用systemctl stop firewalld 关闭防火墙

5.使用yum install iptables-services 安装或者更新服务

6.service iptables stop尝试下关闭服务器

7.关闭成功无异常,重启maste和slave,进入redis-cli 输入info就能看到maste和slave信息了

也不知道为什么,反正这样就可以了???

得了,就这吧!

细节:

主机只能写,从机不能写只能读!主机中所有的信息,都会自动被从机保存

下面我们测试一下,刚开始主机和从机全部为空:

然后我们在主机上面设置 key和value,可以看到从机会自动跟着主机变化数据也改变:

其实好像不需要主机密码也可以,现在可以试试吧密码那一行注释掉,然后两台从机记得也把配置文件密码那一行注释掉,应该也是可以的。

复制原理

Slave 启动成功连接到 Master 后会发送一个 sync 同步命令。

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

全量复制:slave服务器在接收到数据库文件数据后,将其存盘并加载到内存中。(刚开始建立连接时)

增量复制:Master服务器继续将所有收集到的修改命令一次传给slave,完成同步。(后续连接建立完成后)

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

主机宕机

但是如果当我们的主机宕机之后,从机会怎么办呢?

从机宕机之后,我们的从机日志中显示从机会一直尝试与主机建立连接:

此时查看 info replication 如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
127.0.0.1:6379> info replication
# Replication
role:slave
master_host:192.168.43.206
master_port:6379
master_link_status:down
master_last_io_seconds_ago:-1
master_sync_in_progress:0
slave_repl_offset:1353
master_link_down_since_seconds:10
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:102f376f875f58baf401b4da308826aa1eb6f0a0
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:1353
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:574
repl_backlog_histlen:780

我们可以通过命令 slaveof no one ,从机让自己再次变成主机,日志信息也会不再生成:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
127.0.0.1:6379> slaveof no one # 从机让自己变成主机
OK
127.0.0.1:6379> info replication # 再次查看信息
# Replication
role:master
connected_slaves:0
master_replid:e9c251fb2d5e007b0fc96e23bc6dcf2223e96ebf
master_replid2:102f376f875f58baf401b4da308826aa1eb6f0a0
master_repl_offset:1353
second_repl_offset:1354
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:574
repl_backlog_histlen:780
127.0.0.1:6379>

哨兵模式

哨兵模式就可以为我们解决上面主机宕机之后 redis 集群瘫痪的情况。

主从切换的技术的方法是 当主服务器宕机之后,需要手动把一台从服务器切换成主服务器,这就需要人工干预,费事费力,还会造成一段时间内服务不可用,不推荐。

更多时候,我们优先考虑哨兵模式,Redis 2.8 开始正式提供了 Sentinel(哨兵)架构来解决这个问题。

它能够监控主机是否故障,如果故障了根据投票数自动将从机变成主机

哨兵模式是一种特使的模式,首先 redis 提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行。其原理是哨兵通过发送命令,等待 redis 服务器响应,从而监控运行的多个 redis 实例。

这里的哨兵有两个作用:

  • 通过发送命令,让 redis 服务器返回监控其运行状态,包括主服务器和从服务器。
  • 当哨兵监测到master宕机,它自动将slave切换成master,然后通过发布订阅模式通知其他的服务器,修改配置文件,让他们切换主机

然而一个哨兵进程对redis服务器进行监控,可能会出现问题,为此,我们可以使用多个哨兵进行监控,各个哨兵之间还会监控,这样就形成了多哨兵模式。

假设主服务器宕机,哨兵1会先检测到这个结果,系统并不会马上进行failover过程,仅仅是哨兵1主观的认为主服务器不可用,这个现象称为主观下线,后面的哨兵也检测到主服务器不可用,并且数量达到一定值时,那么哨兵之间就会进行一次投票,投票的结果由一个哨兵发起,进行failover【故障转移】操作。切换成功后,就会通过订阅发布模式,让各个哨兵把自己监控的从服务器实现切换主机,这个过程称为客观下线

测试

首先确保我们三台机器的 都设置了密码:(切记:三台机器

然后还有 protected-mode 设置成no:

bind全部设置成 0.0.0.0

主从复制那一栏的密码全都都是上面设置的密码:(注意这个也是三个,主机也要设置

上面都是三台机器全部都得设置的,切记!!!

1、先随便在一个从机的redis bin目录下,创建 sentinel.conf 文件,并写入下列配置:

1
2
3
# sentinel monitor 被监控的名称 主机host port 1
sentinel monitor mymaster 192.168.43.206 6379 1
sentinel auth-pass mymaster 123456

后面这个数字1,代表主机挂了,slave投票看让谁接替成为主机,票数最多的会成为主机!

2、启动哨兵 :./redis-sentinel sentinel.conf

3、让主机宕机

等待几秒钟,可以看到哨兵的日志如下:

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
[root@localhost bin]# ./redis-sentinel sentinel.conf
8211:X 19 Dec 2020 18:49:47.444 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
8211:X 19 Dec 2020 18:49:47.444 # Redis version=5.0.7, bits=64, commit=00000000, modified=0, pid=8211, just started
8211:X 19 Dec 2020 18:49:47.444 # Configuration loaded
8211:X 19 Dec 2020 18:49:47.445 * Increased maximum number of open files to 10032 (it was originally set to 1024).
_._
_.-``__ ''-._
_.-`` `. `_. ''-._ Redis 5.0.7 (00000000/0) 64 bit
.-`` .-```. ```\/ _.,_ ''-._
( ' , .-` | `, ) Running in sentinel mode
|`-._`-...-` __...-.``-._|'` _.-'| Port: 26379
| `-._ `._ / _.-' | PID: 8211
`-._ `-._ `-./ _.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' | http://redis.io
`-._ `-._`-.__.-'_.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' |
`-._ `-._`-.__.-'_.-' _.-'
`-._ `-.__.-' _.-'
`-._ _.-'
`-.__.-'

8211:X 19 Dec 2020 18:49:47.445 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
8211:X 19 Dec 2020 18:49:47.445 # Sentinel ID is 0f7358e160f6100583a3a93d8328fb5deabf77c4
8211:X 19 Dec 2020 18:49:47.445 # +monitor master mymaster 192.168.43.206 6379 quorum 1
8211:X 19 Dec 2020 18:49:47.448 * +slave slave 192.168.43.122:6379 192.168.43.122 6379 @ mymaster 192.168.43.206 6379
8211:X 19 Dec 2020 18:49:47.449 * +slave slave 192.168.43.40:6379 192.168.43.40 6379 @ mymaster 192.168.43.206 6379

# 下面是主机宕机后的日志:
# 发现主机宕机了
8211:X 19 Dec 2020 18:50:38.847 # +sdown master mymaster 192.168.43.206 6379
# 投票后有1个sentinel发现master不能用
8211:X 19 Dec 2020 18:50:38.847 # +odown master mymaster 192.168.43.206 6379 #quorum 1/1
# 当前配置版本被更新
8211:X 19 Dec 2020 18:50:38.847 # +new-epoch 2
# 达到故障转移failover条件,正等待其他sentinel的选举
8211:X 19 Dec 2020 18:50:38.847 # +try-failover master mymaster 192.168.43.206 6379
# 进行投票选举slave服务器
8211:X 19 Dec 2020 18:50:38.848 # +vote-for-leader 0f7358e160f6100583a3a93d8328fb5deabf77c4 2
8211:X 19 Dec 2020 18:50:38.848 # +elected-leader master mymaster 192.168.43.206 6379
8211:X 19 Dec 2020 18:50:38.848 # +failover-state-select-slave master mymaster 192.168.43.206 6379
# 选举一个slave当选为新的master
8211:X 19 Dec 2020 18:50:38.939 # +selected-slave slave 192.168.43.122:6379 192.168.43.122 6379 @ mymaster 192.168.43.206 6379
# 把选举出来的slave进行身份master切换
8211:X 19 Dec 2020 18:50:38.939 * +failover-state-send-slaveof-noone slave 192.168.43.122:6379 192.168.43.122 6379 @ mymaster 192.168.43.206 6379
8211:X 19 Dec 2020 18:50:39.039 * +failover-state-wait-promotion slave 192.168.43.122:6379 192.168.43.122 6379 @ mymaster 192.168.43.206 6379
8211:X 19 Dec 2020 18:50:39.482 # +promoted-slave slave 192.168.43.122:6379 192.168.43.122 6379 @ mymaster 192.168.43.206 6379
# 把故障转移failover改变reconf-slaves
8211:X 19 Dec 2020 18:50:39.482 # +failover-state-reconf-slaves master mymaster 192.168.43.206 6379
# sentinel发送slaveof命令把133重新同步132master
8211:X 19 Dec 2020 18:50:39.539 * +slave-reconf-sent slave 192.168.43.40:6379 192.168.43.40 6379 @ mymaster 192.168.43.206 6379
# slave被重新配置为另外一个master的slave,但数据还未发生
8211:X 19 Dec 2020 18:50:40.547 * +slave-reconf-inprog slave 192.168.43.40:6379 192.168.43.40 6379 @ mymaster 192.168.43.206 6379
# 与master进行数据同步
8211:X 19 Dec 2020 18:50:40.547 * +slave-reconf-done slave 192.168.43.40:6379 192.168.43.40 6379 @ mymaster 192.168.43.206 6379
# 故障转移完成
8211:X 19 Dec 2020 18:50:40.614 # +failover-end master mymaster 192.168.43.206 6379
# master地址发生改变
8211:X 19 Dec 2020 18:50:40.614 # +switch-master mymaster 192.168.43.206 6379 192.168.43.122 6379
# 检测slave并添加到slave列表
8211:X 19 Dec 2020 18:50:40.614 * +slave slave 192.168.43.40:6379 192.168.43.40 6379 @ mymaster 192.168.43.122 6379
8211:X 19 Dec 2020 18:50:40.614 * +slave slave 192.168.43.206:6379 192.168.43.206 6379 @ mymaster 192.168.43.122 6379
8211:X 19 Dec 2020 18:51:10.634 # +sdown slave 192.168.43.206:6379 192.168.43.206 6379 @ mymaster 192.168.43.122 6379
8211:X 19 Dec 2020 18:51:31.667 # -sdown slave 192.168.43.206:6379 192.168.43.206 6379 @ mymaster 192.168.43.122 6379
8211:X 19 Dec 2020 18:51:41.657 * +convert-to-slave slave 192.168.43.206:6379 192.168.43.206 6379 @ mymaster 192.168.43.122 6379

如果主机回来了,只能归并到新的主机下,当做从机,这就是哨兵模式的规则!

然后我们还可以再次让新的主机宕机,那么过几秒后,它会再次为我们选择新的主机。

如此套娃,前提是三台机器至少要保证一台在运行。如果仅剩一台,这一台就会是主机。

注意观察日志,还挺好玩的!!!

另外我还发现配置文件中原本那个配置原来的 主机的ip和端口的,就是 replicaof 192.168.43.122 6379

伴随着哨兵的切换,它会自动改变,并在配置文件的最后一行显示,主机的这个配置是没有的

我们现在的主机是122,那么在 40 206 这两个机器的配置文件最后一行就会有这个设置,如下:

下面简单写一下哨兵模式的优点和缺点

优点:

1、哨兵集群,基于主从复制模式,所有的主从配置优点,它全有

2、主从可以切换,故障可以转移,系统的可用性就会更好

3、哨兵模式就是主从模式的升级,手动到自动,更加健壮

缺点:

1、redis不好在线扩容,集群数量一旦到达上限,在线扩容会非常麻烦

2、实现哨兵模式的配置其实是很麻烦的,里面有很多选择!