当前位置: 首页 > news >正文

Redis原理—4.核心原理摘要

大纲(9870字)

1.Redis服务器的Socket网络连接建立

2.Redis多路复用监听与文件事件模型

3.基于队列串行化的文件事件处理机制

4.完整的Redis Server网络通信流程

5.Redis串行化单线程模型为什么能高并发

6.Redis内核级请求处理流程与原理

7.Redis通信协议与内核级请求数据结构

8.Redis Server的初始化与持久化

9.Redis分布式集群

10.Redis集群模式的数据结构分析

11.Redis节点之间的三次握手原理分析

12.基于slots槽位机制的数据分片原理分析

13.Redis集群slots分配与内核数据结构

14.基于slots槽位的命令执行流程分析

15.基于跳跃表的slots和key关联关系

16.集群扩容时的slots转移过程与ASK分析

17.Redis主从架构原理

18.Redis老版本的sync主从复制原理以及缺陷

19.Redis新版本psync的偏移量和复制积压缓冲区

20.Redis集群的故障探测

1.Redis服务器的Socket网络连接建立

Redis是一种基于文件事件的网络通信模型,它会将网络事件抽象为文件事件File Event。也就是说,在Redis Server的内部,各种网络通信事件其实都是一些文件事件。

图片

2.Redis多路复用监听与文件事件模型

(1)阻塞IO模型(BIO)

(2)非阻塞IO模型

(3)IO复用模型(NIO)(两次调用两次返回)

(4)文件事件模型

(1)阻塞IO模型(BIO)

应用程序调用IO函数时,如果数据没有准备好,那么只能一直等待。如果数据准备好了,则数据会从内核空间拷贝到用户空间,然后IO函数返回成功指示。

阻塞IO(BIO)的优点:程序简单,在阻塞等待数据期间,用户线程挂起,用户线程不会占用CPU资源。

阻塞IO(BIO)的缺点:为每个连接配套一条独立的线程,或者一条线程维护一个连接成功的IO流的读写。在并发量小的情况下,使用BIO模型没什么问题。但在高并发场景下,则需要大量线程来维护大量网络连接。此时内存、线程切换开销会非常巨大,因此BIO模型在高并发场景下不可用。

图片

(2)非阻塞IO模型

把一个Socket接口设置为非阻塞就是告诉内核:当请求的IO操作无法完成时,不要让进程睡眠,而是返回一个错误。这样IO操作函数将不断测试数据是否已经准备好。如果没有准备好,则继续测试,直到数据准备好为止。在这个不断测试的过程中,会大量占用CPU的时间,所以该模型不被推荐。

非阻塞IO的特点:应用程序线程需不断进行IO系统调用,轮询数据是否已准备好。如果没准备好,则继续轮询,直到完成系统调用为止。

非阻塞IO的优点:每次发起IO系统调用,在内核等待数据过程中可以立即返回,用户线程不会被阻塞,实时性比较好。

非阻塞IO的缺点:需要不断重复发起IO系统调用。这种不断轮询,将不断地询问内核,将占用大量的CPU时间,系统资源利用率较低。

图片

(3)IO复用模型(NIO)(两次调用两次返回)

IO多路复用模型,就是内核后来发展了,产生了一种新的系统调用select/epoll。通过select/epoll系统调用,一个线程可以监视多个文件描述符。一旦某个描述符就绪(一般是内核缓冲区可读/可写),内核能够通知程序进行相应的IO系统调用。非阻塞的BIO就是一个线程只能轮询自己的一个文件描述符。

IO多路复用模型的基本原理就是select/epoll系统调用。单个线程不断轮询select/epoll系统调用所负责的成百上千的Socket连接。当某个或者某些socket网络连接有数据到达了,就返回这些可以读写的连接。好处就是通过一次select/epoll调用,就能查询到可以读写的成百上千个网络连接。

select版的多路复用:

图片

epoll版的多路复用:

图片

在这种模式中,首先进行的不是read系统调动,而是select/epoll系统调用。这里有一个前提,需要将目标网络连接,提前注册到select/epoll的可查询Socket列表中,然后才能开启整个IO多路复用模型的读流程。

多路复用的流程如下:

步骤一:进行select/epoll系统调用,查询可读的连接,内核会查询select/epoll系统调用的可查询Socket列表。当任何一个Socket中的数据准备好了,select/epoll系统调用就会返回。当用户线程调用了select/epoll系统调用,则整个线程会被阻塞。

步骤二:用户线程获得了目标连接后会发起read系统调用,阻塞用户线程。内核开始复制数据,将数据从内核缓冲区拷贝到用户缓冲区,并返回结果。

步骤三:用户线程才解除block状态,用户线程终于真正读取到数据,继续执行。

多路复用IO(NIO)的特点:

IO多路复用模型,建立在操作系统内核能够提供系统调用select/epoll的基础上。多路复用IO需要用到两个系统调用:一个是select/epoll的查询调用,一个是read的读取调用。负责select/epoll查询调用的线程,需要不断进行select/epoll轮询,找出可进行IO读取的Socket。另外,多路复用IO模型与前面的非阻塞IO模型是有关系的。对于每一个可以查询的Socket,一般都设置成为非阻塞模型。只是这一点,对于用户程序是透明的(不感知)。

多路复用IO(NIO)的优点:

使用select/epoll的优势在于,它可以同时处理成千上万个连接。与一条线程维护一个连接相比,IO多路复用技术的最大优势是:系统不必创建线程,也不必维护这些线程,从而大大减小了系统的开销。Java的NIO技术,使用的就是IO多路复用模型,在Linux系统上使用了epoll系统调用。

多路复用IO(NIO)的缺点:

本质上,select/epoll系统调用,属于同步IO,也是阻塞IO。都需要在读写事件就绪后,自己负责进行读写,也就是说这个读写过程是阻塞的。

Redis使用多路复用监听Socket:

针对大量的Socket,不太可能每个Socket都用一个线程来监听网络请求和发送响应。面对并发的成千上万个Socket,不可能准备成千上万个线程来处理。所以Redis通过多路复用,实现了一个线程监听多个Socket,这就是IO多路复用模式。

(4)文件事件模型

