广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >浅谈Redis缓冲区机制
  • 490
分享到

浅谈Redis缓冲区机制

2024-04-02 19:04:59 490人浏览 安东尼
摘要

目录Redis缓冲区机制客户端缓冲机制应对输入缓冲区溢出查看输入缓冲区信息如何解决输入缓冲区溢出应对输出缓冲区溢出Monitor命令的执行输出缓冲区设置不合理主从集群中的缓冲区复制缓

Redis缓冲区机制

Redis中的缓冲区机制就是为了平衡客户端发送命令和服务端处理命令的速度差异,如果客户端写入过快或者服务端读取过慢这就会导致缓冲区溢出,缓冲区一旦溢出将引发一系列的性能问题,下面我们详细聊聊。

客户端缓冲机制

Redis为每一个客户端都分配了一个输入缓冲区和输出缓冲区,输入缓冲区会把客户端的请求命令暂存起来,Redis主线程会从缓冲区中获取命令,当Redis处理完命令后会将结果写入到输出缓冲区中,通过输出缓冲区返回给客户端,如下所示

应对输入缓冲区溢出

输入缓冲区溢出一般就是两种情况

  • 写入数据过快,或者写入bigkey的数据占满数据缓冲区。
  • 服务端处理数据过慢,一般是主线程被阻塞无法正常响应客户端请求。

查看输入缓冲区信息

我们可以采用client list查看输入缓冲区的具体信息

127.0.0.1:6379> client list
id=13 addr=127.0.0.1:50484 fd=7 name= age=1136 idle=1 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 user=default
id=14 addr=127.0.0.1:50486 fd=8 name= age=1114 idle=6 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=client user=default

每连接上一个客户端就会多一条输入缓冲区信息,上面命令是我本地连接两个客户端的结果,我们查看缓冲区主要关注内存相关的两个参数

  • qbuf:缓冲区已经使用的长度(字节为单位,0表示没有分配缓冲区)。
  • qbuf-free:缓冲区剩余空闲空间(字节为单位),上面一个客户端的qbuf=26,空闲缓冲区qbuf-free=32742,那么分配内存总大小为26+32742=32768字节也就是32KB。

如果输入缓冲区信息中的qbuf-free很小并且qbuf很大时就需要注意了,这时输入缓冲区可能已经快溢出了,如果此时还有大量请求写入输入缓冲区,Redis的解决办法就是关闭和这个客户端的连接,那么业务数据将无法正常存取。

而且还有一个问题就是输入缓冲区是每一个客户端都会存在,那么当所有客户端的输入缓冲区内存总和超过了maxmemory配置,那么将引发内存淘汰,部分淘汰的数据再次访问需要从后台数据库获取,获取的耗时肯定比Redis直接读取慢的多,所以这也是Redis产生延迟的一个原因。

如何解决输入缓冲区溢出

输入缓冲区溢出本质就是缓冲区的容量不够,所以第一个思路就是扩大输入缓冲区的大小,很不幸Redis没有提供给我们修改输入缓冲区大小的配置,Redis要求每个客户端的输入缓冲区最大不能超过1G,注意是每个客户端!!!,如果客户端的输入缓冲区超过一个1G将关闭客户端连接,所以这个是行不通的。

那就只能从客户端发送数据的大小以及服务端处理命令的速度,客户端需要避免bigkey的写入bigkey的劣势太多一般都需要拆分,第二服务端的命令处理速度这个一般依赖于主线程是否阻塞,需要尽量的避免一些阻塞操作如AOF文件重写,键值删除,fork线程等等。

应对输出缓冲区溢出

对于服务端而言,客户端的输入信息通常都是不可预测的,但是输出信息大多可以预测,如Set命令返回信息只是一个简单的OK,又如一些报错信息,Redis为这些不变的返回信息分配了16KB的固定缓冲空间,也就是说输出缓冲区分为两个部分一部分是输出缓冲区固定返回信息,一部分是可变的返回信息。

输出缓冲区溢出分为三种情况

  • 输出bigkey等容量大的键值。
  • 客户端执行Monitor命令,监控Redis执行。
  • 缓冲区设置不合理。

