删除数据缓冲区限制异常问题 ?
1、记录故障报错
1、删除数据有问题:
这个操作就是删除redis里面1w条数据。
公司业务系统通过excel表格删除1w条数据、大概删除300000字节(300k左右)、执行操作后、删除数据库成功、删除缓存失败、会导致redis部分缓存没有被删除、(诡异的是:这个删除失败问题、有时候存在、有时候不存在)
2、排查问题:
一顿Google和GPT排查问题发现:通过网络传输时候、套接字文件过大、导出传输不完整、套接字发送缓冲区的最大值受到限制、系统底层资源限制没有优化。
java-a机器配置:(配置不正常、限制有点小) 300k左右 > 212992(208k)
[root@iZ2zei4wx78lgr88khvwjbZ ~]# sysctl net.core.wmem_max
net.core.wmem_max = 212992
java-b机器配置:(配置是正常的)
[root@iZ25bzqcfd9Z ~]#sysctl net.core.wmem_max
net.core.wmem_max = 16777216
3、问题原因:
1、java服务是高可用的(两个节点、分别在两个不同服务器、一个配置是不正常的、会导致时而成功、时而失败)
2、主要原因就是系统资源受到了限制、java服务受到影响、导致业务层次出现问题。
2、deepseek给的问题解释:
-
问题现象与缓冲区的关系:
- 当删除1万条数据(约300KB)时,A机器
net.core.wmem_max=208KB的配置会导致数据包超过单次发送缓冲区上限。 - Redis的DEL命令虽然支持批量删除,但所有key会作为一个完整请求通过网络传输。如果总数据量超过发送缓冲区限制,可能会出现:
- 数据包被拆分成多个TCP分段(增加延迟和丢包风险)
- 部分数据因缓冲区满被丢弃
- 触发TCP流量控制导致超时
- 当删除1万条数据(约300KB)时,A机器
-
间歇性失败的原因:
- 当请求被路由到B机器(16MB缓冲区)时操作成功
- 当请求被路由到A机器(208KB缓冲区)时可能失败
- 高可用集群的负载均衡机制会导致请求在不同机器间跳转
-
Redis协议层面的验证:
下载
# 模拟1万条key的DEL命令大小 echo "DEL key1 key2 ... key10000" | wc -c如果结果接近300KB,则验证了你的判断。
-
解决方案建议:
-
紧急处理:
# 临时调大A机器发送缓冲区 sysctl -w net.core.wmem_max=16777216 -
永久修复:
在/etc/sysctl.conf中添加:net.core.wmem_max=16777216执行
sysctl -p生效 -
应用层优化:
- 分批执行DEL(每批500-1000个key)
- 使用UNLINK替代DEL(异步删除)
- 考虑使用SCAN+DEL的Lua脚本在服务端执行
-
-
其他可能性排查:
- 使用
netstat -s | grep -i "buffer"查看是否有缓冲区溢出统计 - 通过Redis慢查询日志确认大请求的处理情况
- 检查TCP重传率:
nstat -az | grep -i retrans
- 使用
3、优化操作系统资源限制参数
vim /etc/sysctl.conf
# Controls source route verification
net.ipv4.conf.default.rp_filter = 1
net.ipv4.ip_nonlocal_bind = 1
net.ipv4.ip_forward = 1
# Do not accept source routing
net.ipv4.conf.default.accept_source_route = 0
# Controls the System Request debugging functionality of the kernel
kernel.sysrq = 0
# Controls whether core dumps will append the PID to the core filename.
# Useful for debugging multi-threaded applications.
kernel.core_uses_pid = 1
# Controls the use of TCP syncookies
net.ipv4.tcp_syncookies = 1
# Disable netfilter on bridges.
net.bridge.bridge-nf-call-ip6tables = 0
net.bridge.bridge-nf-call-iptables = 0
net.bridge.bridge-nf-call-arptables = 0
# Controls the default maxmimum size of a mesage queue
kernel.msgmnb = 65536
# # Controls the maximum size of a message, in bytes
kernel.msgmax = 65536
# Controls the maximum shared segment size, in bytes
kernel.shmmax = 68719476736
# # Controls the maximum number of shared memory segments, in pages
kernel.shmall = 4294967296
# TCP kernel paramater
net.ipv4.tcp_mem = 786432 1048576 1572864
net.ipv4.tcp_rmem = 4096 87380 4194304
net.ipv4.tcp_wmem = 4096 16384 4194304
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_sack = 1
# socket buffer
net.core.wmem_default = 8388608
net.core.rmem_default = 8388608
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.netdev_max_backlog = 262144
net.core.somaxconn = 20480
net.core.optmem_max = 81920
# TCP conn
net.ipv4.tcp_max_syn_backlog = 262144
net.ipv4.tcp_syn_retries = 3
net.ipv4.tcp_retries1 = 3
net.ipv4.tcp_retries2 = 15
# tcp conn reuse
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 0
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_timestamps = 0
net.ipv4.tcp_max_tw_buckets = 20000
net.ipv4.tcp_max_orphans = 3276800
net.ipv4.tcp_synack_retries = 1
net.ipv4.tcp_syncookies = 1
# keepalive conn
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 3
net.ipv4.ip_local_port_range = 10001 65000
# swap
vm.overcommit_memory = 0
vm.swappiness = 10
#net.ipv4.conf.eth1.rp_filter = 0
#net.ipv4.conf.lo.arp_ignore = 1
#net.ipv4.conf.lo.arp_announce = 2
#net.ipv4.conf.all.arp_ignore = 1
#net.ipv4.conf.all.arp_announce = 2
net.ipv4.ip_forward=1
vm.max_map_count=262144
kernel.pid_max=4194303
fs.file-max=1000000
net.ipv4.tcp_max_tw_buckets=6000
net.netfilter.nf_conntrack_max=2097152
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
vm.swappiness=0
#生效命令
sysctl -p

浙公网安备 33010602011771号