Redis搭建主从复制实现高可用

Redis搭建主从复制实现高可用,第1张

Redis搭建主从复制实现高可用

高可用 HA(High Availability)是分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计减少系统不能提供服务的时间。

假设系统一直能够提供服务,我们说系统的可用性是 100%。如果系统每运行 100 个时间单位,会有 1 个时间单位无法提供服务,我们说系统的可用性是 99%。很多公司的高可用目标是 4 个 9,也就是 99.99%,这就意味着,系统的年停机时间为 8.76 个小时。

那么如何保证系统的高可用呢

首先,在整个架构的每个节点中,不允许存在单点问题,因为单点一定是高可用最大的风险点,我们应该在系统设计过程中去避免单点问题。

在实现方法上,一般采用的就是集群部署、或者冗余部署来实现。这样的设计使得如果某个节点出现故障,其他的节点还可以继续使用。

1. Redis 中高可用设计的必要性

Redis 作为一个高性能 Nosq 中间件,会有很多热点数据存放在 Redis 中,一旦 Redis-server 出现故障,会导致所有相关业务访问都出现问题。另外,即便是设计了数据库兜底的方案,大量请求对数据库的访问也很容易导致数据库出现瓶颈,造成更大的灾难。

除此之外,Redis 的集群部署还可以带来额外的收益:

  • 负载(性能),Redis 本身的 QPS 已经很高了,但是如果在一些并发量非常高的情况下,性能还是会受到影响。这个时候我们希望有更多的 Redis 服务来完成工作
  • 扩容(水平扩展),第二个是出于存储的考虑。因为 Redis 所有的数据都放在内存中,如果数据量大,很容易受到硬件的限制。升级硬件收效和成本比太低,所以我们需要有一种横向扩展的方法

在 Redis 中,提供了高可用方案包含以下几种:

  • 主从复制(用来实现读写分离)
  • 哨兵机制(实现 master 选举)
  • 集群机制(实现数据的分片)
2. Redis 的 Master-Slave 方法

主从复制模式,简单来说就是把一台 Redis 服务器的数据,复制到其他 Redis 服务器中。其中负责复制数据的来源称为 master,被动接收数据并同步的节点称为 slave,数据的复制是单向的,如下图所示,对于主从模式,其实有很多的变体。

在很多组件中都有使用这种思想,比如 mysql 的主从复制、redis 的主从复制、activemq 的主从复制、kafka 里面的数据副本机制等等。

2.1 主从复制的好处
  1. 数据冗余,主从复制实现了数据的热备,是除了持久化机制之外的另外一种数据冗余方式。
  2. 读写分离,使数据库能支撑更大的并发。在报表中尤其重要。由于部分报表 sql 语句非常的慢,导致锁表,影响前台服务。如果前台使用 master,报表使用 slave,那么报表 sql 将不会造成前台锁,保证了前台速度。
  3. 负载均衡,在主从复制的基础上,配合读写分离机制,可以由主节点提供写服务,从节点提供服务。在读多写少的场景中,可以增加从节点来分担 redis-server 读 *** 作的负载能力,从而大大提高 redis-server 的并发量
  4. 保证高可用,作为后备数据库,如果主节点出现故障后,可以切换到从节点继续工作,保证 redis-server 的高可用。
2.2 Redis 如何配置主从复制

需要注意,Redis 的主从复制,是直接在从节点发起就行,主节点不需要做任何事情

在 Redis 中有三种方式来开启主从复制。

  • 在从服务器的 redis.conf 配置文件中加入下面这个配置

    replicaof  
    
  • 通过启动命令来配置,也就是启动 slave 节点时执行如下命令

    ./redis-server ../redis.conf --replicaof  
    
  • 启动 redis-server 之后,直接在客户端窗口执行下面命令

    redis>replicaof  
    
2.2.1 准备三台虚拟机

准备好三台虚拟机,并且这三台虚拟机需要能相互 ping 通,以及相互能够访问 6379 这个端口,如果访问不了,需要关闭防火墙。当然了,可以直接正三台服务器测试。

firewall-cmd –zone=public –add-port=6379/tcp –permanent

  • 192.168.183.130(master)
  • 192.168.183.131(slave)
  • 192.168.183.132(slave)

这三台机器上都需要安装 redis-server,安装步骤如下。

注意事项,Redis6 安装需要 gcc 版本大于 5.3 以上,否则安装会报错。

# 升级到gcc 9.3:
yum -y install centos-release-scl
yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils
scl enable devtoolset-9 bash
# 需要注意的是scl命令启用只是临时的,退出shell或重启就会恢复原系统gcc版本。
# 如果要长期使用gcc 9.3的话:
echo -e "nsource /opt/rh/devtoolset-9/enable" >>/etc/profile

开始安装

wget http://download.redis.io/releases/redis-5.0.3.tar.gz
tar -zxvf redis-5.0.3.tar.gz
# 执行编译
cd redis-5.0.3
make
# 安装到指定目录
make install PREFIX=/usr/local/redis
2.2.2 演示配置过程

