Redis为了解决输出缓冲区消息大量堆积的隐患,设置了一些保护机制,主要采用两种限制措施:
大小限制,当某一客户端缓冲区超过设定值后直接关闭连接;
持续性限制,当某一客户端缓冲区持续一段时间占用过大空间时关闭连接。
通过CONFIG GET *查看,可以找到客户端输出缓冲区的默认配置:

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,也就是不限制。因为普通客户端通常采用阻塞式的消息应答模式,何谓阻塞式呢?如:发送请求,等待返回,再发送请求,再等待返回。这种模式下,通常不会导致Redis服务器输出缓冲区的堆积膨胀;
对于Pub/Sub客户端(也就是发布/订阅模式),大小限制是8M,当输出缓冲区超过8M时,会关闭连接。持续性限制是,当客户端缓冲区大小持续60秒超过2M,则关闭客户端连接;
对于slave客户端来说,大小限制是256M,持续性限制是当客户端缓冲区大小持续60秒超过64M,则关闭客户端连接。

如果数据量较大时,主从同步会有出现失败的问题,log里面报错:

Discarding previously cached master state.

从日志中我们可以看到在redis主库在接到从库要求重新同步数据的时候先生成一个rdb文件,再通过psync来做部分同步,可以看到问题就出在部分同步这一块,由于client-output-buffer-limit值设置太小,导致导数发送失败。失败后,从库继续发起数据同步的请求,但是每次都失败,redis主库反复地生成rdb文件,对主从同步是由影响的:
查看当前大小:

127.0.0.1:6385> config get client-output-buffer-limit 
1) "client-output-buffer-limit"
2) "normal 0 0 0 slave 268435456 67108864 60 pubsub 33554432 8388608 60"

可以看到,目前的限制是最大256M和60s内不超过64M,从我们上面日志信息可以看到psync的数据明显是大于256M的。我们进行如下设置把很限制调大:

config set client-output-buffer-limit 'slave 1073741824 268435456 300'

查看大小:

192.168.255.189:6380>  config get client-output-buffer-limit 
1) "client-output-buffer-limit"
2) "normal 0 0 0 slave 1073741824 268435456 300 pubsub 1073741824 134217728 300"

调完后再观察,发现从库的的复制状态很快就变成了up。
我们上面的调整是加大复制输出缓冲区,还有一个办法就是关闭复制输出缓冲区的限制:

config set client-output-buffer-limit 'slave 0 0 0'
config set client-output-buffer-limit 'pubsub 0 0 0'
config set client-output-buffer-limit 'replica 0 0 0'

最后重启redis服务,主从同步解决,也可以将配置写入redis配置文件中:

client-output-buffer-limit normal 0 0 0
client-output-buffer-limit replica 1024mb 256mb 300
client-output-buffer-limit pubsub 1024mb 128mb 300

扫描下面二维码,给我点动力吧~

微信

微信

支付宝

支付宝

带符号 * 的表示必填项