Redis集群-主从架构

1.为什么需要集群?

互联网思维一向讲究的是三高,即高并发,高可用,高性能。高并发:系统能够同时并行处理的请求,主要度量指标有响应延时,吞吐量,每秒查询处理,每秒事务处理,并发用户等;高可用:当系统某些节点故障时,系统依然可以对外提供服务,正常处理请求;高性能:程序的处理速度快,资源消耗最低(CPU、内存占用率低)的情况下利用率也要足够高【比如:当线程因为IO阻塞时,CPU空闲】。通常情况下集群可以对这三高起到积极的作用,如:通过增加节点数量,系统整体能并行处理的请求数变多(高并发);当某个节点故障时,其他节点依然可以将故障节点的流量进行处理(高可用);如果单个节点的系统吞吐量已经到达瓶颈了。增加节点的数量,等量的请求到达系统时,每个节点分得的流量变少了,处理的时间就会缩短,在外部看来,自然就更快了(高性能)。

2.主从架构可以解决什么问题?

主从架构师集群的一种模式,它侧重于解决系统的高可用问题,即当主节点故障时,可以快速通过从节点对外进行恢复。比如:Kafka中分区的副本;MySQL的主从;Redis的主从等等。

3.Redis如何实现主从?

一般来说实现主从最重要的就是主从之间的数据一致性问题该如何解决,而且必须控制数据一致性的延时在一定的范围之内,延时越小宕机恢复后数据丢失就越小。Redis使用了全量和增量复制的机制来让从节点的数据能尽量快的与主节点保护一致。

全量复制:Redis的全量复制其实就是通过将主节点的RDB快照将全量数据发送给从节点,从而让从节点可以最快的与主节点中的内存数据一致。
生成RDB快照的时候,主节点的主线程仍然是可以继续接受客户端的请求执行命令,这一部分也叫作增量数据,而这些增量数据如果不能及时的同步给从节点,就会造成数据不一致的问题。
增量复制:Redis的增量复制其实是通过复制积压缓冲区实现的。当从节点加载完RDB快照时,就会不停的向主节点发送数据偏移量,主节点就会从复制积压缓冲区中的增量数据发送给从节点,从而达到增量数据的同步。

复制积压缓冲区的底层数据结构是一个环形队列,它的作用是保存Redis主节点最近执行的所有写命令,方便从节点增量同步。复制积压缓冲区的大小可以通过配置repl_backlog_size进行设置,默认1M,生产环境最好是将它改成跟自己业务体量相匹配的大小。

复制积压缓冲区的工作原理:Redis的开启主从模式后,内存里会有一个自增的偏移量对应每一条写命令,每一条写命令都会写到aof-buffer(AOF日志)和repl_backlog_buffer(积压缓冲区)。当从节点向主节点发起同步请求时会携带自己最大的偏移量,主节点收到该同步请求后,就会先向复制积压缓冲区里边判断该偏移量是否还存在。如果不在了,主节点就会向从节点执行全量复制,即执行一个RDB快照并发送给从节点;如果还在就会将执行增量复制,即将该偏移量之后的命令发送给从节点。

什么情况下会导致,从节点最大偏移量的数据不在复制积压缓冲区呢?最根本的原因就是因为主节点的接受到的写命令太多,直接将复制积压缓冲区的旧数据给覆盖了,而导致这种现象的原因就比较多了。如:1.复制积压缓冲区设置过小;2.从节点执行数据同步慢;3.网络原因。当复制积压缓冲区被写满,主节点只能执行RDB快照并发送给从节点进行同步,而生成RDB之后,需要经过内核拷贝到客户端缓冲区经过网络IO,最终从节点经过网络IO又发生一次内核拷贝才能进行数据的恢复,成本很高,消耗的时间也比较大。在这区间如果从节点还没执行完成这次的全量复制,而主节点的复制积压缓冲区又再次被覆写了上一次的数据偏移量,这就意味着从节点又需要开始进行全量复制了,这种从节点不停的向主节点进行全量复制的现象就是复制风暴。

客户端缓冲区是一个统称,连接到主节点普通客户端也会有自己的一个缓冲区一般称之为client buffer。对于主节点来说,从节点也是一个客户端也有自己的缓冲区,而每一个从节点的缓冲区叫做replication buffer。客户端缓冲区是Redis节点与所有客户端进行数据交互的一个内存区域,如果某个客户端缓冲区过大的时候,Redis会主动与该客户端断开连接回收内存。

主节点进行全量复制的流程是:1.生产RDB快照并写到文件;2.将RDB快照读取到从客户端缓冲区;3.发送RDB文件。可以看到在主节点生成RDB快照的时候如果可以直接写到从客户端的缓冲区,就可以减少文件的IO,并且可以降低内核的调用与数据拷贝,从而提升性能。这个优化其实就是无盘复制,即生成的RDB文件不写入到磁盘,全程在内存里,所以叫无盘复制。因为RDB文件一般都较大,并且一直在内存中,所以比较适合网络畅通,从节点性能较好的场景,否则会占用主节点的内存,引发其他问题。