bigkey是老生常谈的一个问题,当服务端输出一个bigkey或者keys这类命令,对输出缓冲区的考验是非常大的,因为查询的一瞬间会占据输入缓冲区大量的内存空间。

Monitor命令的执行

Monitor命令一般是一个debug命令,用来监控Redis的具体执行情况,能够返回服务器处理的每一个命令。

127.0.0.1:6379> monitor
OK
1652184977.609761 [0 127.0.0.1:50484] "get" "name"
1652185391.529292 [0 127.0.0.1:50484] "set" "test" "lisi"
......

一直运行monitor将一直占据输出缓冲区,也就是说占据时间越长,越容易造成输出缓冲区的溢出,所以Monitor命令仅仅只适用于调试环境,不能在生产上执行这些命令。

输出缓冲区设置不合理

输入缓冲区的大小不能设置,但是输出缓冲区的是可以设置的我们可以通过配置项client-output-buffer-limit来设置,设置的内容就是两部分

  • 缓冲区的内存大小,当超过缓冲区配置的大小,服务端会关闭和客户端的连接。
  • 持续写入的时间限制和持续写入的容量限制,当超过持续写入时间限制和容量限制,服务端也会强制关闭和客户端的连接。

客户端种类

在聊缓冲区配置时,我们需要先了解下客户端的种类,本文中强调的客户端并不是单纯指通过命令./redis-cli -c -h 127.0.0.1 -p 6379去连接Redis服务器这类客户端称为常规客户端,我们还有通过消息订阅Redis频道的客户端,还有一种最为特殊的主从同步,从节点也是一个特殊的客户端称为从节点客户端。

配置项client-output-buffer-limit也是针对这三种,给出了不一样的配置,如下所示

## 普通客户端配置
client-output-buffer-limit nORMal 0 0 0
## 从节点客户端配置
client-output-buffer-limit replica 256mb 64mb 60
## 消息订阅频道的客户端
client-output-buffer-limit pubsub 32mb 8mb 60

######################配置解释######################
## 第一个参数:代表分配给客户端的缓存大小,为0代表没有限制
## 第二个参数:表示持续写入的最大内存,为0代表没有限制
## 第三个参数:表示持续写入的最长时间,为0代表没有限制

普通客户端设置

普通客户端就是传输的一些普通的指令,一个指令发送完需要等待其返回后才会发送下一个指令,也就是说只要不是返回的bigkey数据,占用输出缓冲区的内存就极少,能够立即发送给客户端响应,所以一般正常客户端默认配置都是0,也就是不限制。

消息订阅频道客户端

当订阅频道产生消息后,会将消息通过输出缓冲区发送给客户端,这种属于非阻塞的方式,一瞬间可能有多个指令到达,所以需要指定缓冲区大小。

如何解决输出缓冲区溢出

到这里其实我们已经能够得到输出缓冲区溢出的解决方案了

  • bigkey应当避免使用。
  • Monitor命令只在调试的时候使用,不能应用到生产。
  • 合理设置输出缓冲区上限、持续写入时间上限以及持续写入内存容量上限。

主从集群中的缓冲区

除了输入缓冲区和输出缓冲区外在主从集群场景下还存在两种缓冲区,我们称为复制缓冲区和复制积压缓冲区,这两个缓冲区的溢出和输入输出缓冲区稍有不同。

复制缓冲区

复制缓冲区这个名词看着很陌生,但是我们之前在聊主从同步时讲过,主从全量同步期间从节点会加载主节点的RDB文件,这时主节点同样还能写入数据,但是从节点在加载RDB文件没办法实时同步,所以Redis就为每一个从节点开辟了一片空间,用来存放主从全量同步期间产生的操作命令,这就是replication buffer,也就是复制缓冲区。

复制缓冲区溢出

复制缓冲区什么时候会溢出呢?

  • 当从节点在加载RDB文件这个过程中如果存在大量的写操作就会造成复制缓冲区内存溢出。
  • 从节点加载RDB文件的时间过长。

发生溢出后,主节点会关闭与从节点的连接,导致全量同步失败。