当有大量的客户端来并发访问Redis时,Redis Server端就会有大量的Socket,这些Socket里可能会产生一些网络事件:

一.Accept(连接应答事件)

二.Read(有数据可以读取的事件)

三.Write(有数据可以写出的事件)

四.Close(连接被关闭)

这些网络事件都会被抽象成文件事件File Event,即Redis里的网络事件(Accept、Read、Write、Close)都会抽象为文件事件。

图片

3.基于队列串行化的文件事件处理机制

当同一时间有大量的Redis Client发送请求,那么短时间里就会有大量的请求到达Redis Server。然后Redis Server内部的大量Socket就会短时间内产生大量事件,比如Accept事件、Read事件等。此时有两种处理方案:

方案一:把这产生事件的Socket一个个放入Queue里进行串行化排队,不管同一时间有多少请求过来,要返回多少响应,都让所有产生事件的Socket进入队列里排队,串行化等待处理。

方案二:把产生事件的Socket分发给不同的线程来进行并发处理,通过开启大量的线程,让多个线程并发去处理不同Socket产生的事件。

Redis选择的是方案一:

图片

4.完整的Redis Server网络通信流程

步骤一:在Redis服务器初始化时,Redis会将连接应答处理器和服务器监听套接字的AE_READABLE事件关联起来。接着如果一个客户端跟Redis发起连接请求,那么服务器监听套接字就会产生AE_READABLE事件,然后触发连接应答处理器来处理客户端的连接请求,接着创建客户端套接字,并将这个新创建的客户端套接字的AE_READABLE事件与命令请求处理器关联起来。

步骤二:当客户端向Redis发起命令请求时,不管是读请求还是写请求都一样。首先会在客户端套接字产生一个AE_READABLE事件,然后由命令请求处理器来处理。命令请求处理器就会从客户端套接字中读取请求相关数据,传给相关程序去执行。

步骤三:多个Socket可能会并发产生不同的操作,每个操作对应不同的文件事件。但IO多路复用程序会监听多个Socket,会将Socket放入一个队列中排列。每次从队列中取出一个Socket给文件事件分派器,然后文件事件分派器会把Socket分给对应的事件处理器进行处理。

步骤四:接着Redis准备好给客户端的响应数据后,Redis会将客户端套接字的AE_WRITABLE事件与命令响应处理器关联起来。

步骤五:当客户端准备好读取响应数据时,会在客户端套接字上产生一个AE_WRITABLE事件。触发命令响应处理器来处理,将准备好的响应数据写入客户端套接字,供客户端来读取。

步骤六:命令响应处理器写完后,就会删除这个客户端套接字的AE_WRITABLE事件和命令响应处理器的关联关系。

图片

5.Redis串行化单线程模型为什么能高并发

(1)大量Redis Client短时间发起连接请求

(2)与大量Redis Client短时间建立连接

(3)建立连接后短时间内发起大量命令请求

(4)为什么通过队列 + 单线程进行串行化处理

(5)Redis可以抗下高并发靠的是什么

(6)Redis单线程模型的高并发总结

Redis可以抗高并发,它的并发能力很强。普通机器单机就可以轻松抗每秒几千并发,高配机器可以抗几万并发。接下来结合Redis Server端的网络通信模型来分析一下:为什么Redis能抗高并发。

(1)大量Redis Client短时间发起连接请求

大量Redis Client在短时间对单个Redis Server发起请求时会出现什么?

首先会出现大量的Redis Client同时要和Redis Server建立网络连接,Redis Server负责连接的Socket在短时间内需要处理大量要建立连接的请求和事件。

(2)与大量Redis Client短时间建立连接

为什么短时间内Redis Server可以跟大量的Redis Client建立连接?

原因一:连接建立的性能开销是比较低的,短时间内完成大量的连接建立是没问题的。

原因二:要看和Redis Client建立的连接是短连接还是长连接。如果是短连接模式,那么频繁的建立和断开连接就耗性能,所以建立的都是长连接。虽然第一次建立连接需要花费一些时间,但是后续这个连接就不用重复建立和断开了,可以复用。所以,短时间内大量的客户端请求和Redis Server建立连接,是没有问题的。

(3)建立连接后短时间内发起大量命令请求

大量Redis Client和Redis Server建立连接后,会基于Socket在短时间内高并发地发送命令请求。于是Redis Server的各个Socket短时间内就会出现大量的网络事件,这些网络事件会全部通过队列 + 单线程来进行串行化处理。

(4)为什么通过队列 + 单线程进行串行化处理

针对内存里的共享数据结构,如果允许多线程并发访问,那么就会导致频繁的加锁和互斥。而且多线程对CPU负载消耗是很大的,如果CPU负载太高,多线程运转的效率也会急转直下。所以多线程访问一块共享内存数据结构,大量的加锁和互斥竞争,会导致性能不高。因此单线程可避免多线程切换对CPU负载消耗,避免对内存数据结构进行大量的加锁和互斥。

(5)Redis可以抗下高并发靠的是什么

Redis可以抗下高并发靠的是每个请求执行和处理的速度和效率。如果一个请求要耗费10ms才能处理完毕,此时每秒只能处理100个请求。如果一个请求只要1ms就可以处理完毕,那么每秒就能处理1000个请求。而当Redis的一个请求是基于纯内存来操作,而且避免了加锁和互斥,那么处理速度是很快的。

(6)Redis单线程模型的高并发总结

首先,依靠IO多路复用可以同时监听大量连接请求,大量请求过来后先进行串行化排队。然后,由于基于纯内存来操作数据 + 单线程没有线程切换及数据竞争,所以大量请求都能很快地处理掉。

6.Redis内核级请求处理流程与原理

Redis Server会为每个建立好连接的客户端,创建一个RedicsClient内存数据结构。RedicsClient之间会以链表的方式进行组织,RedicsClient中包含关键的两部分是:输入缓冲区 + 输出缓冲区。

Redis Server为客户端建立好连接后,当客户端发送请求命令给Redis Server时,Redis Server的命令请求处理器就会往RedisClient数据结构的输入缓冲区中写入请求命令。