1.主从服务建立socket连接
2.从服务器发送ping命令
3.主服务器响应pong命令,验证从服务器密码
4.从服务器保存主服务器信息(runid、masterip、masterport、…)
从服务器发送psync命令(psync ${master-runid} ${offset})
主服务器执行bgsave,并记录写命令到积压缓冲区,向从服务器发送RDB快照
从服务器加载RDB快照,完成数据同步,修改offset
从服务器再次发起psync ${master-runid} ${offset}命令
主服务器查看psync中的master-runid以及offset,发送写命令
从服务器执行写命令

4.主从节点必须要注意的问题

部分参数配置可以不同(如:AOF),但是与内存相关的参数(maxmemory ,hash-max-ziplist-entries)必须要一致,否则当从节点的数据量超过已分配的内存时,会触发maxmemory-policy 策略进行内存溢出的控制。此时,从节点的数据必然会回收一部分(否则必然发生OOM),而主从复制流程依然正常进行,复制偏移量依然不变,这就会导致主从数据不一致。

主从节点一般部署在不同机器上,复制时必然存在网络延迟。Redis提供了repl-disable-tcp-nodelay参数用于控制是否关闭TCP_NODELAY[默认关闭]。当该参数开启时,主节点会合并较小的TCP数据包从而节省带宽。 默认发送时间间隔取决于Linux的内核,一般默认为40毫秒。 这种配置节省了带宽但增大主从之间的延迟。当关闭时,主服务器会将所有命令数据及时地发送给从服务器,降低延迟,但是会增加网络带宽的消耗。注意tcp_backlog参数的理解。

5.Redis主从能否实现读写分离?

对于读占比较高的场景,确实可以通过把一部分读流量分摊到从节点来减轻主主节点的压力,同时所有写操作必须在主节点中执行。假设Redis现在的从节点可以执行读命令,那么使用了读写分离会有以下几个问题。
1.数据延迟问题:主从之间的数据必定是存在延迟的,如果现在主节点写入一个数据,客户端立马去从节点读取该数据,此时因为主节点的数据尚未同步到从节点,所以客户端认为该数据不存在,对于这种情况,业务端需要自己做出决策,究竟是读从节点读不到时,就去读主节点还是其他方案。此时如果选择去读取主节点,那么主节点仍然是承担了一部分读请求。
2.数据过期问题:主节点负责所有数据的写操作,当一个数据过期的时候,从节点并不会对该数据执行任何操作,从节点的数据全部来自于主节点。所以从节点是无法判断一个数据有没有过期的,所以这就需要业务侧对这种情况进行考虑。
3.客户端路由问题:当从节点宕机的时候,就需要业务端有自己的判断机制,是转向主库还是有其他的多个从节点作为备选方案。
事实上,Redis的从节点默认情况下是不会接受任何读写数据的请求的,从节点的目标只有一个就是作为主节点数据的副本,以提供主节点宕机后的快速恢复。换句话说Redis现在的主从架构默认情况下是不支持读写分离的。
再回到读写分离的本质上,为什么需要进行读写分离?无非就是分担主节点的压力,所以如果能够将主节点的压力降低到足够承受的地步,那么久自然不需要所谓的读写分离了。而主节点的压力绝大部分都是来自于主线程的阻塞,所以归根究底就是要把Redis的阻塞扼杀掉。Redis的性能瓶颈常见项。所以总的来说,Redis的主从模式是可以实现读写分离的,但是需要自己修改相关配置,因为Redis的默认机制是所有命令必须由主节点接受并执行,从节点只负责从主节点中拷贝数据,作为一个纯粹的副本。另外,实现读写分离的性价比不高,实际上是可以通过避免使用可能会导致主线程阻塞的相关命令来达到更高的吞吐量。
如果需要对redis中的集合元素进行聚合统计,而且这部分数据要求不是非常准确或是允许一定的延时,那么使用从库来进行是比较合适的。因为集合元素存在大量子元素时进行统计,会阻塞主线程,而在从库中进行就可以避免主线的阻塞了,充分利用从库的资源。但实际上这种方案仍然是可以被HyperLogLog替换。

6.Redis主节点宕机了,能否进行自动恢复?

主节点宕机,这时候其实是可以将从节点重新作为主节点对外提供服务,这个时候Redis就实现了高可用。我们想要将从节点快速作为主节点的人工处理主要有以下几步:
1.首先要判断,主节点是不是真的不可用,无法对外提供服务;
2.选择一个从节点,断开从节点的主从关系【此时从节点变更为主节点】;
3.将新的主节点信息发送给客户端【客户端获取到新主节点的时候重新发起连接,客户端想要获取到新主节点的方式有很多,比如:手动修改配置、事件监听机制、主动轮训】;
4.如果存在多个从节点的话,原来旧的从节点还需要手动的与新主节点建立主从关系,开始进行复制。
实际上,当主节发生了故障需要将从节点作为新主节点对外提供服务这个过程也称之为故障转移。对于主节点是否发生了故障是可以通过监控来去及时的发现并告警,然后开始处理。但是在处理过程中,其实步骤是比较固定的,无非就是选择一个从节点,然后断开主从关系,之后通知客户端主节点信息变更,最后将其他从节点重新与新主节点建立主从关系。如果每次都需要人工去处理的话,新手可能会敲错一些命令,然后导致故障恢复时间变长。对于一些稍微比较有经验的工程师来说就会想相关命令写成一个脚本,需要恢复的时候只需要执行一些就可以完成了。一开始其实有很多开源的脚本已经将这个功能实现了,只是没有集成到Redis中,后来Redis就自己在内部实现了这个故障转移的机制,这个机制就是Redis哨兵模式,就是为了解决主从模式下的高可用。详细请看Redis集群模式-哨兵模式。