在 192.168.183.131 和 192.168.183.132这两台机器上分别按照下面的 *** 作增加配置。

  • 编辑 redis.conf 文件,通过 shift+g 跳转到最后一行,增加如下配置

    replicaof 192.168.183.130 6379
    
  • 分别启动这两台机器,启动成功后,使用如下命令查看集群状态

    redis> info replication
    

  • 启动日志中可以看到,在启动过程中已经从 master 节点复制了信息。

    46765:S 27 Nov 2021 15:40:21.625 * Ready to accept connections
    46765:S 27 Nov 2021 15:40:21.625 * Connecting to MASTER 192.168.183.130:6379
    46765:S 27 Nov 2021 15:40:21.626 * MASTER <-> REPLICA sync started
    46765:S 27 Nov 2021 15:40:21.626 * Non blocking connect for SYNC fired the event.
    46765:S 27 Nov 2021 15:40:21.627 * Master replied to PING, replication can continue...
    46765:S 27 Nov 2021 15:40:21.629 * Trying a partial resynchronization (request 2019d62fdf44c95d2a0b326e4cffa1814b11d4b2:43).
    46765:S 27 Nov 2021 15:40:21.629 * Successful partial resynchronization with master.
    46765:S 27 Nov 2021 15:40:21.629 * MASTER <-> REPLICA sync: Master accepted a Partial Resynchronization.
    

有可能会出现链接失败的情况。

  • 修改redis.conf中bind 127.0.0.1 为 bing 0.0.0.0
  • 在centos7中,systemctl stop firewalld即可关闭防火墙。其他版本可通过service iptables stop关闭防火墙。
  • 重新启动服务即可

如果没有开启日志,可以通过下面的方法进行开启

  • 找到 Redis 的配置文件 redis.conf
  • 打开该配置文件, vi redis.conf;
  • 通过 linux 的查询命令找到 (loglevel 下面) logfile “ “ ;
  • 在冒号里面输入日志的路径,比如 logfile “/usr/local/redis/log/redis.log”, 需要提前创建好目录和文件,redis 默认不会创建该文件。

接着,我们在 master 节点上通过设置一些 key,会发现数据立刻就同步到了两个 slave 节点上,从而完成了主从同步功能。不过在默认情况下,slave 服务器是只读的,如果直接在 slave 服务器上做修改,会报错。不过可以在 slave 服务器的 redis.conf 中找到一个属性,允许 slave 服务器可以写,但是不建议这么做。因为 slave 服务器上的更改不能往 master 上同步,会造成数据不同步的问题

slave-read-only no 
2.3 Redis 主从复制的原理分析

Redis 的主从复制分两种,一种是全量复制,另一种是增量复制。

2.3.1 全量复制

如下图所示,表示 Redis 主从全量复制的整体时序图,全量复制一般发生在 Slave 节点初始化阶段,这个时候需要把 master 上所有数据都复制一份,具体步骤是:

  • 从服务器连接主服务器,发送 SYNC 命令;
  • 主服务器接收到 SYNC 命名后,开始执行 BGSAVE 命令生成 RDB 文件并使用缓冲区记录此后执行的所有写命令;
  • 主服务器 BGSAVE 执行完后,向所有从服务器发送快照文件,并在发送期间继续记录被执行的写命令(表示 RDB 异步生成快照期间的数据变更);
  • 从服务器收到快照文件后丢弃所有旧数据,载入收到的快照;
  • 主服务器快照发送完毕后开始向从服务器发送缓冲区中的写命令;
  • 从服务器完成对快照的载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令;

问题:生成 RDB 期间,master 接收到的命令怎么处理?

开始生成 RDB 文件时,master 会把所有新的写命令缓存在内存中。在 slave node 保存了 RDB 之后,再将新的写命令复制给 slave node。(跟 AOF 重写期间的思路是一样的)

完成上面几个步骤后就完成了 slave 服务器数据初始化的所有 *** 作,savle 服务器此时可以接收来自用户的读请求,同时,主从节点进入到命令传播阶段,在这个阶段主节点将自己执行的写命令发送给从节点,从节点接收命令并执行,从而保证主从节点数据的一致性。

在命令传播阶段,除了发送写命令,主从节点还维持着心跳机制:PING 和 REPLCONF ACK,下面演示一下具体的实现。

  • 在 slave 服务器 redis cli 上执行 REPLCONF listening-port 6379 (向主数据库发送 replconf 命令说明自己的端口号)

  • 开始同步,向 master 服务器发送 sync 命令开始同步,此时 master 会发送快照文件和缓存的命令。