Redis Server中会有一个命令查找表,由一系列的RedisCommand组成。根据RedisClient的输入缓冲区的请求命令 + 命令查找表,可以找到对应的RedisCommand。根据具体的RedisCommand,就可以操作Redis Server中的内存数据结构,如字符串、哈希等。根据RedisCommand命令操作完Redis Server中的内存数据结构后,就会将操作结果放入RedisClient的输出缓冲区。

后续客户端想要获取请求响应时:Redis Server就可以找到该客户端对应的RedisClient数据结构,然后就可以从RedisClient的输出缓冲区找到命令请求的操作结果,进行返回。

图片

7.Redis通信协议与内核级请求数据结构

Redis Client和Redis Server端之间的数据需要按照约定的格式来进行组织。比如客户端请求:set key value -> jedis.set(key, value),会通过某种协议组织成某种数据。

在网络通信的过程中,代码里的对象和数据结构,往往需要进行按照协议进讲行封装和组织。按照协议进行组织之后,会得到一些协议数据,比如:

*3\rn$3\rnSETr\n$3r\nkeyr\n$5Vr\nvalue\r\n

按照协议组织的请求数据,还必须进行序列化。

请求数据从Client端发送到Server端的过程中:首先会按照协议组织成协议数据,然后协议数据会被序列化成字节数据流,即byte[]字节数组,接着字节数据流会被Socket通过网络传输到Server端。Server端通过Socket读取出来的首先是字节流,然后把字节流进行反序列化拿到一个协议数据,接着协议数据才会按照协议还原回请求数据,最后请求数据会被放入到RedisClient的输入缓冲区里。

请求数据 -> 协议数据 -> 序列化字节流数据 -> Socket网络传输 -> 反序列化字节流数据 -> 协议数据 -> 请求数据

RedicsClient之间会以链表的方式进行组织。

RedicsClient中会有一个querybuf字段表示输入缓冲区,还原出来的请求数据会放入querybuf中。

RedicsClient中会有一个buf字段表示输出缓冲区,调用命令函数的执行结果就会写入buf中。

RedicsClient中会有一个arg字段存放命令字符串。

RedicsClient中会有一个cmd字段指向在命令查找表找到的RedisCommand。

8.Redis Server的初始化与持久化

(1)Redis启动时初始化的主要工作

(2)Redis的定位

(3)Redis的持久化

(1)Redis启动时初始化的主要工作

初始化命令查找表、RedisCommand、IO多路复用程序、套接字Queue、事件处理器等,读取并加载redis.conf里的配置到内存。

(2)Redis的定位

Redis是基于内存进行NoSQL数据存储,可以认为它是一个分布式缓存系统。因为Redis是基于内存的,所以才可以用来进行缓存。

由于基于内存必然会面临一个问题:如果Redis进程重启,那么内存里的数据就全部丢失了。所以一般也会给Redis开启数据持久化:用AOF来进行数据持久化,用RDB去进行周期性的冷备份。

(3)Redis的持久化

AOF就是每次对内存里的数据进行更新后,都会有对应的记录写入到内存中,可以设定AOF记录刷新到磁盘的策略。

一.比如每条数据写入内存后就把它的AOF记录刷到磁盘,确保每条数据都不会丢失,但这样会导致Redis的性能退化到基于磁盘的数据存储级别。

二.当然也可以设定每秒把内存里的AOF记录刷到磁盘文件里。如果突然对Redis Server进程进行重启,可能会丢失1秒内写入到内存的数据所对应的AOF记录。但只要Redis Server重启后,就会把磁盘文件里之前的AOF记录都读取出来,还原内存数据。

RDB就是周期性把内存的数据写一份快照放到磁盘文件里去。RDB比较适合做数据冷备份,它会将数据备份成一个文件,可以将RDB文件放到其他服务器上。如果服务器磁盘坏了导致AOF没了,此时就可以基于1个小时前的RDB去进行数据恢复。

9.Redis分布式集群

图片

10.Redis集群模式的数据结构分析

在Redis集群模式下,每个节点都会给其他的节点创建对应的内存数据结构,来保存该节点信息。

每个Redis Server都会有一个ClusterState内存数据结构,用来保存所有节点的信息。

ClusterState结构中会有一个myself字段,指向ClusterState它自己代表的ClusterNode节点。

ClusterState结构中会有一个state字段,表示整个Redis集群当前所处的状态。

ClusterState结构中会有一个nodes字段,表示一个包含了各个节点的ClusterNode结构的字典。

ClusterNode结构里会有一个name字段,代表着该Redis节点在集群中自动生成的名字。

ClusterNode结构里会有一个flags字段,代表着该Redis节点在集群中的角色是主还是从。

ClusterNode结构里会有一个ip字段,代表着该Redis节点的IP地址。

图片

11.Redis节点之间的三次握手原理分析

Redis集群里的节点在互相通信前,需要进行meet协议下的三次握手。meet协议下的三次握手,其实就是通过一系列命令让多个Redis节点组成一个集群。

具体来说就是会以一台Redis节点为基础,告诉它有另外一个Redis节点。首先Redis Server会给要连接的其他Redis节点,在自己内存里创建一个ClusterNode数据结构。然后发送一条meet消息到要连接的其他Redis节点上,该Redis节点收到一条meet消息后会也在内存里创建一个ClusterNode,并返回一条pong消息。当这个Redis Server收到pong消息后,又会发出一条ping消息给这个要连接的其他Redis节点。

meet -> pong -> ping

图片

meet三次握手协议是Redis自己的协议,与TCP网络连接的三次握手是不同的。TCP三次握手是用来建立基础的底层网络连接,属于网络层的协议。Redis三次握手属于应用层的协议,用于和集群里的各个节点建立相互连接。

Gossip协议的核心就是:发送meet、pong、ping消息时,会顺便随机选节点记录的2个节点信息一起发送出去。

三次握手 + Gossip协议传播 -> 集群建立

12.基于slots槽位机制的数据分片原理分析

假设需要往Redis集群里写入100G的数据,Redis集群里有5个节点,那么每个节点就需要在内存里存储20G的数据,这时就要面临两个问题。

问题一:往Redis集群写入数据时数据应该写入到哪个数据分片,也就是往Redis集群写入一条数据时,这条数据应该写入到集群的哪个节点里。