参考资料

1.极客时间专栏课-redis核心技术与实战
2.<
4.<

Original: https://www.cnblogs.com/zhenjungan/p/16504092.html
Author: zhenjungan
Title: Redis集群-主从架构

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/581876/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 每天一个 HTTP 状态码 201

    201 Created 表示请求成功,在服务器端创建了一个新资源… 201 Created 201 Created 表示客户端的请求已经成功完成,结果是创建了一个新资源…

    Linux 2023年6月7日
    0127
  • Linux防火墙——iptables简介

    一、防火墙相关概念 这里描述了一些相关的概念。 [En] Some related concepts are described here. 从逻辑上讲,防火墙可以分为主机防火墙和…

    Linux 2023年5月27日
    0104
  • 实现邮箱发送验证码功能

    实现注册和忘记密码界面的邮箱发送验证码功能 邮箱验证步骤 本文使用了redis数据库做验证码的缓存,不想用redis数据库也可以直接将验证码放入mysql中,设置验证码有效期即可。…

    Linux 2023年6月7日
    0136
  • Redis 集群

    三高架构:并发,性能,可用 主从复制 主从复制:将 master 中的数据即时、有效的复制到 slave 中 特征:一个 master 可以拥有多个 slave,一个 slave …

    Linux 2023年5月28日
    0108
  • __pycache__

    最近在使用python写一个串口模块的时候,偶然发现运行脚本之后,在工程文件夹下面出现了这样一个文件夹__pycache__,所以就特意到网上查了一下这个文件夹是怎么回事。 &am…

    Linux 2023年6月14日
    0114
  • 001.IT运维面试问题-Linux基础

    Redhat、CentOS、Fedora、SuSE、Debian、Ubuntu、FreeBSD等。 ⑴开机BIOS自检,加载硬盘。 ⑵读取MBR,MBR引导。 ⑶grub引导菜单(…

    Linux 2023年6月13日
    0103
  • 通过示例学习PYTORCH

    核心是:PyTorch提供了两个主要的特性: 一个n维的Tensor,与Numpy相似但可以在GPU上运行 构建和训练神经网络的自动微分 我们将使用一个三阶多项式拟合 (y=sin…

    Linux 2023年6月14日
    0111
  • 从零开始制作一个linux iso镜像

    一、前言 对于一个极简化的linux系统而言,只需要三个部分就能组成,它们分别是一个linux内核、一个根文件系统和引导。以下是本文制作linux iso镜像所用到的系统和软件: …

    Linux 2023年5月27日
    091
  • Pycharm设置python文件头

    设置路径为: File->Setting->Editor->File and code Templates->Python Script 可用的预定义文件模…

    Linux 2023年6月8日
    0111
  • centos 8及以上安装mysql 8.0

    本文适用于centos 8及以上安装mysql 8.0,整体耗时20分钟内,不需要FQ 1.环境先搞好 systemctl stop firewalld //关闭防火墙 syste…

    Linux 2023年6月7日
    0109
  • QLabel图片自适应

    故事背景:由于要做终端定制的需求,在服务端上传一张128像素的图片,下发给客户端,适配所有图标(界面左上角、任务栏、快捷方式、托盘等),但是由于每个位置的图标大小不一样,代码要根据…

    Linux 2023年6月13日
    088
  • windows 使用挂载盘提供FTP服务

    环境说明: NFS服务器:centos7.0 IP:192.168.18.10 FTP服务器:windows server 2008 IP:192.168.18.41 准备工作: …

    Linux 2023年6月8日
    0169
  • CentOS 7安装jdk-mysql-nginx

    安装jdk 设置开机自启 重启systemctl Original: https://www.cnblogs.com/nianxue/p/16618805.htmlAuthor: …

    Linux 2023年6月6日
    075
  • Python3.9.5安装

    基础环境:yum install openssl-devel bzip2-devel expat-devel gdbm-devel readline-devel sqlite-de…

    Linux 2023年6月6日
    097
  • 每天一个 HTTP 状态码 103

    103 Earyly Hints 是被用于在最终的 HTTP 消息前返回一些响应头… 103 Early Hints 103 Earyly Hints 是被用于在最终 …

    Linux 2023年6月7日
    0112
  • 高通MSM8998 ABL的调试

    高通在MSM8998上引入了UEFI,用来代替LK(Little Kernel)。高通UEFI由XBL和ABL两部分组成。XBL负责芯片驱动及充电等核心应用功能。ABL包括芯片无关…

    Linux 2023年6月7日
    085
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球