Redis缓冲区分析

news/2025/2/6 16:02:17/文章来源:https://www.cnblogs.com/ceiloruz/p/18701089

Redis缓冲区分析

1 Redis缓冲区简介

缓冲区,用一块内存空间暂时存放命令数据,目的是解决因数据和命令的处理速度小于发送速度而导致数据丢失和性能问题。缓冲区的内存空间有限,当写数据速度>读数据速度持续进行,会导致缓冲区容量需越来越大。当缓冲区占用内存>设定上限阈值,就会出现缓冲区溢出,会丢数据。

危害

  • 如果发生溢出就会丢失数据。
  • 缓冲区大小设置不当可能因为缓冲区过大影响Redis实例所在机器的可用内存

缓冲区在redis中应用场景

1 用来暂存客户端发送的命令数据或者服务器端返回给客户端的数据结果。
2 在主从节点间进行数据同步时,用来暂存主节点接收的写命令和数据

2 客户端输入、输出缓冲区

redis服务器端和客户端之间的缓冲区。redis是典型的C/S结构,C即client,S即server。

为避免C、S 的请求发送和处理速度不匹配,S给每个连接的C都设个输入、输出缓冲区,称为客户端输入、输出缓冲区。输入缓冲区先暂存C发来的命令,Redis主线程再从中读命令并处理。
当Redis主线程处理完数据,会把结果写入输出缓冲区,再通过输出缓冲区返给客户端

img

2.1 输入缓冲区溢出

2.1.1 可能场景

写入bigkey,如一下写入多个百万级别的集合类型数据
服务器端处理请求速度过慢,如Redis主线程出现间歇性阻塞,无法及时处理正常发送的请求,导致客户端发送的请求在缓冲区越积越多

client list命令
查看输入缓冲区的内存使用,可使用CLIENT LIST命令:

CLIENT LIST
id=5 addr=127.0.0.1:50487 fd=9 name= age=4 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=26 qbuf-free=32742 obl=0 oll=0 omem=0 events=r cmd=client

案例展示的是一个客户端的输入缓冲区情况,如有多个客户端,输出结果中的addr会显示不同客户端的IP和端口号
输入缓冲区相关参数:
cmd
客户端最新执行的命令。这个例子中执行的是CLIENT命令。
qbuf
输入缓冲区已经使用的大小。这个例子中的CLIENT命令已使用了26字节大小的缓冲区。
qbuf-free
输入缓冲区尚未使用的大小。

这个例子中的CLIENT命令还可以使用32742字节的缓冲区。qbuf和qbuf-free的总和就是Redis服务器端当前为已连接的这个客户端分配的缓冲区总大小。这个例子中总共分配了 26 + 32742 = 32768字节,也就是32KB的缓冲区。
qbuf和qbuf-free:Redis为每个客户端分配了输入缓冲区,它的作用是将客户端发送的命令临时保存,同时Redis会到输入缓冲区拉取命令并执行,输入缓冲区为客户端发送命令道Redis执行命令提供了缓冲功能。qbuf代表了输入缓冲区的大小,qbuf-free代表输入缓冲区的剩余容量。输入缓冲区会根据输入内容的大小动态调整,每个客户端的输入缓冲区大小不能超过1G。超过后客户端将被关闭

通常Redis S不止服务一个C,当多个C连接占用的内存总量,超过maxmemory配置项(如4G),触发Redis数据淘汰。如使用多个客户端,导致Redis内存占用过大,也会导致内存溢出(out-of-memory),进而引起Redis崩溃,给业务应用造成严重影响。

2.1.2 解决方案

Redis不允许我们调节客户端输入区的大小,Redis客户端的输入缓冲区的大小的上线阈值,在代码中设定为1GB。
因此必须避免客户端写入 bigkey,避免 Redis 主线程阻塞的慢命令。

2.2 输出缓冲区溢出

Redis输出缓冲区暂存Redis主线程要返回给客户端的数据。
一般主线程返回给客户端的数据,既有简单且大小固定的OK响应(例如,执行SET命令)或报错信息,也有大小不固定的、包含具体数据的执行结果(例如,执行HGET命令)。