问题二:数据应该如何在Redis集群各个节点间进行迁移和Rebalance。

一.数据节点的扩容

Redis集群刚开始是5个节点,现在往集群里加入1个节点。那么由于刚刚加入集群的这个节点是空的,没有数据的。所以Rebalance就是把已有的5个节点上的数据,迁移到新的空节点上去。让已有的节点上的数据变少,让新的空节点上的数据变多,这是数据扩容要实现的效果。

二.数据节点的缩容

Redis集群目前是5个节点,为节约成本需要缩容为3个节点,那么减少的2个节点的数据也需要迁移到另外的3个节点上。

三.为解决数据扩容和缩容引入数据分片

Redis集群的每个节点会包含n个数据分片,在往Redis集群写入数据时,会通过路由算法把每条数据写入到某节点的某数据分片里,其中的路由算法可能是随机分配或者是轮询分配等。

当Redis集群需要进行扩容时:首先计算出已有的每个节点要迁移哪些数据分片给新节点,然后再对这些指定的数据分片进行迁移。

当Redis集群需要进行缩容时:只需要把减少的节点机器上的数据分片迁移给剩余的机器即可。

Redis集群的数据分片是通过slots槽位来实现的,Redis集群的数据分片数量是固定的,总共有16384个slots。

所以Redis集群启动后,需要给各个节点分配它们负责的slots槽位。每个节点会负责一部分的slots槽位,每个slot槽位就是一个数据分片。

13.Redis集群slots分配与内核数据结构

可以通过一些命令手动给节点分配槽位范围。比如指定给节点1分配的槽位范围是1-5000,指定给节点2分配的槽位范围是5001-10000等。当一个节点分配好槽位后,就会把自己负责的槽位信息同步给其他节点。

每个ClusterNode里会有一个slots字段,用于存放该ClusterNode对应节点被分配的槽位集合。

每个ClusterNode里会有一个numslots字段,用于存放该ClusterNode对应节点分配的槽位数量。

每个Redis节点里的ClusterState中也会有一个slots字段,是一个大小为16384的数组,数组中的每一个元素会通过指针指向一个ClusterNode,所以ClusterState.slots数组里存放了16384个槽位中每个槽位在哪个节点中。

图片

14.基于slots槽位的命令执行流程分析

(1)多个Redis节点如何一起组成一个Redis集群

(2)组成集群后各节点如何构建内存里的数据结构

(3)Redis集群的去中心化

(4)如何决定一个key应交给集群中哪个节点来处理

(1)多个Redis节点如何一起组成一个Redis集群

各个Redis节点互相之间进行三次握手,基于Gossip协议将连接到的节点扩散给其他节点,这样就可以让一群节点互相之间建立连接了。

(2)组成集群后各节点如何构建内存里的数据结构

首先会进行slots分配,即基于命令来分配各个节点的slots。然后每个节点会在内存里记录各个ClusterNode都有哪些slots。每个节点的ClusterState的slots数组16384个元素会指向各个ClusterNode。每个节点会把自己的slots同步给其他节点,从而实现集群里的槽位分配。

(3)Redis集群的去中心化

Redis集群架构有一个很关键的特征,就是去中心化。即Redis节点之间的关系是对等的,每个节点处理的事情都一样。这样就避免了需要去选举一个Leader来管控整个集群的情况。

(4)如何决定一个key应交给集群中哪个节点来处理

客户端想要对某个key进行请求操作时,由于不知道究竟找哪个节点去处理,所以会随机找一个节点来发送关于这个key的命令请求。

该随机节点接收到请求后,会在内部先计算一下这个key究竟属于哪个slot。如果发现该slot就在当前节点中就直接处理,否则就响应MOVED(slot + 目标地址)错误让客户端进行请求重定向。

计算key属于哪个slot的方法:通过CRC算法(key)得到一个值,然后和16383做位运算得到一个0到16383范围内的数字,这个数字就代表了这个key应该属于哪个slot了。

图片

15.基于跳跃表的slots和key关联关系

在集群模式下,所有数据都会被划分到16384个数据槽位里。16384个数据槽位就等于16384个数据分片,每个槽位里都有一部分数据。客户端发送命令后,等待Server端计算key所属的槽位,之后就可以把数据放在对应的槽位里。

每次操作完key-value数据后,会通过skipList跳跃表来对这个key与slot进行关联绑定。这个跳表中的每个节点的分值是槽号,成员是键。在跳表中,节点按各自所保存的分值从小到大排列。通过这个跳表就能快速获取某个slot的所有数据库键。

16.集群扩容时的slots转移过程与ASK分析

(1)集群扩容时的slots是如何进行转移的

(2)进行slots转移过程中可能会出现的ASK错误

(1)集群扩容时的slots是如何进行转移的

集群里加入一个新节点,可以通过命令把某节点上的一部分slots转移到该新节点中。进行slots转移需要依靠ClusterState里的两个数据结构:migration_slots_to和importing_slots_from。进行转移时,首先会根据跳表查出要转移的slots包含的所有key,然后再将这些key发送到新节点中进行存储。

(2)进行slots转移过程中可能会出现的ASK错误

ASK错误指的是:节点的槽位正在迁移,但却收到了一个key请求,此时该节点没能在自己的数据库里找到该key。于是该节点就会看一下
ClusterState.migration_slots_to,看看key所属的槽位是否发生迁移。如果是,则响应客户端ASK错误并引导客户端到正在导入槽位的节点去查找key。

17.Redis主从架构原理

在从节点的ClusterNode中,其slaveof字段会指向主节点的ClusterNode。

在主节点的ClusterNode中,其numslaves字段表示拥有多少个从节点。

在主节点的ClusterNode中,其slaves字段中会指向具体的从节点的ClusterNode。

图片

18.Redis老版本的sync主从复制原理以及缺陷

Redis 2.x以前的老版本里使用的sync主从复制有很多缺陷,只有了解老版本的sync主从复制原理,才能理解Redis主从复制原理的演进过程。

某节点通过slaveof操作成为主节点的从节点后,主节点会做如下事情。

步骤一:首先主节点会执行bgsave命令进行后台保存,生成数据快照文件——RDB文件