127.0.0.1:6379> sync
Entering replica output mode...  (press Ctrl-C to quit)
SYNC with master, discarding 202 bytes of bulk transfer...
SYNC done. Logging commands from master.
"ping"
"ping"
  • slave 会将收到的内容写入到硬盘上的临时文件,当写入完成后会用该临时文件替换原有的 RDB 快照文件。需要注意的是,在同步的过程中 slave 并不会阻塞,仍然可以处理客户端的命令。默认情况下 slave 会用同步前的数据对命令进行响应,如果我们希望读取的数据不能出现脏数据,那么可以在 redis.conf 文件中配置下面的参数,来使得 slave 在同步完成对所有命令之前,都回复错误:SYNC with master in progress

    slave-serve-stale-data no
    
  • 复制阶段结束后,master 执行的任何非查询语句都会异步发送给 slave。 可以在 master 节点执行 set 命令,可以在 slave 节点看到如下同步的指令。

    redis > sync
    "set","11","11"
    "ping"
    

另外需要注意的是:

master/slave 复制策略是采用乐观复制,也就是说可以容忍在一定时间内 master/slave 数据的内容是不同的,但是两者的数据会最终同步成功。

具体来说,redis 的主从同步过程本身是异步的,意味着 master 执行完客户端请求的命令后会立即返回结果给客户端,然后异步的方式把命令同步给 slave。这一特征保证启用 master/slave 后 master 的性能不会受到影响。

但是另一方面,如果在这个数据不一致的窗口期间,master/slave 因为网络问题断开连接,而这个时候,master 是无法得知某个命令最终同步给了多少个 slave 数据库。不过 redis 提供了一个配置项来限制只有数据至少同步给多少个 slave 的时候,master 才是可写的:

min-replicas-to-write 3     #表示只有当3个或以上的slave连接到master,master才是可写的

min-replicas-max-lag 10     #表示允许slave最长失去连接的时间,如果10秒还没收到slave的响应,则master认为该slave以断开

修改 master redis 服务的 redis.conf, 打开这两个配置,重启即可看到效果。

2.3.2 增量复制

从 Redis2.8 开始,主从节点支持增量复制,并且是支持断点续传的增量复制,也就是说如果出现复制异常或者网络连接断开导致复制中断的情况,在系统恢复之后仍然可以按照上次复制的地方继续同步,而不是全量复制。

它的具体原理是:主节点和从节点分别维护一个复制偏移量(offset),代表的是主节点向从节点传递的字节数;主节点每次向从节点传播 N 个字节数据时,主节点的 offset 增加 N;从节点每次收到主节点传来的 N 个字节数据时,从节点的 offset 增加 N。主从节点的偏移量可以分别保存在:master_repl_offset 和 slave_repl_offset 这两个字段中,通过下面的命令可以查看。

127.0.0.1:6379> info replication
# Replication
role:slave
master_host:192.168.221.128
master_port:6379
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_repl_offset:77864
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:acb74093b4c9d6fb527d3c713a44820ff0564508
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:77864
second_repl_offset:-1
repl_backlog_active:1   # 开启复制缓冲区
repl_backlog_size:1048576  # 缓冲区最大长度
repl_backlog_first_byte_offset:771  # 起始偏移量,计算当前缓存区可用范围
repl_backlog_histlen:77094  # 以保存数据的有效长度
2.3.3 无磁盘复制

前面我们说过,Redis 复制的工作原理基于 RDB 方式的持久化实现的,也就是 master 在后台保存 RDB 快照,slave 接收到 rdb 文件并载入,但是这种方式会存在一些问题。

  • 当 master 禁用 RDB 时,如果执行了复制初始化 *** 作,Redis 依然会生成 RDB 快照,当 master 下次启动时执行该 RDB 文件的恢复,但是因为复制发生的时间点不确定,所以恢复的数据可能是任何时间点的。就会造成数据出现问题。

  • 当硬盘性能比较慢的情况下(网络硬盘),那初始化复制过程会对性能产生影响

因此 2.8.18 以后的版本,Redis 引入了无硬盘复制选项,可以不需要通过 RDB 文件去同步,直接发送数据,通过以下配置来开启该功能:

repl-diskless-sync yes

master 在内存中直接创建 rdb,然后发送给 slave,不会在自己本地落地磁盘了

2.3.4 主从复制注意事项

主从模式解决了数据备份和性能(通过读写分离)的问题,但是还是存在一些不足:

1、第一次建立复制的时候一定是全量复制,所以如果主节点数据量较大,那么复制延迟就比较长,此时应该尽量避开流量的高峰期,避免造成阻塞;如果有多个从节点需要建立对主节点的复制,可以考虑将几个从节点错开,避免主节点带宽占用过大。此外,如果从节点过多,也可以调整主从复制的拓扑结构,由一主多从结构变为树状结构。

2、在一主一从或者一主多从的情况下,如果主服务器挂了,对外提供的服务就不可用了,单点问题没有得到解决。如果每次都是手动把之前的从服务器切换成主服务器,这个比较费时费力,还会造成一定时间的服务不可用。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5612057.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-15
下一篇 2022-12-15

发表评论

登录后才能评论

评论列表(0条)

保存