因此,Redis为每个客户端设置的输出缓冲区,包括两部分:

一个16KB固定缓冲空间,暂存OK响应和出错信息
可动态增加的缓冲空间,暂存大小可变的响应结果

2.2.1 可能场景

bigkey
服务器端返回大量bigkey结果。

MONITOR
用来监测Redis执行的。执行这命令后,会持续输出监测到的各个命令操作:

MONITOR
OK
1600617456.437129 [0 127.0.0.1:50487] "COMMAND"
1600617477.289667 [0 127.0.0.1:50487] "info" "memory"
MONITOR输出结果会持续占用输出缓冲区,并越占越多,最后就是发生溢出。

MONITOR命令主要用在调试环境,生产环境禁止持续使用MONITOR。若线上偶尔使用MONITOR检查Redis命令执行情况,也没问题。

2.2.2 设置缓冲区 client-output-buffer-limit

设置缓冲区上限阈值:设置输出缓冲区持续写入数据的数量上限阈值,和持续写入数据的时间的上限阈值。

设置缓冲区大小前,需先区分客户端类型:普通客户端、发布订阅客户端、slave客户端

client-output-buffer-limit

选项:

class: 客户端类型 normal:普通客户端 ; slave:slave客户端,用于复制; pubsub:发布订阅客户端

hard limit:如果客户端使用的输出缓冲区大于hardlimit,客户端会立即关闭。

soft limit和soft seconds:如果客户端使用的输出缓冲区大于soft limit,并且超出了soft seconds秒,客户端会被立即关闭。

Redis针对不同客户端有不同策略,默认策略如下:

client-output-buffer-limit normal 0 0 0

client-output-buffer-limit slave 256mb 64mb 60

client-output-buffer-limit pubsub 32mb 8mb 60

对于普通客户端来说,限制为0,也就是不限制。因为普通客户端通常采用阻塞式的消息应答模式,何谓阻塞式呢?如:发送请求,等待返回,再发送请求,再等待返回。这种模式下,通常不会导致Redis服务器输出缓冲区的堆积膨胀;

对于Pub/Sub客户端(也就是发布/订阅模式),大小限制是8M,当输出缓冲区超过8M时,会关闭连接。持续性限制是,当客户端缓冲区大小持续60秒超过2M,则关闭客户端连接;

对于slave客户端来说,大小限制是256M,持续性限制是当客户端缓冲区大小持续60秒超过64M,则关闭客户端连接。

2.2.2 解决方案

避免大K操作返回大量数据结果
避免在线上环境中持续使用MONITOR
使用client-output-buffer-limit设置合理缓冲区大小上限或缓冲区连续写入时间和写入量上限

3 主从集群中的缓冲区

全量复制和增量复制都会用到缓冲区。

3.1 全量复制缓冲区的溢出

全量复制,Master(后文简称为M)在向Replica(后文简称为R)传输RDB文件同时,会继续接收C发送的写请求。

这些写命令先保存在复制缓冲区,等RDB传输完,再发给从节点执行。

主节点会为每个从节点都维护一个复制缓冲区,保证和主从节点间的数据同步。

img

如果全量复制时,S接收和加载RDB较慢,同时M接收了大量的写命令,写命令在复制缓冲区中会越积越多,最终导致溢出,复制缓冲区一旦溢出,M也会直接关闭和R进行复制操作的连接,全量复制直接失败。

3.1.1 复制缓冲区发生溢出解决方案

1 控制主节点保存的数据量大小,建议把主节点的数据量控制在2-4GB,这样可以让全量同步执行更快些,避免复制缓冲区累积过多命令。
2 使用client-output-buffer-limit配置项,来设置合理的复制缓冲区大小。设置的依据就是主节点的数据量大小,主节点的数据量大小,主节点写负载压力和主节点本身的内存大小。
3 需要控制节点数量,避免主节点中复制缓冲区占用过多内存的问题。

在M执行:

config set client-output-buffer-limit replica 512mb 128mb 60

replica
该配置项针对复制缓冲区
512mb
将缓冲区大小的上限设为512M
128mb和60
若连续60s内写入量>128M,也会触发缓冲区溢出