步骤二:然后主节点会将生成RDB文件的时间点之后的所有命令,写入复制缓冲区中

步骤三:接着主节点会将RDB文件传输给从节点,从节点收到RDB文件后会将数据加载到内存中

步骤四:之后主节点便会把复制缓冲区里的命令发送给从节点执行,这样主从节点的数据几乎一样了

步骤五:最后主节点通过命令传播机制,把主节点最新的命令操作也同步给从节点

图片

这种sync模式的问题是:每次从节点重启都要发送sync命令给主节点,让主节点按照上述步骤重新做一遍数据同步操作。由于每次从节点重启都要执行sync,而sync开销最大的地方是执行bgsave操作(特别耗时)。

bgsave是一个极为重量级且耗时的操作。如果Redis内存里有大量数据(如十个G),那么执行bgsave会产生大量磁盘IO,会非常耗时。主节点把这么大的RDB文件传输给从节点,会非常耗费网络资源和带宽,甚至可能被打满。从节点收到RDB文件后,几乎会阻塞对外服务,通过大量磁盘IO加载RDB文件到内存。

以上便是sync模式进行主从同步的缺陷。

19.Redis新版本psync的偏移量和复制积压缓冲区

(1)Redis老版本的主从复制只支持sync模式

(2)Redis新版本使用psync模式优化断线重连

(1)Redis老版本的主从复制只支持sync模式

每次从节点断线重连,主节点都要执行一遍bgsave生成RDB文件并传输数据快照给从节点。在很多情况下,从节点可能仅仅是做一些运维工作而需要进行重启。这时候从节点的断线重连时间间隔其实不长,所以没有必要每次断线重连都传输RDB快照。

(2)Redis新版本使用psync模式优化断线重连

如果断开的时间间隔还比较短,那就不需要传输RDB也不需要执行bgsave。其实只需要想办法把断线这段时间里做出的那些命令变更,传输给断线重连的节点,然后断线重连的节点再重新执行这些命令即可。

如果断开的时间间隔太长,比如几小时甚至几天。那么在这段时间里做出的数据变更太多,此时就只能通过bgsave生成RDB文件进行传输同步。

(3)psync模式的核心

psync主要是基于复制偏移量 + 复制积压缓冲区来实现优化的。

主从节点都会记录各自的复制偏移量。断线重连后主节点只需对比相互间的复制偏移量差距,然后决定是否执行bgsave生成RDB文件。

如果产生偏移量差距的命令都在复制积压缓冲区里,此时就可以把这些命令直接传输给从节点。从节点只需把这些命令执行一遍,就能让数据完成同步。

如果节点落后的数据太多,导致重启时主从节点间的数据偏移量差距太大,那么这些偏移量对应的命令在复制积压缓冲区里就找不到了,此时就只能进行全量同步。也就是把生成的RDB快照文件传输给从节点,来实现主从数据同步。

图片

20.Redis集群的故障探测

(1)Redis定时ping与疑似下线分析

(2)Redis故障报告与下线标记

(1)Redis定时ping与疑似下线分析

每个Redis节点都会定时发送ping消息给所有的其他节点。整个Redis集群里是没有Controller或者Leader角色的,每个节点都是对等的,并没有中心化的总控节点。通过各个节点互相间进行探测和通信来实现集群的功能。

每个Redis节点定时发送的ping消息会尝试探测其他节点是否还存活,如果其他节点是存活的就会返回pong消息。

如果两个从节点发送出去的ping消息,并没有在指定时间范围内收到pong消息。此时每个从节点就会把主节点的flags状态由master标记为pfail,也就是标记为疑似下线状态。

(2)Redis故障报告与下线标记

每个节点都会把疑似下线的信息发送给其他节点,从而实现相互间疑似下线信息的交换。每个节点在汇总针对某个节点的疑似下线报告fail_reports时,都会判断集群里是否过半节点都认为某个节点下线了,如果是则标记某个节点为正式下线状态fail,最后还要把某个节点被标记为正式下线状态的信息同步给其他节点。

flags状态变化:master/slave -> pfail -> fail。

对于Redis集群里的任何一个节点(无论是主节点还是从节点),都遵循如下的故障探测机制:

一.每个节点都定时发送ping消息给其他节点

二.如果一段时间没收到某节点的pong消息,就标记该节点状态为pfail

三.将pfail信息交换给其他所有节点

四.汇总fail_report,如果过半节点数量都认为pfail,则标记节点状态为fail,以及同步该节点的fail状态给其他所有节点,这时该节点便正式死亡

相关文章:

Redis原理—4.核心原理摘要

大纲(9870字) 1.Redis服务器的Socket网络连接建立 2.Redis多路复用监听与文件事件模型 3.基于队列串行化的文件事件处理机制 4.完整的Redis Server网络通信流程 5.Redis串行化单线程模型为什么能高并发 6.Redis内核级请求处理流程与原理 7.Redis通信协议与内核级请求数据…...

面向对象系统的分析和设计

来源:《设计模式精解-GOF23种设计模式解析》 作者:k_eckel k_eckels mindview - 博客园 (cnblogs.com) --------- 面向对象系统的分析和设计实际上追求的就是两点: (1)高内聚 (2)低耦合 …...

单片机:实现交通信号灯(附带源码)

使用单片机实现交通信号灯控制系统是一个经典的嵌入式系统应用。这个项目可以帮助你理解如何通过单片机控制不同颜色的LED灯、处理时间控制、以及输入输出的基本操作。通过这个项目,你将掌握如何设计交通信号灯的时序控制、如何实现定时控制交通灯的切换、以及如何与…...

小白如何学习看懂CAD图纸?

首先,你需要了解CAD图纸的基本构成,包括图例、尺寸标注、比例等等。接着,你可以通过一些专业的书籍、在线课程或视频教程来逐步学习如何识别和理解这些元素。但建议不要学的太复杂了。 掌握基本概念: 坐标系:了解CAD…...

HarmonyOS-高级(一)

文章目录 一次开发、多端部署自由流转 🏡作者主页:点击! 🤖HarmonyOS专栏:点击! ⏰️创作时间:2024年12月09日12点19分 一次开发、多端部署 布局能力 自适应布局 拉伸能力均分能力占比能力缩放…...

