Redis被广泛使用的一个很重要的原因是它的高性能。因此我们必要要重视所有可能影响Redis性能的因素、机制以及应对方案。影响Redis性能的五大方面的潜在因素,分别是:
Redis内部的阻塞式操作
CPU核和NUMA架构的影响
Redis关键系统配置
Redis内存碎片
Redis缓冲区
这一讲,我们来学习一下Redis缓冲区的相关知识。
缓冲区的功能是用一块内存来暂存命令数据,避免出现因为数据和命令的处理速度慢于发送速度而导致的数据丢失和性能问题。但缓冲区的内存空间有限,如果发生溢出,就会丢失数据。
Redis缓冲区有两个应用场景:
在客户端和服务器端之间进行通信时,用来暂存客户端发送的命令数据,或者是服务器端返回给客户端的数据结果;
主从节点间进行数据同步时,用来暂存主节点接收的写命令和数据。
客户端输入和输出缓冲区 如何应对输入缓冲区溢出可能导致溢出的情况有两种:写入了bigkey;服务器端处理请求的速度过慢。
如何查看输入缓冲区的内存使用情况:使用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
cmd,表示客户端最新执行的命令;
qbuf,表示输入缓冲区已经使用的大小;
qbuf-free,表示输入缓冲区尚未使用的大小;
客户端输入缓冲区大小=qubf+qbuf-free。
如何避免输入缓冲区溢出:一是把缓冲区调大;二是从数据命令的发送和处理速度入手。
首先,输入缓冲区不能通过参数调整,在代码里设置客户端输入缓冲区大小上限阈值为1GB。
其次,避免客户端写入bigkey。
如何应对输出缓冲区溢出可能导致溢出的情况有三种:
服务器端返回bigkey的大量结果;
执行了MONITOR命令;
缓冲区大小设置得不合理。
首先,避免bigkey操作返回大量数据结果,可以使用SCAN命令。
其次,避免在线上环境中持续使用MONITOR命令。。MONITOR命令是用来监测Redis执行的。执行后,会持续输出监测到各个命令操作。MONITOR的输出结果会持续占用输出缓冲区,越占越大,最后发生溢出。MONITOR命令主要用在调试环境中,不要在线上生产环境中持续使用MONITOR。
最后,使用client-output-buffer-limit设置合理的缓冲区大小上限,或是缓冲区连续写入时间和写入量上限:
设置缓冲区大小的上限阈值;
设置输出缓冲区持续写入数据的数量上限阈值,和持续写入数据的时间的上限阈值。
按照客户端类型不同,设置也不同:
普通客户端:client-output-buffer-limit normal 0 0 0。通常把普通客户端的缓冲区大小限制,以及持续写入量限制、持续写入时间限制都设置为0,也就是不做限制;
订阅客户端:client-output-buffer-limit pubsub 8mb 2mb 60;
从节点客户端:在介绍主从集群中的缓冲区时再具体说明。
主从集群中的缓冲区主从集群间的数据复制包括全量复制和增量复制。无论哪种复制,都会用到缓冲区。
复制缓冲区的溢出问题全量复制时,从节点接收和加载RDB慢,同时主节点接收到大量的写命令,复制缓冲区越积越多,最后导致溢出。一旦发生溢出,主节点会关闭从节点的连接,导致全量复制失败。
如何避免复制缓冲区发生溢出首先,控制主节点保存的数据量大小,通常控制在2~4GB。
其次,通过client-output-buffer-limit配置项来设置合理的复制缓冲区大小:
config set client-output-buffer-limit slave 512mb 128mb 60
在实际应用中设置复制缓冲区的大小时,可以根据写命令数据的大小和应用的实际负载情况来估计缓冲区中累积的写命令数据量。然后再和所设置的复制缓冲区大小进行比较,判断设置的缓冲区大小是否足够支撑累积的写命令数据量。
关于复制缓冲区的问题,因为复制缓冲区是在主节点上的,如果集群中的从节点非常多,主节点的内存开销就会非常大。所以,必须得控制和主节点连接的从节点个数。
复制积压缓冲区的溢出问题增量复制时使用的缓冲区称为复制积压缓冲区。在基础篇第6讲中已经学过复制积压缓冲区了,叫repl_backlog_buffer。
首先,复制积压缓冲区是一个大小有限的环形缓冲区。当写入速度比读取速度要快,会导致溢出。主节点会关闭和从节点的连接,要重新进行同步。
为了应对复制积压缓冲区的溢出问题,可以调用复制积压缓冲区的大小,通过设置repl_backlog_size这个参数值。
总结按缓冲区的用途分为:
客户端的输入和输出缓冲区;
主从集群中主节点上的复制缓冲区和复制积压缓冲区。
从缓冲区溢出对Redis的影响分类:
缓冲区溢出导致网络连接关闭;
缓冲区溢出导致命令数据丢失。
缓冲区溢出的原因及解决方案:
命令数据发送过快过大。普通客户端避免使用bigkey,复制缓冲区避免过大的RDB文件;
命令数据处理较慢。减少Redis主线程上的阻塞操作,例如使用异步的删除操作;
缓冲区空间过小。使用clinet-output-buffer-limit配置项设置合理的输出缓冲区、复制缓冲区和复制积压缓冲区大小。
参考资料21 | 缓冲区:一个可能引发“惨案”的地方