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

Redis集群延迟到底为啥?那些坑和怎么破你得知道

Redis集群用起来爽,但有时候延迟一高,真是让人头疼,延迟说白了就是你的命令发出去,到收到回复这个时间变长了,这背后原因很多,有些是使用不当自己挖的坑,有些是集群本身的特点,咱们一个个来说。

网络问题:最容易被忽略的“马路”

你可以把Redis集群的节点想象成几个分布在城市不同地方的仓库,网络就是连接这些仓库的马路,延迟高,首先得看看是不是马路堵了。

  • 带宽不够:这是最常见的原因之一,如果你的应用服务器和Redis集群之间网络带宽本身就小,或者你突然间有大量数据要读写(比如搞活动秒杀),数据包就得在马路上排队,延迟自然就上去了,这就好比双车道突然涌入了上百辆车,不堵才怪。(来源:普遍性运维经验)
  • 节点间通信开销:Redis集群节点之间需要不停地“打电话”来同步信息、检测彼此是否还活着(故障转移),如果网络本身质量差,比如有丢包或者延迟本身就高,这些内部通信就会变慢,节点可能会误以为另一个节点挂了,从而触发不必要的故障转移,这个过程会引发短暂的不可用和高延迟。(来源:Redis官方文档关于集群总线的部分)

怎么破?

Redis集群延迟到底为啥?那些坑和怎么破你得知道

  1. 监控网络:定期用 ping 命令看看应用服务器到Redis各节点的延迟是否稳定,如果可能,使用网络监控工具查看是否有丢包。
  2. 升级带宽:如果业务量增长,带宽成了瓶颈,该升级就得升级。
  3. 保证网络质量:尽量让客户端和Redis集群在同一个机房或者同一个云服务商的可用区内,减少物理距离带来的延迟。

慢查询:一个慢,个个等

Redis是单线程模型的(指处理命令的核心模块),就像一个只有一个收银员的超市,如果一个顾客买了整整一购物车的东西,要求收银员一件件扫码算钱,后面的人就只能干等着,慢查询就是这个“磨蹭的顾客”。

  • 哪些操作是慢查询?
    • *`keys ` 命令**:这个命令会遍历所有键,在生产环境是绝对禁止的,键一多,整个Redis就卡死了。
    • 一次性获取大集合的所有元素:比如对一个存了几万成员的Set使用 SMEMBERS 命令。
    • 使用不当的 SORT 命令
    • 写入一个非常大的Value:比如一个Value有好几MB,不仅传输慢,序列化/反序列化也耗时间,还可能引发更严重的问题。

怎么破?

Redis集群延迟到底为啥?那些坑和怎么破你得知道

  1. 使用 slowlog 命令:Redis提供了慢查询日志,你可以设置一个时间阈值(比如10毫秒),超过这个时间的命令都会被记录下来,定期检查慢日志,找到罪魁祸首,命令是 SLOWLOG GET [数量]。(来源:Redis官方文档关于SLOWLOG的部分)
  2. 避免使用危险命令:用 SCAN 系列命令替代 keys;大集合分批获取;控制单个Value的大小,建议不要超过10KB。
  3. 优化数据结构:有时候不需要存整个大对象,可以拆分成多个Key-Value。

持久化带来的“停顿”

为了保证数据不丢,Redis需要把数据从内存写到硬盘上,这个过程叫持久化,但写硬盘比写内存慢得多,所以持久化操作可能会引起延迟毛刺(突然的延迟高峰)。

  • RDB快照:当执行BGSAVE生成RDB快照时,Redis会fork一个子进程来做这件事,fork操作本身,在数据量大的时候,可能会因为复制父进程的内存页表而短暂阻塞主进程(尤其是在虚拟机上),虽然子进程在后台干活不影响主进程,但fork的那一刻可能会有感觉。(来源:Redis持久化文档)
  • AOF重写:和RDB类似,也会fork子进程,如果AOF的刷盘策略设置为 always(每个命令都刷盘),延迟会非常高,一般不建议使用,通常用 everysec(每秒刷一次)折中。

怎么破?

Redis集群延迟到底为啥?那些坑和怎么破你得知道

  1. 规划持久化时机:尽量不要在业务高峰时段触发持久化,可以配置RDB快照在凌晨低峰期进行。
  2. 选择合适的持久化策略:根据业务对数据丢失的容忍度,选择RDB、AOF或两者结合,大多数场景下,everysec 是个不错的选择。
  3. 警惕机器内存不足:如果机器内存所剩无几,fork进程时可能因为需要交换内存(swap)而导致严重延迟甚至服务崩溃。

Redis集群特有的坑

  • 跨槽位访问:Redis集群把数据分到16384个槽位里,如果你的客户端不支持集群模式(比如用了普通的Jedis而不是JedisCluster),或者你用了需要操作多个Key的命令(比如跨节点的Set交集 SINTER),但这些Key又没有存储在同一个节点上(即没有使用相同的hash tag),那么命令就会失败或者效率极低,因为需要跨节点通信。(来源:Redis集群规范)
  • 数据倾斜:如果大量数据都集中在了某一个或某几个节点上,导致这些节点压力巨大,而其他节点很闲,这个热点节点就会成为整个集群的瓶颈,延迟全集中在这里了,这可能是因为hash tag使用不当,或者某些Key本身就是热点。

怎么破?

  1. 使用智能客户端:确保你的客户端是支持Redis集群协议的,它能帮你缓存槽位映射,直接把命令发到正确的节点。
  2. 谨慎使用多Key命令:在集群中尽量避免使用跨Key的命令,如果非要用,确保这些Key通过 {user1000}.profile{user1000}.account 这样的hash tag强制分配到同一个节点。
  3. 监控节点负载:观察每个节点的内存、CPU和网络流量,及时发现热点节点,从业务上分析原因并调整。

系统资源瓶颈

Redis是内存数据库,它对CPU不敏感,但对内存和磁盘I/O非常敏感。

  • 内存不足触发Swap:这是最致命的情况之一,当物理内存不够用时,操作系统会把内存中不常用的数据换到硬盘的Swap分区,硬盘的速度比内存慢几个数量级,一旦发生Swap,Redis的性能会急剧下降,延迟飙升。
  • CPU竞争:虽然Redis自己不吃太多CPU,但如果Redis进程和其他非常消耗CPU的进程(比如Java应用、数据库)跑在同一台机器上,它们会争抢CPU时间片,也可能导致Redis处理命令变慢。

怎么破?

  1. 给Redis留足内存:确保机器的可用物理内存远大于Redis最大使用内存,绝对要避免使用Swap,可以通过 redis-cli info memory 命令查看内存使用情况。
  2. 隔离部署:尽量让Redis服务器独享一台机器,或者只与I/O需求不高的服务部署在一起。

排查Redis集群延迟,就像一个老中医看病,要望闻问切,先从最简单的网络、慢查询查起,再看持久化、集群配置,最后检查系统资源,平时做好监控,把这些坑都提前填平,你的Redis集群才能跑得又快又稳。