Datawhale AI 冬令营(第一期)定制你的第一个专属模型-学习笔记

最近我报名参加了Datawhale组织的主题为“动手学系列,人人都能应用的AI”的Datawhale AI冬令营(第一期)。 本次学习一共12天,从12月10日-12月21日,学习会包含【跑通速通手册】,【学习大模型微调&数据集…...

群控系统服务端开发模式-应用开发-登录退出发送邮件

一、登录成功发送邮件 在根目录下app文件夹下controller文件夹下common文件夹下&#xff0c;修改Login.php&#xff0c;代码如下 <?php /*** 登录退出操作* User: 龙哥三年风水* Date: 2024/10/29* Time: 15:53*/ namespace app\controller\common; use app\controller\Em…...

app-2 App 应用抓包之 Postern+Charles

一、前言 本篇是基于 Postern Charles 方式对安卓应用数据包进行抓取。可以抓取到市面上大多数的app数据包。 二、环境准备 postern&#xff1a;postern下载地址 charles&#xff1a;Charles 4.5.6 中文版(便携免安装).rar 提取码&#xff1a;6d8f 三、配置及抓包测试 3.…...

cnocr配置及训练测试

cnocr配置及训练测试 1&#xff0c;相关链接2&#xff0c;已有模型调用测试&#xff08;1&#xff09;下载相关模型&#xff08;2&#xff09;Cnstd文本检测模型&#xff08;3&#xff09;模型调用解析脚本 3&#xff0c;自定义数据集训练测试&#xff08;1&#xff09;标签转换…...

【优选算法 前缀和】前缀和算法模板详解:一维前缀 & 与二维前缀和

一维前缀和 题目解析 算法原理 解法一&#xff1a;暴力解法 简单模拟&#xff0c;读完题意有 q 次询问&#xff0c;给哪两个数&#xff0c;就求哪段区间的和并且返回&#xff0c;这样的做法&#xff0c;时间复杂度为O(N*q)&#xff0c;这个时间复杂度会超时&#xf…...

【记录】用JUnit 4的@Test注解时报错java.lang.NullPointerException的原因与解决方法

项目场景&#xff1a; 在练习黑马点评的逻辑过期解决缓存击穿时&#xff0c;编写了一个预热缓存数据的单元测试 SpringBootTest public class HmDianPingApplicationTests {Resourceprivate ShopServiceImpl shopService;Testpublic void testSaveShop() throws InterruptedE…...

Transformer入门(6)Transformer编码器的前馈网络、加法和归一化模块

文章目录 7.前馈网络8.加法和归一化组件9.组合所有编码器组件构成完整编码器 7.前馈网络 编码器块中的前馈网络子层如下图所示&#xff1a; 图1.32 – 编码器块 前馈网络由两个带有ReLU激活函数的全连接层组成。全连接层&#xff08;Fully Connected Layer&#xff09;有时也…...

(七)腾讯cloudstudio+Stable-Diffusion-webui AI绘画教程-安装Stable-Diffusion-WebUI

一、说明 本文选择安装stable-diffusion-webui最新版本 cloud studio 免费版最大的问题是空间不足&#xff0c;我晚上上传时超过了硬盘大小&#xff0c;直接不能启动&#xff0c;没办法&#xff0c;删除&#xff0c;又建了一个工作空间 二、安装 1、打开终端 2、配置Git代理…...

算法基础Day7(动态规划)

文章目录 1.题目2.题目解答1.第N个泰波那契数题目及题目解析动态规划算法学习1.状态表示2.状态转移方程3.初始化4.填表顺序5.空间优化 代码提交空间优化 2.三步问题题目及题目解析算法学习代码提交 1.题目 1137. 第 N 个泰波那契数 - 力扣&#xff08;LeetCode&#xff09;面试…...

代理IP地址和端口是什么?怎么进行设置?

保护个人隐私、突破地域限制、提升网络安全性是我们不断追求的目标。IP地址与端口一种实现这些目标的重要工具。但是&#xff0c;你可能对它是什么&#xff0c;以及如何设置感到困惑。别担心&#xff0c;本文将为你揭开这些神秘的面纱&#xff0c;让你轻松掌握这项技能。 1.IP…...

一文详解TCP协议 [图文并茂, 明了易懂]

欢迎来到啊妮莫的学习小屋! 目录 什么是TCP协议 TCP协议特点✨ TCP报文格式 三次握手和四次挥手✨ 可靠性 效率性 基于字节流✨ 基于TCP的应用层协议 什么是TCP协议 TCP(传输控制协议, Transmission Control Protocol) 是一种面向连接的, 可靠的, 基于字节流的传输层通…...

js后端开发之Next.js、Nuxt.js 与 Express.js

后端js之Next.js、Nuxt.js 与 Express.js 在现代 Web 开发中&#xff0c;JavaScript 已经成为前后端通用的编程语言&#xff0c;而选择合适的后端框架则是构建高效、可扩展应用程序的关键。本文将带你深入了解三个流行的 JavaScript 后端框架&#xff1a;Next.js、Nuxt.js 和 …...

人工智能概要

目录 前言1.什么是人工智能&#xff08;Artificial Intelligence, AI&#xff09;2.人工智能发展的三次浪潮2.1 人工智能发展的第一次浪潮2.2 人工智能发展的第二次浪潮2.3 人工智能发展的第三次浪潮 3.人工智能发展的必备三要素3.1 数据3.2 算法&#xff08;algorithm&#xf…...

spring boot 3集成swagger

Spring Boot 3 集成 Swagger 的过程与之前版本相比有一些变化&#xff0c;主要是因为 springfox 库已经停止更新&#xff0c;并且不再支持新的 Spring Boot 版本。因此&#xff0c;对于 Spring Boot 3 来说&#xff0c;推荐使用 springdoc-openapi 作为集成 Swagger 的解决方案…...

【PlantUML系列】状态图(六)

一、状态图的组成部分 状态&#xff1a;对象在其生命周期内可能处于的条件或情形&#xff0c;使用 state "State Name" as Statename 表示。初始状态&#xff1a;表示对象生命周期的开始&#xff0c;使用 [*] 表示。最终状态&#xff1a;表示对象生命周期的结束&…...