假设一条写命令数据是1KB,则复制缓冲区可积压512K条(512MB/1KB = 512K)写命令。
M在全量复制期间,可承受写命令速率上限=2000条/s(128MB/1KB/60≈2000)。

评估依据:

根据写命令数据的大小 && 实际负载情况(即写命令速率),估计缓冲区中会积压的写命令数据量,再和所设置的复制缓冲区大小比较,判断设置的缓冲区是否够支撑积压的写命令数据量。由于M复制缓冲区的内存开销,会是每个R客户端输出缓冲区占用内存总和。若集群中R很多,M内存开销就很大。所以还得控制和M连接的R个数,不要使用大规模主从集群。

3.2 增量复制积压缓冲区的溢出

增量复制时使用的缓冲区,这个缓冲区称为复制积压缓冲区。

M在把接收到的写命令同步给R时,同时会把这些写命令写入复制积压缓冲区。
一旦R发生网络闪断,和M重连后,R就会从复制积压缓冲区读取断连期间M接收到的写命令,进行增量同步:

img

repl_backlog_buffer:复制积压缓冲区是一个大小有限的环形缓冲区。当主节点把复制积压缓冲区写满以后,会覆盖缓冲区中的旧命令。如果节点还没同步这些旧命令(通过对比offset),就会造成主从节点间重新开始执行全量复制。
为了应对复制冲压缓冲区的溢出问题,我们可以调整复制积压缓冲区的大小,即repl_backlog_size参数值。

4 总结

使用缓冲区后,当命令数据的接收方处理速度跟不上发送方的发送速度,缓冲区可避免丢失命令数据。

按缓冲区用途,如客户端通信or主从节点复制,分为:

客户端的输入和输出缓冲区
主从集群中主节点上的复制缓冲区和复制积压缓冲区
从缓冲区溢出对Redis的影响的角度,把四个缓冲区分成两类总结

缓冲区溢出导致网络连接关闭
普通客户端、订阅客户端及从节点客户端,所用缓冲区本质都是Redis客户端和服务器端间,或主从节点间为传输命令数据而维护。这些缓冲区一旦溢出,处理机制都是直接关闭客户端和服务器端的连接,或主从节点间的连接。
而网络连接关闭造成的直接影响,就是业务程序无法读写Redis,或者是主从节点全量同步失败,需重新执行。
缓冲区溢出导致命令数据丢失
M的复制积压缓冲区属环形缓冲区,一旦溢出,新写入的命令数据就会覆盖旧的命令数据,导致旧命令数据的丢失,进而导致主从节点重新全量复制。
缓冲区溢出的原因:

命令数据发送过快、过大
对普通客户端,可避免bigkey,而对复制缓冲区,就是避免过大RDB文件
命令数据处理较慢
减少Redis主线程上的阻塞操作,如使用异步删除操作
缓冲区空间过小
使用client-output-buffer-limit配置项设置合理的输出缓冲区、复制缓冲区和复制积压缓冲区大小
输入缓冲区的大小默认是固定的,无法通过配置修改,除非改源码。

Redis的主从同步非常依赖于两个参数的合理配置:

  1. client-output-buffer-limit
  2. repl-backlog-size

5 案例

数据变更量太大,超过了client-output-buffer-limit,会导致主从同步连接被断开,然后S要求psync,但是由于repl-backlog-size太小,导致psync失败,需要full sync,而full sync需要Discarding previously cached master state,重新load RDB文件到内存,而这个加载数据过程是阻塞式的。所以导致slave出现间歇式的不可用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/879694.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微服务开发环境搭建

1. 配置maven,使用阿里镜像库 2.idea下载常用的插件,lomok插件和mybatis插件 3.新建工程,微服务分布式工程 4.前端开发工具安装vs code 5.配置git代码仓库管理 本文永久更新地址:1. 配置maven,使用阿里镜像库 找到maven下载安装目录,找到conf配置文件,修改setting.xml配置…

SpringBoot的idea搭建使用过程(一)

1,在idea中新建一个SpringBoot项目 2,搭建项目框架 3,修改application配置文件后缀改成yml,添加配置文件,yml需要注意格式 4,在控制器层添加一个测试接口 5,启动Demo1Application类启动成功后就可以访问http://localhost:8080/看到在templates里面添加的index.html 本文永…

