缓冲区(buffer),是内存空间的一部分。也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区。

一、Redis缓冲区溢出影响

在Redis中,主要有三个场景用到了缓冲区的概念。

  • 在客户端和服务器端之间进行通信时,用来暂存客户端发送的命令数据,或者是服务器端返回给客户端的数据结果
  • 在主从节点间进行数据同步时,Redis使用缓冲区来暂存主节点接收的写命令和数据
  • 在Redis进行AOF持久化的时候Redis为了避免频繁写磁盘同样用到了缓冲区的概念

缓冲区概念最初是操作系统为了缓和 CPU 与 I/O 设备速度不匹配的矛盾,提高 CPU 和 I/O 设备的并行性而引入的。

对于高速设备与低速设备的不匹配,势必会让高速设备花时间等待低速设备。有了缓冲区的概念就可以很好的解决这个问题。缓冲区也是生产者消费者模式的重要体现。

1、缓冲区溢出导致网络连接关闭

如果 qubf-free 耗尽,就会引起客户端输入缓冲区溢出,Redis 的处理方法就是把客户端连接关闭,导致的结果就是业务程序无法进行数据存取。

2、缓冲区溢出导致命令数据丢失或者崩溃

通常情况下,会有很多的客户端连接,当客户端连接占用的内存总量,超过了 Redis 的 maxmemory 配置时,就会触发 Redis 进行数据淘汰,影响业务程序的访问性能。

甚至多个客户端会导致 Redis 内存占用过大,也会导致内存溢出问题,进而引起 Redis 崩溃。

二、客户端缓冲区

客户端缓冲区又有两个,输入缓冲区和输出缓冲区,都是为了解决客户端和服务器端的请求发送和处理速度不匹配所设置的。

输入缓冲区暂存的是客户端发来的命令,其常见的溢出原因有两个:

  1. 写入了BigKey,如一次性写入了百万级别的哈希或集合数据,超过了缓冲区的大小
  2. 服务端处理请求的速度过慢导致阻塞,无法及时处理请求,使得客户端发送的请求在缓冲区内越积越多。

输出缓冲区暂存的是 Redis 主线程要返回给客户端的数据。

这个数据,既有简单且大小固定的 OK 响应(例如,执行 SET 命令)或报错信息,也有大小不固定的、包含具体数据的执行结果(例如,执行 HGET 命令)

输出缓冲区常见的溢出原因有三种:

  1. 返回BigKey的大量结果
  2. 执行了某些不合理的命令
  3. 缓冲区大小设置不合理

从输入和输出缓冲区常见导致溢出的原因来看,BigKey是最可能导致溢出的原因,因此我们应该尽量避免使用BigKey。

对于输入缓冲区,因为没有办法改变其大小(默认每个客户端1G),我们只能通过控制命令的发送和处理速度入手,尽量避免阻塞。

对于输出缓冲区则要避免一些返回大量结果的命令的使用如KEYS,MONITOR等,同时可以通过调整输出缓冲区的大小来避免溢出。

三、复制缓冲区

复制缓冲区是用于Redis主从节点之间复制时使用的。由于主从节点间的数据复制包括全量复制和增量复制两种。因此复制缓冲区也分为复制缓冲区和复制积压缓冲区两种。

1、复制缓冲区

在全量复制过程中,主节点在向从节点传输 RDB 文件的同时,会继续接收客户端发送的写命令请求。这些写命令就会先保存在复制缓冲区中,等 RDB 文件传输完成后,再发送给从节点去执行。主节点上会为每个从节点都维护一个复制缓冲区,来保证主从节点间的数据同步。

对于复制缓冲区,如果主库传输 RDB 文件以及从库加载 RDB 文件耗时长,同时主库接收的写命令操作较多,就会导致复制缓冲区被写满而溢出。

想要避免复制缓冲区溢出,一方面我们可以控制主节点保存的数据量大小,这样可以让RDB文件的传输以及从库加载时间变快,以避免复制缓冲区累积过多命令。

也可以根据主节点的数据量大小、主节点的写负载压力和主节点本身的内存大小来更合理的设置复制缓冲区的大小来避免溢出,此外,由于主节点会为每一个从节点设置一个复制缓冲区,如果集群中的从节点数非常多的话,主节点的内存开销就会非常大,因此我们应该尽量避免一个主节点有过多的从节点。

 

2、复制积压缓冲区