前端缓存页面处理方法

当前一个前端应用新发布时&#xff0c;重新编译后&#xff0c;原来引用的资源文件名都会有变化。如果这个应用的页面在前端浏览器中有缓存&#xff0c;则会导致加载资源失败。怎样去除这种缓存&#xff0c;同时也能尽可能的保证前端访问的性能 ChatGPT said: ChatGPT 这是一个经…...

每日一题 284. 窥视迭代器

284. 窥视迭代器 想要提前知道下一个内容&#xff0c;就需要缓存 class PeekingIterator : public Iterator { public:PeekingIterator(const vector<int>& nums) : Iterator(nums) {// Initialize any member here.// **DO NOT** save a copy of nums and manipula…...

Cesium-(Primitive)-(BoxGeometry)

含实现代码 GISer世界 效果: 以下是 BoxGeometry 类的构造函数属性,以表格形式展示: 属性名类型默认值描述minimumCartesian3盒子的最小 x, y, 和 z 坐标。maximumCartesian3盒子的最大 x, y, 和 z 坐标。vertexFormatVertexFormatVertexFormat.DEFAULT要计算的顶点属性。以下…...

CSS元素宽高特点、类型转化、显式和隐藏(display)

元素的宽高特点 块级元素 可以设置宽高&#xff0c;不可以和其他元素在一行设置宽高时&#xff0c;元素的宽高为设置的值没有设置宽高时&#xff0c;宽度和父级宽高一样&#xff0c;高度由元素内容决定 行级元素 不可以设置宽高&#xff0c;可以和其他元素在一行元素的宽高…...

上市公司投资效率Biddle模型数据(包括最终数据、原始数据及构造说明)2003-2022年

一、计算方式&#xff1a;参考《Journal of accounting and economics》Biddle G C&#xff0c;构建Biddle模型使用企业投资对成长机会的回归模型来估计企业的投资效率&#xff0c;这里成长机会用销售增长率来衡量。回归模型如下图所示: 二、资料范围&#xff1a;包括原始数据…...

矩阵的乘(包括乘方)和除

矩阵的乘分为两种&#xff1a; 一种是高等代数中对矩阵的乘的定义&#xff1a;可以去这里看看包含矩阵的乘。总的来说&#xff0c;若矩阵 A s ∗ n A_{s*n} As∗n​列数和矩阵 B n ∗ t B_{n*t} Bn∗t​的行数相等&#xff0c;则 A A A和 B B B可相乘&#xff0c;得到一个矩阵 …...

Spring Security6.3 自定义AuthorizationManager问题

项目环境&#xff1a; Springboot3.3.5, 对应的SpringFrameWork6.1&#xff0c;Security为6.3 问题&#xff1a;我想自定义AuthorizationManager接口实现类&#xff0c;在里面判断如果角色为amdin则放行请求&#xff1b; 在AdminAuthorizationManager类的check()方法中pass变量…...

第一部分:基础知识 9 . 视图 --[MySQL轻松入门教程]

