当前位置:首页 > 问答 > 正文

Redis读数据到底耗时多少,实际用起来感觉和理论差别挺大

综合自多位开发者的技术博客分享、社区论坛讨论如知乎和Stack Overflow上的相关问答、以及部分公司内部的技术复盘文档)

“Redis读数据到底耗时多少,实际用起来感觉和理论差别挺大”这个事,确实是很多刚开始用或者用过一段时间的开发者经常碰到的一个困惑,理论文档上都说Redis是微秒级别的响应,快得不得了,但真用起来,有时候会感觉没那么快,甚至偶尔会‘卡’一下,这中间的差距主要来自哪里呢?我们来具体聊聊。

Redis读数据到底耗时多少,实际用起来感觉和理论差别挺大

理论上的那个微秒级延迟,比如官方说的大概在100微秒左右,这个数字是在一个近乎完美的理想环境下测出来的,这个环境大概是啥样呢?根据一些性能测试报告的描述,它得跑在本机,也就是客户端和Redis服务器在同一台物理机器上,网络延迟基本为零;用的还是回环地址;Redis实例独占CPU资源,没有其他任何进程干扰;操作的数据结构非常简单,比如就读写一个很小的字符串;而且此时Redis本身的内存和CPU压力都极低,这种条件在实际的生产环境里几乎不存在,这个理论值更像是一个性能上限的标尺,告诉你这个工具潜力有多大,但不能直接当成日常表现的承诺。

那实际用起来感觉慢,差别大,问题通常出在以下几个地方:

Redis读数据到底耗时多少,实际用起来感觉和理论差别挺大

第一个大头,也是最常见的问题,就是网络,只要你的客户端和Redis服务器不是在同一台机器上,哪怕它们都在同一个机房,网络来回的时间就成了延迟的主要部分,这个时间单位是毫秒,比Redis内部处理数据的微秒时间高了一个数量级,根据一些云服务商提供的网络延迟数据,同可用区内网延迟一般在0.1ms到0.5ms(也就是100到500微秒)之间,这已经比Redis本身处理数据的时间长好几倍了,如果跨了机房甚至跨地域,那延迟就可能飙升到几十毫秒,这时候感觉‘卡’就非常正常了,网络本身的波动、带宽被打满、防火墙规则复杂等,都会进一步加剧这个问题。

第二个是Redis服务器本身的状态,理论测试是空载的Redis,但你的生产环境Redis可能正忙得不可开交,如果Redis的CPU使用率很高,它就不能及时响应你的读取命令,就像一家餐厅,厨师就一个人,平时炒一个菜很快,但赶上饭点,订单堆成山,你点的简单小炒也得排队等,如果Redis占用的内存接近或超过机器物理内存,操作系统会开始进行内存交换,把部分数据换到硬盘上,硬盘的速度和内存比慢了成千上万倍,一旦发生交换,延迟就会急剧上升,出现明显的卡顿,有开发者在问题排查记录里提到,他们就是因为机器内存不足触发交换,导致Redis的响应时间从亚毫秒级直接掉到了几百毫秒。

Redis读数据到底耗时多少,实际用起来感觉和理论差别挺大

第三个是命令和使用方式的问题,理论测试用的是最简单的GETSET命令,但如果你不经意间用了一个KEYS *这样的命令,当Key数量巨大时,这个命令会阻塞Redis,导致所有后续命令都得等着,感觉就是整个服务卡住了,或者你频繁地连接、断开Redis,每次建立连接都有开销,不如使用连接池复用连接来得高效,还有,读取一个很小的字符串和读取一个非常大的Hash结构,或者执行一个复杂的Lua脚本,耗时肯定是不一样的,有团队在技术复盘里写道,他们发现某个查询接口慢,追查下去是某个Redis操作返回了一个序列化后体积达几十KB的大对象,网络传输和客户端反序列化都花了很长时间。

第四个是客户端的问题,有时候延迟不是服务器造成的,而是出在客户端,客户端所在的机器负载也很高,CPU忙不过来,处理接收到的Redis响应慢了,或者客户端使用的驱动库效率不高,序列化、反序列化数据慢,再或者,就像前面说的,没有用连接池,每个请求都新建连接,开销巨大。

感觉和理论差别大,是很正常的,要缩小这个差距,关键不在于怀疑Redis本身,而在于排查上述这些实际环境中的因素,常用的方法是使用Redis自带的SLOWLOG命令来查看哪些命令执行得慢,或者使用更专业的监控工具来观察服务器和网络的各项指标,有运维工程师分享经验,他们通过监控发现某个时间段延迟飙升,最终定位到是机房网络抖动造成的,还有的团队通过将大Value拆分成小Value、避免使用阻塞命令、将Redis实例升级到配置更高的服务器等措施,显著改善了读取数据的响应速度。

Redis读数据的理论耗时是一个理想的基准,而实际体验是理论性能减去网络损耗、减去服务器负载、减去不当使用的开销之后的结果,觉得慢的时候,多从这些实际环节去找原因,往往就能找到答案。”