增量复制时,主节点和从节点进行常规同步时,会把写命令也暂存在复制积压缓冲区中。如果从节点和主节点间发生了网络断连,等从节点再次连接后,可以从复制积压缓冲区中同步尚未复制的命令操作。

需要注意的是复制积压缓冲区是一个大小有限的环形缓冲区。

当主节点把复制积压缓冲区写满后,会覆盖缓冲区中的旧命令数据。此时会造成主从节点的数据不一致。

针对这个问题,一般的应对的方法是调大复制积压缓冲区的大小,这个大小的计算方式一般可以使用

缓冲区大小=(主库写入命令速度 * 操作大小 - 主从库间网络传输命令速度 * 操作大小)* 2

如果如果并发请求量非常大,调整缓冲区大小的方式还不能解决,那么可以考虑使用切片集群的方式解决

 

四、AOF缓冲区

AOF缓冲区是Redis在AOF持久化的所设置的缓冲区,AOF缓冲区也有两种AOF缓冲区和AOF重写缓冲区。

1、AOF缓冲区

我们都知道,即使是固态硬盘,它的读写速度也是与内存的读写速度相差很多的。AOF缓冲区就主要是Redis用来解决主进程执行命令速度与磁盘写入速度不同步所设置的,通过AOF缓冲区可以有效地避免频繁对硬盘进行读写,进而提升性能。Redis在AOF持久化的时候,会先把命令写入到AOF缓冲区,然后通过回写策略来写入硬盘AOF文件。

AOF缓冲区的溢出可能与磁盘写入速度有关系,也可能与AOF回写策略有关系,当大量命令积压在AOF缓冲区,超过其设置阈值之后,就会导致缓冲区溢出,想要避免这个问题,我们可以通过调整回写策略,或者调整AOF缓冲区大小的方式来解决。

2、AOF重写缓冲区

AOF重写缓冲区是Redis在子进程进行AOF重写的时候,父进程接受了新的命令,此时会把命令写入AOF重写缓冲区,等到子进程重写完成后,把AOF重写缓冲区命令追加到新的AOF文件中。

AOF重写缓冲区的溢出与AOF重写期间主进程所处理的命令数有关系,当AOF重写期间Redis主进程处理了大量的命令,这些命令都会写入AOF重写缓冲区,当超过设定阈值之后,就会导致溢出。

避免AOF重写缓冲区的溢出我们也可以通过调整AOF重写缓冲区的大小来解决。

五、总结

这篇文章总结了缓冲区的概念,分析了Redis的三个缓冲区,以及可能造成其溢出的原因和解决办法。

对于缓冲区溢出其实主要有两种原因,一是缓冲区大小不够,二是消费者处理的速度太慢,而生产者生产的太快,导致大量内容积压在缓冲区,进而导致溢出。

而解决方案就可以通过调整缓冲区的大小,或者调整生产者与消费者之间生产与处理消息的速度,使其处于一个相对平衡的状态。