解决复制缓冲区溢出

控制主节点实例的大小,减小生成的RDB文件,这样就能减少从节点加载RDB文件的时间,减小复制缓冲区的压力。

从节点其本质就是主节点的特殊客户端,所以使用的是输出缓冲区(也就是指replication buffer),可以设置client-output-buffer-limit replica 256mb 64mb 60扩大缓冲区大小。

注意:主节点上的复制缓冲区会为每一个从节点分配一个,那么从节点的数量过多即使每个从节点没有达到maxmemory,但累加的结果也会给主节点带来内存压力

复制积压缓冲区

复制积压缓冲区溢出

主从集群在写操作时会将操作写入复制缓冲区和复制积压缓冲区中,一旦网络发送故障后恢复连接,在2.8版本之前主从节点会进行全量同步开销非常大,所以2.8版本后还是采用了增量同步,仅仅将网络断开这段时间的操作同步给从节点,所以在网络恢复连接后从节点会将自己的复制偏移量slave_repl_offset发送给主节点,主节点将自身的写入偏移量master_repl_offset和slave_repl_offset在复制积压缓冲区中做对比得到网络断连期间的操作。

复制积压缓冲区又叫repl_backlog_buffer,是一个环形缓冲区,同步示意图如下。

复制积压缓冲区溢出其实也就是因为复制积压缓冲区是一个有限环形结构,一般主节点写入偏移量要大于从节点的读取偏移量,但如果写入偏移量覆盖了从节点的读取偏移量这就引发了复制积压缓冲区溢出。

解决复制积压缓冲区溢出

一般是调整repl_backlog_size这个参数的大小,扩大复制积压缓冲区的大小,减小主节点写入偏移量覆盖从节点读取偏移量的风险。

到此这篇关于浅谈Redis缓冲区机制的文章就介绍到这了,更多相关Redis缓冲区内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: 浅谈Redis缓冲区机制

