Redis高可用之主从复制实践

606 阅读6分钟

前言

Redis支持多种高可用方案如Redis Sentinel 集群和 Redis 数据集群,但是今天我们的主题是Redis的主从复制。而且今天我们重点在于如何搭建Redis的主从复制,不着重与主从复制的原理。废话不多说,那么我们就来实践Redis主从复制的搭建。

什么是主从复制

开始动手之前,我们先简单聊一聊什么是主从复制?主从复制是指将一个Redis服务器的数据,复制到其他的Redis服务器,这就叫做主从复制。在这个现象中前者称之为主节点(master),后者称之为从节点(slave);数据的复制是单向的,只能由主节点到从节点。

默认情况下,每台Redis服务器都是主节点;且一个主节点可以有0个或者有1个以上的从节点,但一个从节点只能有一个主节点。

主从复制的作用

当我们知道了什么是主从复制,那我们肯定也要知道为啥需要主从复制了,不然只知道怎么去做,不知道为啥去做,也是蛮烦恼的。Redis的主从复制到底有啥用,这个我们就可以看看如果只有单机情况下的Redis宕机,我们到底会面临啥问题,自然就能得出Redis的主从复制的作用,这里我们就不展开说,直接给出结论。Redis的主从复制主要有以下几种作用:

  • 数据备份。单个Redis一旦宕机,就有可能丢失所有数据,主从复制实现了数据的热备份,即使master宕机丢失数据,只要有slave存在我们就可以找回数据。

  • 负载均衡。搭建好了主从,我们就可以只让主负责写服务,其他从负责读服务,这样在读多写少的场景下,通过多个从节点的分担读请求,就可以实现提高Redis的并发量,从而提高系统的性能。

  • 高可用基础。Redis这种主从复制在master发生故障时不能自动从slave中选举、切换master,需要人工干预。总的来说不够智能,后续的哨兵模式、Redis集群能够解决这些问题,但是又建立在Redis这种主从复制上,所以说他是高可用的基础。

    后面我们就来说一说,如何搭建Redis的主从复制。

服务器准备

目前手里买的服务器都已经过期了,只能拿自己的电脑做实验,所以直接把Redis目录复制三份,并将每一份的配置文件redis.conf中端口号port配置进行修改。

# 将端口号6379分别修改成下表中的样子
port 6379
ip端口角色
192.168.0.1036379master
192.168.0.1036380slave
192.168.0.1036381slave

建立复制的相关命令

需要注意的是,Redis主从复制的开启,完全是在从节点发起的;不需要我们在主节点做任何事情。

从节点开启主从复制,有以下三种方式:

  • 通过配置文件开启 在从服务器的配置文件中指定具体的master的地址,配置格式如下:
slaveof <masterip> <masterport>
# 如果master有密码
masterauth <master-password>

在配置文件redis.conf中添加以下配置:

slaveof 192.168.1.103 6379  
# 如果master有密码
masterauth 2021
  • 启动从服务器时开启 redis-server启动命令后加入参数 --slaveof <masterip> <masterport>,如果master有密码,则需要加入密码参数。 --requirepass <password> 最终的启动命令如下:
redis-server.exe  ./redis.conf  --slaveof 127.0.0.1 6379 --masterauth 2021
  • 客户端处执行命令开启 在Redis客户端如redis-cli 中执行命令 slaveof <masterip> <masterport>来指定主服务器,如果master有密码则需要紧接着执行下面的命令:

     config set masterauth 2021
    

上述3种方式最终的效果都是一样的的,大家可以自己试一试。这里以第二种方式为例,看一下当执行了slaveof后,Redis主节点和从节点的变化。

观察效果

在master的客户端上执行命令info replication client list 可以看到下图所示的信息:

master客户端执行命令

在端口号为6381的slave上执行 info replication命令可以看到下面的信息:

image-20210824102950905

由两张图的信息可以看出,端口号为6379的服务器角色是master,端口号6380和6381的服务器角色是slave,那么接下来我们试试到底他们之间能不能同步数据。

从下图可以看出master和slave都是没有数据的(6380的机器也是一样我就没有放上来)

image-20210824103634434

image-20210824103710285

那么我们接下来就开始测试:

  1. 在master上执行命令:
set test 123

image-20210824104056704

  1. 到对应的slave去查询这个key

image-20210824104139046

从节点已经有了数据,读取出来数据也是正确的。

  1. 接下来我们在master上删除这个key。

    image-20210824104302555

  2. 再到对应的slave上读取这个key,可以发现数据已经没有了。

    image-20210824104352911

  3. 我们在master在增加一些数据,然后将slave6381和master断开主从关系,看看有什么现象。

    image-20210824104725960

在确保slave6381已经有了上述数据之后,我们执行下面的命令断开主从关系。

slaveof no one

记住我们在前文说到过“Redis主从复制的开启,完全是在从节点发起的;不需要我们在主节点做任何事情”,所以这个命令是在slave6381上执行的,大家千万别搞错了!

slave6381执行命令之后信息如图所示,我们发现断开了关系,但是slave6381上从master上同步过来的数据仍然存在。因为从节点断开复制后,不会删除已有的数据,只是不再同步主节点新的数据变化。

image-20210824105216945

主节点打印的日志如下图所示,显示slave6381已经下线。

主节点打印的日志

下面是redis主从复制场景的一些可调参数,需要根据实际环境调整

  • slave-serve-stale-data yes : 是否可以把不新鲜的数据服务与客户端
  • slave-read-only yes : 从节点只读,启用slaveof定义后才生效
  • repl-diskless-sync no :是否同时向多个从节点同时发数据
  • repl-diskless-sync-delay 5 :发送的延迟时间
  • repl-ping-slave-period 10 探测从节点状态
  • repl-timeout 60 探测节点超时时间
  • repl-disable-tcp-nodelay no : 启用nodelay
  • repl-backlog-size 1mb
  • slave-priority 100 : 从节点优先级,复制集群中,主节点故障时,sentinel应用场景中的主节点选举时使用的优先级;数字越小优先级越高,但0表示不参与选举;
  • min-slaves-to-write 3:主节点仅允许其能够通信的从节点数量大于等于此处的值时接受写操作;
  • min-slaves-max-lag 10:从节点延迟时长超出此处指定的时长时,主节点会拒绝写入操作

总结

综上所述,简单的Redis主从复制就搭建好了。另外提一下,slave 可以接受其他 slave 的连接。除了多个 slave 可以连接到同一个 master 之外, slave 之间也可以像层叠状的结构(cascading-like structure)连接到其他 slave 。自 Redis 4.0 起,所有的 sub-slave 将会从 master 收到完全一样的复制流。本文这里呢只是简单搭建一下主从复制,有兴趣的同学可以自己试一试。