Redis缓冲区溢出及解决方案的更多相关文章

  1. 缓冲区溢出利用——捕获eip的傻瓜式指南

    [译文] 摘要:为一个简单的有漏洞程序写一个简单的缓冲区溢出EXP,聚焦于遇到的问题和关键性的教训,提供详细而彻底的描述 内容表:1. I pity the fool, who can't smash ...

  2. sprintf的缓冲区溢出

    sprintf的缓冲区溢出 分类: 技术2010-03-07 15:26 362人阅读 评论(0) 收藏 举报 今天,调试sector的时候遇到一个特奇怪的问题,程序会在取string的c_str() ...

  3. Redis高可用技术解决方案总结

    一.常见使用方式 Redis的几种常见使用方式包括: Redis单副本: Redis多副本(主从): Redis Sentinel(哨兵): Redis Cluster: Redis自研. 二.各种使 ...

  4. 【独家】终生受用的Redis高可用技术解决方案大全

    最近很多朋友向我咨询关于高可用的方案的优缺点以及如何选择合适的方案线上使用,刚好最近在给宜人贷,光大银行做企业内训的时候也详细讲过,这里我再整理发出来,供大家参考,如有不妥之处,欢迎批评指正,也欢迎推 ...

  5. [转]Redis学习---Redis高可用技术解决方案总结

    [原文]https://www.toutiao.com/i6591646189714670093/ 本文主要针对Redis常见的几种使用方式及其优缺点展开分析. 一.常见使用方式 Redis的几种常见 ...

  6. 缓冲区溢出基础实践(一)——shellcode 与 ret2libc

    最近结合软件安全课程上学习的理论知识和网络资料,对缓冲区溢出漏洞的简单原理和利用技巧进行了一定的了解.这里主要记录笔者通过简单的示例程序实现缓冲区溢出漏洞利用的步骤,按由简至繁的顺序,依次描述简单的 ...

  7. 使用Linux进行缓冲区溢出实验的配置记录

    在基础的软件安全实验中,缓冲区溢出是一个基础而又经典的问题.最基本的缓冲区溢出即通过合理的构造输入数据,使得输入数据量超过原始缓冲区的大小,从而覆盖数据输入缓冲区之外的数据,达到诸如修改函数返回地址等 ...

  8. 这可能是目前最全的Redis高可用技术解决方案总结

    本文主要针对 Redis 常见的几种使用方式及其优缺点展开分析. 一.常见使用方式 Redis 的几种常见使用方式包括: Redis 单副本: Redis 多副本(主从): Redis Sentine ...

  9. TP-Link TL-WR841N v14 CVE-2019-17147 缓冲区溢出漏洞分析笔记v2018.12.31

    0x00 背景 Httpd服务中的缓冲区溢出漏洞 复现参考文章https://www.4hou.com/posts/gQG9 Binwalk -Me 解压缩 File ./bin/busybox文件类 ...

  10. SEED信息安全实验系列:缓冲区溢出漏洞实验

    缓冲区溢出漏洞实验 本课程详细出自http://www.shiyanlou.com/courses/231,转载请注明出处. 一.实验描述 缓冲区溢出是指程序试图向缓冲区写入超出预分配固定长度数据的情 ...

随机推荐

  1. SpringBoot 快速开启事务(附常见坑点)

    序言:此前,我们主要通过XML配置Spring来托管事务.在SpringBoot则非常简单,只需在业务层添加事务注解(@Transactional )即可快速开启事务.虽然事务很简单,但对于数据方面是 ...

  2. 调试以及Linq查询

    1.调试的步骤 调试快捷键: F10逐过程(不会进入函数内部,直接获取函数运行结果) F11逐语句(会进入函数) F5执行,如果调试中多个断点,按F5执行到下一个断点 出现黄色箭头表示执行到这一句,但 ...

  3. tensorboard可视化详细

    tensorboard可视化详细 2019-09-06 tensorboard可视化的官方学习链接 1.tensorboard可视化的用途 首要的目的是记录tensorflow的Graph,tenso ...

  4. TiSpark 初级应用

    目前正在使用tispark 进行离线计算,简单记录一下操作过程 一.技术验证 场景:计算每次充电过程中单体最高电压的变化速率  解决方案:     使用tispark 直接访问tidb的数据,采用sp ...

  5. 在Win7的64位系统中安装最新版Eclipse或STS

    Eclipse版本为:eclipse-jee-2021-12-R-win32-x86_64 STS版本为:sts-4.13.1.RELEASE 这两个版本中都自带了17.0.1的jre插件,默认会使用 ...

  6. VS 2022创建ATL组件 (C++)

    https://www.cnblogs.com/chechen/p/8119018.html 步骤如下: 1.新建ATL项目 打开Visual Studio 2022 新建ATL项目 2.添加接口类. ...

  7. CentOS7更改阿里源

    阿里云yum源:1)备份当前yum源防止出现意外还可以还原回来cd /etc/yum.repos.d/cp /CentOS-Base.repo /CentOS-Base-repo.bak2)使用wge ...

  8. 自用nodejs安装笔记

    下载Nodejs 进入Nodejs官网https://nodejs.org/zh-cn/ 下载 安装Node.js 检查Nodejs和npm包管理器是否安装成功 用管理员打开cmd控制台 命令行输入n ...

  9. C#多线程开发-处理异步操作中的异常

    C#多线程开发-处理子线程中的异常 在平时的多线程开发中,对于异常的处理是至关重要的,千万不能马虎.如果在实际的项目中,对于某些线程中的异常没有处理,会直接导致整个程序崩溃,软件无法使用. 其中需要说 ...

  10. LinkedBlockingQueue出入队实现原理

    类图概述 由类图可以看出,L是单向链表实现的,有两个ReentrantLock实例用来控制元素入队和出队的原子性,takeLock用来控制只有一个线程可以从队头获取元素,putLock控制只有一个线程 ...