本文链接: https://www.lsjlt.com/news/150461.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 浅谈Redis缓冲区机制
    目录Redis缓冲区机制客户端缓冲机制应对输入缓冲区溢出查看输入缓冲区信息如何解决输入缓冲区溢出应对输出缓冲区溢出Monitor命令的执行输出缓冲区设置不合理主从集群中的缓冲区复制缓...
    99+
    2022-11-13
  • 浅谈C++ 缓冲区(buffer)的使用
    缓冲区 缓冲区 (buffer) 是内存空间的一部分. 在内存中会为每一个数据流开辟一个内存缓冲区. 缓冲区是用来存放流中的数据, 缓冲区中的数据就是流. 在 C++ 中, 输入输出...
    99+
    2022-11-12
  • Redis缓冲区机制实例分析
    这篇文章主要介绍“Redis缓冲区机制实例分析”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Redis缓冲区机制实例分析”文章能帮助大家解决问题。Redis缓冲区机制Redis中的缓冲区机制就是为了...
    99+
    2023-06-30
  • 浅谈Redis的异步机制
    目录前言一、Redis 的阻塞点4 类交互对象和具体的操作之间的关系:切片集群实例交互时的阻塞点二、可以异步执行的阻塞点三、异步的子线程机制总结前言 命令操作、系统配置、关键机制、硬...
    99+
    2022-11-13
  • 浅谈java如何实现Redis的LRU缓存机制
    目录LRU概述使用LinkedHashMap实现 使用LinkedHashMap简单方法实现双链表+hashmapLRU概述 最近使用的放在前面,最近没用的放在后面,如果...
    99+
    2022-11-12
  • 浅谈缓冲字符流 BufferedReader BufferedWriter用法
    缓冲字符流BufferedReader和BufferedWriter 问题: 之前的文件读写都是按照字节、字符或者数组来实现的,对于文本文件而言,能否按照行,一行行读写呢。 提供了B...
    99+
    2022-11-12
  • 浅谈Redis中的自动过期机制
    目录Redis中的自动过期机制一、使用Redis Key自动过期机制二、SpringBoot整合key失效监听Redis中的自动过期机制 实现需求:处理订单过期自动取消,比如下单30...
    99+
    2022-11-13
  • 浅析Java NIO 直接缓冲区和非直接缓冲区
    定义 以上是书《深入理解java虚拟机》对直接内存的描述。直接缓冲区用的就是直接内存。 java nio字节缓冲区要么是直接的,要么是非直接的。如果为直接字节缓冲区,则j...
    99+
    2022-11-12
  • 浅谈Redis缓存更新策略
     内存淘汰超时剔除主动更新说明不用自己维护,利用Redis的内存淘汰机制,当内存不足时自动淘汰部分数据。下次查询时更新缓存给缓存数据添加TTL时间,到期后自动删除缓存,下次...
    99+
    2022-11-13
    redis缓存策略 redis缓存更新策略 redis缓存更新机制
  • 【Android】 浅谈Handler机制
    Handler机制产生的原因 在谈论一个机制之前,需要了解这个机制设计出来是为了解决什么问题。 Handler设计出来就是因为UI线程不能进行耗...
    99+
    2022-06-06
    handler机制 handler Android
  • 浅谈Java锁机制
    目录1、悲观锁和乐观锁2、悲观锁应用3、乐观锁应用4、CAS5、手写一个自旋锁1、悲观锁和乐观锁 我们可以将锁大体分为两类: 悲观锁 乐观锁 顾名思义,悲观锁总是...
    99+
    2022-11-12
  • 浅谈Redis缓存雪崩解决方案
    目录1.保持缓存层的高可用2.限流降级组件3.缓存不过期4.优化缓存过期时间5.使用互斥锁重建缓存6.异步重建缓存缓存层承载着大量的请求,有效保护了存储层。但是如果由于大量缓存失效或...
    99+
    2022-11-13
  • 浅谈Python pygame绘制机制
    pygame绘制机制简介  屏幕控制 pygame.display • 用来控制Pygame游戏的屏幕 • Pygame有且只有一个屏幕 • 屏幕左上角坐标为(0,0) ...
    99+
    2022-06-02
    pygame绘制机制 python pygame
  • 浅谈Java内省机制
    目录概念JavaBean内省相关API代码案例:获取属性相关信息内省属性的注意事项完整代码概念 JavaBean 在实际编程中,我们常常需要一些用来包装值对象的类,例如Student...
    99+
    2022-11-13
    Java内省机制 Java内省
  • 浅谈Swift派发机制
    目录直接派发函数表派发消息机制派发具体派发直接派发 C++ 默认使用的是直接派发,加上 virtual 修饰符可以改成函数表派发。直接派发是最快的,原因是调用指令会少,还可以通过编译...
    99+
    2022-11-12
  • 浅谈Linux信号机制
    目录一、信号列表1.1、实时信号非实时信号1.2、信号状态1.3、信号生命周期1.4、信号的执行和注销二、信号掩码和信号处理函数的继承2.1、信号处理函数的继承2.2、信号掩码的继承2.3、sigwait 与多线程2...
    99+
    2022-06-03
    Linux 信号机制
  • 浅谈Java 代理机制
    目录一、常规编码方式二、代理模式概述三、静态代理3.1、什么是静态代理3.2、代码示例四、Java 字节码生成框架五、什么是动态代理六、JDK 动态代理机制6.1、使用步骤6.2、代...
    99+
    2022-11-12
  • 浅谈AndroidDialog窗口机制
    目录问题引出Dialog源码分析构造方法show()方法问题引出 //创建dialog 方式一 AlertDialog.Builder builder=new AlertDialo...
    99+
    2022-11-13
  • 浅谈numpy广播机制
    目录Broadcast最简单的广播机制稍微复杂的广播机制广播机制到底做了什么一个正确的经典示例一种更便捷的计算方式Broadcast 广播是numpy对不同形状(shape)的数组进...
    99+
    2023-02-15
    numpy 广播机制
  • 浅谈redis缓存在项目中的使用
    背景 Redis 是一个开源的内存数据结构存储系统。 可以作为数据库、缓存和消息中间件使用。 支持多种类型的数据结构。 Redis 内置了 复制(replication),LUA脚...
    99+
    2022-11-12
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作