虚机运行pgjdbc-ng 客户端驱动创建数据库连接报超时错误

// debug 调试代码发现 CryptoUtil.nonce卡住,继续跟踪发现是random.nextInt方法阻塞。 public ScramSession start(String user) {String nonce = CryptoUtil.nonce(nonceLength, secureRandom); // return new ScramSession(scramMechanism,channelBindMethod, serverSuppo…

政采云业务网关实践:使用 Higress 统一替代 APISIX/Kong/Istio Ingress

技术栈统一是逐步达成的目标,不过从目前需要解决的问题紧急度上看,容器网关、业务网关需要合并,以一个技术栈解决网关配置治理、扩展能力的问题。经过社区活跃度、能力对比等多个维度的比较,最终筛选出 APISIX、Higress、Istio(IngressGateway)这三个网关服务。作者:政采…

03 配置测试、兼容测试

8.配置测试 8.1配置测试综述 1)个人计算机 2)部件 3)外设 4)接口 5)可选项和内存 6)设备驱动程序 8.1.1分离配置缺陷 软件缺陷和配置缺陷有可能造成软件出现问题。 8.2执行配置测试 1)确定所需配置类型 2)确定有哪些厂商的硬件、型号、和驱动程序可用 3)确定可能的硬件…

ThreeJs-13效果合成与后期处理

一.合成效果原理与设置 什么是效果合成,就是可以把一些效果经过后期处理再放出来 原来的物体是直接通过render渲染出来,而现在则是经过一条render通道,可以处理也可以叠加处理后再放出来首先正常加载模型首先导入效果合成器以及一些自带的效果创建合成效果渲染器,跟之前渲染…

解决Windows11可能出现的自动获取到错误的DNS地址问题

现象 当一个wifi再射中中配置了手动的DNS地址,如114.114.114.114/114.114.115.115,连接其他新wifi的时候,虽然默认自动获取DNS,但是获取的却不是路由配发的DNS,而是之前设置的114.114.114.114/114.114.115.115 解决方案 1、首先打开旧ui的网卡的设置,确定处于自动dns。2、…

docker在mac-m1芯片部署并启用tomcat

手把手教你使用docker在mac-m1芯片部署并启用tomcat 1,下载docker并安装 登陆官网下载dockr,选择mi芯片的docker下载 下载地址:https://www.docker.com/get-started 2,配置docker的阿里云加速器(也可以配置其他加速器) 在设置---docker engine 中添加阿里云的加速器 {&quo…

JS-51 事件代理(事件委托)

由于事件会在冒泡阶段向上传播到父节点,因此可以把子节点的监听函数定义在父结点上,由父节点的监听函数统一处理多个子元素的事件。这种方法叫做事件的代理(delegation)var ul =document.querySelector(ul);ul.addEventListenr(click,function(event){if(event.target.tagN…

docker搭建jenkins导入python包

title: docker搭建jenkins导入python包 tags: - docker - centos - jenkins categories: - docker1. 项目概述 2. 环境准备 3. 创建 Dockerfile 4. 创建 Docker Compose YAML 文件 services volumes5. 同级目录放requirements.txt 6. 启动 Jenkins 服务 7. 访问 Jenkins 8. 验…

普通人做短剧需要哪些证书?

短剧行业爆火,但在制作短剧需持有相关资质,否则就属于违规经营。不管是想在各大平台宣传推广,还是想上架小程序等途径都是要求三证齐全的。 那应该先取得什么样的资质才可以开展这项业务? 第一个就是增值电信业务经营许可证—ICP许可证这是从事互联网行业的基本要求,它的申…

DeepSeek如何在资源优化时做到了性能领先?

问题:DeepSeek如何在资源优化时做到了性能领先? DeepSeek V3的Benchmark如图3所示,该图显示DeepSeek V3在主要数据集测试时超越了业界LLM同类标杆的水平,这给了业界一个初步的惊喜,尤其是训练阶段花费了少于业界LLM同类标杆十分之一的代价:图3:DeepSeek V3如何以更少资源…