Redis教程(十二)缓冲区详细说明
一、Redis缓冲区介绍
Redis通过缓冲区机制把事务存放于提前申请好的内存空间中,尽量避免Redis因为处理事务的效率 < 产生事务的速度导致数据积压,最后发生数据丢失的问题。但是随着缓冲区使用增多,Redis需要的内存也就越来越多,一旦耗尽了机器可用内存就会导致 Redis 发生OOM。Redis缓冲区应用场景有三个:暂存客户端发送的命令数据、暂存服务器端返回给客户端的数据结果以及主从节点间进行数据同步时,用来暂存主节点接收的写命令和数据。这三种场景对应了客户端输入输出缓冲区、主从复制缓冲区以及订阅缓冲区,因为事务通常集中在客户端输入输出缓冲区和主从复制缓冲区,所以很容易因为这二者的配置导致线上异常。
· 输入缓冲区(无参数调整):用于存放客户端发送过来的指令,Redis 主线程再从输入缓冲区中读取命令。该参数在Redis源码中设定为1G(无法直接修改),也就是说允许每个客户端暂存1GB的命令和数据。通常导致输入缓冲区溢出的主要原因是bigkey或Redis主线程阻塞导致无法及时处理其它请求,如果要避免输入缓冲区溢出就只能从数据命令的发送和处理速度入手,避免写入大量bigkey以及Redis主线程阻塞
#关注qbuf和qbuf-free的值,如果有客户端qbuf的值接近qbuf-free,代表缓冲区快没资源了。如果客户端继续写入就会被关闭 #如果大量客户端存在这种情况会导致 Redis 内存占用过大,导致内存溢出(out-of-memory),引起Redis 崩溃 redis > client list
· 输出缓冲区(client-output-buffer-limit):当 Redis 主线程处理完数据后会把结果写入到输出缓冲区,再通过输出缓冲区返回给客户端。输出缓冲区分为普通客户端(normal)、从库客户端(slave)、订阅客户端(pubsub)三类。如果存放的数据超过了限制,就会发生缓存溢出,可能导致溢出的原因主要有服务器端返回bigkey数据、持续monitor、缓冲区大小设置不合理三种情况。
#第1个0设置的是缓冲区大小限制,第2个0和第3个0分别表示缓冲区持续写入量和持续写入时间的组合限制,比如64m 60代表60秒内持续写入数据达到64M client-output-buffer-limit normal 0 0 0 client-output-buffer-limit slave 256m 64m 60 #缓冲区大小为256MB,如果持续60秒写入了64M也会触发缓冲区溢出,导致全量复制失败 client-output-buffer-limit pubsub 0 0 0 #假设client-output-buffer-limit slave 128m 64m 60 那么上限只能使用128m的内存,如果每个命令写入1k数据,128m/1k/60s=2133条命令每秒,也就是写入的QPS最多只能到达2000左右
二、Redis缓冲区故障案例
Redis为主从复制架构,但是服务在异常重启后发现主从关系一直无法正常建立
· 查看主库日志,发现主库有频繁进行bgsave的行为,并且每一次bgsave的过程会中断
· 查看从库日志,可以看到一直在循环"全量复制---中断---全量复制"
· 主从集群间的数据复制包括全量复制和增量复制两种。全量复制是同步当前主库上所有数据到从库,增量复制通常是主从网络中断后主库收到的命令进行同步,它们都会用到缓冲区。为了解决上类问题,一是可以控制主节点实例大小,比如将主节点数据量控制在2~4GB,这样全量同步的过程就不会太长,避免复制缓冲区累积过多命令。二是通过client-output-buffer-limit 配置项调大复制缓冲区大小。需要注意主节点的复制缓冲区内存开销是针对每一个从库的,如果有多个从节点同时发起主从同步,很容易造成OOM,因此需要控制从节点的数量,尤其是集群重启时
redis> config set client-output-buffer-limit "normal 0 0 0 slave 5073741824 2073435456 120 pubsub 33554432 8388608 60" redis> config rewrite
评论