在MySQL中,视图(View)是一个命名的SQL查询,它被存储在数据库目录中。视图可以包含来自一个或多个表的数据,并且可以像真实表一样被查询。下面是对MySQL视图的详细讲解: 创建视图 使用 CREATE VIEW 语句来创建视图。语法如下: CREATE [OR REPLACE] [ALGORITHM = {UNDEFIN…...

用GPT零负担学单片机之点亮一颗cpu 第3节 训练or特征匹配?用GPT开发嵌入式

用GPT零负担学单片机之点亮一颗cpu 第3节 训练or特征匹配?AI写代码 大家好,我是小杰学长 如果你是大学生 遇到电子技术 学习 成长 入行难题 我曾经通过大学比赛赚钱 从事嵌入式AI 航天军工 用特别的学习和求职方法线下半年带50+学弟学妹入行开发 主页佳喔威信,给你提供一定资…...

2.6、vue2中侦听属性的变化

2.6.1、侦听属性作用侦听属性的变化其实就是监视某个属性的变化。当被监视的属性一旦发生改变时,执行某段代码。2.6.2、watch配置项监视属性变化时需要使用watch配置项 可以监视多个属性,监视哪个属性,请把这个属性的名字拿过来即可。 i.可以监视Vue的原有属性 ii.如果监视的…...

enable_shared_from_this

用途 struct S {shared_ptr<S> dangerous(){return shared_ptr<S>(this); // dont do this!} };int main() {shared_ptr<S> sp1(new S);shared_ptr<S> sp2 sp1->dangerous();return 0; }考虑以上代码&#xff0c;从一个被shared_ptr管理的struc…...

重生之我在异世界学智力题(2)

大家好&#xff0c;这里是小编的博客频道 小编的博客&#xff1a;就爱学编程 很高兴在CSDN这个大家庭与大家相识&#xff0c;希望能在这里与大家共同进步&#xff0c;共同收获更好的自己&#xff01;&#xff01;&#xff01; 本文目录 引言智力题&#xff1a;逃离孤岛智力题&a…...

深入解析下oracle的number底层存储格式

oracle数据库中&#xff0c;number数据类型用来存储数值数据&#xff0c;它既可以存储负数数值&#xff0c;也可以存储正数数值。相对于其他类型数据&#xff0c;number格式的数据底层存储格式要复杂得多。今天我们就详细探究下oracle的number底层存储格式。 一、环境搭建 1.…...

prometheus

1.安装&#xff0c;tar包&#xff0c;解压即用 tar xf prometheus-2.33.3.linux-amd64.tar.gz -C /app/tools/ 2.创建软链接 ln -s prometheus-2.33.3.linux-amd64/ /app/tools/prometheus 3.进入目录 cd /app/tools/prometheus 4.运行 ./prometheus 5.此时&#xff0…...

C# 23种设计模式(1)单例模式(单件模式)

一、单例模式介绍 单例模式&#xff08;Singleton Pattern&#xff09;是一种创建型设计模式&#xff0c;它确保一个类只有一个实例&#xff0c;并提供一个全局访问点。这个模式在需要一个对象被共享且全局唯一的情况下非常有用&#xff0c;比如配置对象、日志对象、数据库连接…...

Javaweb:HTML、CSS

学习 资源1 学习资源 2 黑马javaweb HTML 1、基础标签、样式 图片标签&#xff1a;<img> src:绝对路径、相对路径(绝对磁盘路径&#xff0c;网络路径&#xff1b;./当前目录&#xff09;width:宽度&#xff08;百分比&#xff09;height:高度&#xff08;百分比&…...

SmartDV将SDIO系列IP授权给RANiX开发车联网(V2X)产品

双方的合作将增强符合ISO 26262标准的车联网&#xff08;V2X&#xff09;系统的通信和连接能力&#xff0c;加速实现更安全、更智能的汽车系统和车辆创新 加利福尼亚州圣何塞市&#xff0c;2024年12月——灵活、高度可配置、可定制化的半导体设计知识产权&#xff08;IP&#…...

【Android】创建型设计模式—单例模式、工厂模式、建造者模式

单例模式 单例模式&#xff08;Singleton Pattern&#xff09;是一种创建型设计模式&#xff0c;它确保一个类只有一个实例&#xff0c;并提供全局访问点。 单例模式类图&#xff1a; #mermaid-svg-kzf6IdXdYeNOHtP0 {font-family:"trebuchet ms",verdana,arial,sa…...

ida9pro压缩包

资源类型的博客大部分都是为了自己某天换新机了用 下载链接2&#xff1a;ida9.zip 下载链接1&#xff1a;https://mega.nz/folder/yiAiVDAa#T0kogEE7ufqy0x0EpCuOLQ 主目录下该文件为证书文件 ida9中选择它&#xff0c;就可以了...

前端入门之VUE--vue组件化编程

前言 VUE是前端用的最多的框架&#xff1b;这篇文章是本人大一上学习前端的笔记&#xff1b;欢迎点赞 收藏 关注&#xff0c;本人将会持续更新。 文章目录 2、Vue组件化编程2.1、组件2.2、基本使用2.2.1、VueComponent 2、Vue组件化编程 2.1、组件 组件&#xff1a;用来实现…...

C++是如何工作的?

首先来看一个最基本的C程序段。 #include <iostream>int main() {std::cout << "HelloWorld" << std::endl;std::cin.get(); } 第一行 #include 的含义是预处理的意思&#xff0c;这条语句的作用是将一个名为iostream的文件拷贝到源代码中这个…...

JavaScript中的this, 究竟指向什么?

在JavaScript代码的不同位置中&#xff0c;this所指向的数据是不一样的。比如大部分同学都知道&#xff0c;在对象的函数属性方法中&#xff0c;this指向对象本身&#xff1b;在构造函数中&#xff0c;this指向要生成的新对象。事实上&#xff0c;this指向的逻辑不止这几种&…...

JavaWeb学习(3)(Servlet详细、Servlet的三种实现方式(面试)、Servlet的生命周期、传统web.xml配置Servlet(了解))

目录 一、Servlet详细。 &#xff08;1&#xff09;基本介绍。 &#xff08;2&#xff09;基本作用。 1、接收客户端请求数据。 2、处理请求。 3、完成响应结果。 二、Servlet的三种实现方式。 &#xff08;1&#xff09;实现javax.servlet.Servlet接口。 1、基本介绍。 2、代码…...

【图像去雾数据集】URHI数据集介绍

URHI数据集对应论文&#xff1a;RESIDE: A Benchmark for Single Image Dehazing&#xff08;2017&#xff09; URHI数据集下载链接&#xff1a;https://sites.google.com/site/boyilics/website-builder/reside 为便于下载&#xff0c;将上述官方提供的链接中百度云链接粘贴如…...

Playwright中Page类的方法

导航和页面操作 goto(url: str, **kwargs: Any): 导航到一个URL。 reload(**kwargs: Any): 重新加载当前页面。 go_back(**kwargs: Any): 导航到会话历史记录中的前一个页面。 go_forward(**kwargs: Any): 导航到会话历史记录中的下一个页面。 set_default_navigation_tim…...

算力介绍与解析

算力&#xff08;Computing Power&#xff09;是指计算机系统在单位时间内处理数据和执行计算任务的能力。算力是衡量计算机性能的重要指标&#xff0c;直接影响计算任务的速度和效率。 算力的分类和单位 a. 基础算力&#xff1a;以CPU的计算能力为主。适用于各个领域的计算。…...

CentOS 上如何查看 SSH 服务使用的端口号?

我们知道&#xff0c;linux操作系统中的SSH默认情况下&#xff0c;端口是使用22&#xff0c;但是有些线上服务器并不是使用的默认端口&#xff0c;那么这个时候&#xff0c;我们应该如何快速知道SSH使用的哪个端口呢&#xff1f; 1、通过配置文件查看 cat /etc/ssh/sshd_confi…...

每日算法Day03

1.19.删除链表的倒数第N个节点 算法链接: 19. 删除链表的倒数第 N 个结点 - 力扣&#xff08;LeetCode&#xff09; 类型: 链表 难度: 中等 思路&#xff1a;采用双指针法&#xff0c;控制两个指针之间的距离为n个节点 易错点&#xff1a;返回节点的确定和头节点的处理&…...

【漏洞复现】Apache Solr 身份认证绕过导致任意文件读取漏洞复现(CVE-2024-45216)

🏘️个人主页: 点燃银河尽头的篝火(●’◡’●) 如果文章有帮到你的话记得点赞👍+收藏💗支持一下哦 【漏洞复现】Apache Solr 身份认证绕过导致任意文件读取漏洞复现(CVE-2024-45216) 一、漏洞概述1.1漏洞简介1.2组件描述1.3漏洞描述二、漏洞复现2.1 应用协议2.2 环境…...

若依将数据库更改为SQLite

文章目录 1. 添加依赖项2. 更新配置文件 application-druid.yml2.1. 配置数据源2.2. 配置连接验证 3. 更新 MybatisPlusConfig4. 解决 mapper 中使用 sysdate() 的问题4.1. 修改 BaseEntity4.2. 修改 Mapper 5. 更新 YML 配置 正文开始&#xff1a; 前提条件&#xff1a;在您的…...