问题发现,莫名其妙的暂停
最近因为工作原因,给一个数据库写了一个redis代理,将redis请求转换成该数据库的请求,然后丢到数据库去。
该数据库本身在我的虚拟机上跑,读写性能应该在2k ops的样子。
然后神奇的事情出现了,我开始跑redis-benchmark工具,不开启redis pipeline功能,ops大概在1.7k,一旦开启pipeline,以3个请求一个pipeline丢请求过去,ops一下下降到了70上下。难道我针对pipeline做的处理出问题了?
于是启动wireshark,抓了一下包,看tcp流,数据都是对的。但是看请求时间,确实一秒只做了70个请求上下。那就很有意思了。这个时候,只能仔细观察数据包,看看延迟具体是多少了。于是我就注意到了以下这个包:

可以看到,从36.86s到35.91s之间,传输莫名其妙停止了40ms。我仔细确认了暂停传输前后的包,传输顺序如下:
- 客户端向代理发起请求,请求包括三个set请求
- 服务器端返回一个set的响应,ok,同时附带对刚才请求的ack
- 停顿40ms
- 客户端发送了一个ack
- 服务器返回两个set的响应,即两个ok。
如此循环。
注意到中间停顿了40ms,我就有点好奇,检查了服务器的日志,三个请求的write api调用间隔并没有超过3ms。所以看起来不像是我的代码问题,那就只能是tcp协议的问题了。
那么到底为什么呢?可以看

在实现数据库redis代理时,发现开启pipeline功能后,性能从1.7k ops骤降至70 ops。通过wireshark抓包分析,发现在TCP层存在40ms的莫名暂停。研究发现,这是Nagle算法与延迟ACK策略相互作用的结果。服务器等待ACK,客户端延迟40ms发送ACK,导致传输阻塞。解决方法在于调整TCP设置,避免此类性能下降。
最低0.47元/天 解锁文章
1831

被折叠的 条评论
为什么被折叠?



