Redis 怎么应对响应延迟

207 阅读3分钟

在应对响应延迟之前,首先要确定Redis是否真的变慢的。大部分时候,Redis的延迟都是很低的,如果某些时刻突然出现很高的延迟,时间达到几秒到几十秒,持续时间不长,这种情况叫延迟毛刺。

平常检测Redis变慢,我们需要确认当前环境的Redis基线性能。Redis2.8.7开始,redis-cli命令提供了--intrisic-latency监测和统计测试期间内的最大延迟作为Redis基线性能。

一般我们会使用120秒来持续采集,取最大延迟作为基本性能标准。如果你观察到Redis运行时延迟时基线性能的2倍及以上,就可以认定Redis变慢了。

./redis-cli --intrinsic-latency 120

本质上能影响Redis变慢的三大要素:操作特性、文件系统和操作系统。

应对自身操作特性的影响

1、慢查询

SORT、SUNION/SMEMBERS操作复杂度O(N+M*log(M))O(N)

  • 用其他高效命令代替 SSCAN多次迭代返回,避免一次返回数据大阻塞
  • 当需要排序、交集、并集时,可以在客户端完成,而不使用SORT、SUNION、SINTER命令,拖慢Redis
  • KEYS命令用SCAN命令替代

2、过期key操作

  • Redis采样ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP的默认值是20,表示20个key/100ms删除
  • 如果超过25%的key过期了,则重复删除过程,直到过期key的比例降到25%以下。

应该避免key值同时过期,可以在expireat和expire的过期参数上,加上一个一定大小范围内的随机值。

文件系统AOF

1、由于AOF的落盘策略有三种always、everysec、no

always不会使用后台子线程来执行,而是每次操作都落盘 everysec则使用后台子线程每秒执行一次fsync操作 no则被落盘的flush操作交给操作系统控制

AOF同理在磁盘压力比较大的时候,fsync操作会阻塞,fsync操作虽然由后台子线程执行,但主线程会监控fsync执行的进度。你可以理解为Java的future机制,调用主线程调用get同样会阻塞。后台子线程虽然是异步的,新命令在主线程执行,如果子线程的fsync迟迟没有执行完,主线程也会阻塞。

如果业务应用对延迟非常敏感,但同时允许一定量的数据丢失。你可以把 no-appendfsync-on-rewrite 设置为yes。 这样主线程就不会关心fsync操作的结果,继而给实例带来阻塞。如果既要高可靠又要高性能则需要采用SSD磁盘来解决。

2、Linux Swap机制

Redis是内存数据库,内存操作非常频繁,操作系统的内存机制直接影响到Redis的处理效率。在Redis内存不否用的时候,操作系统会启用Swap机制,把内存数据和磁盘的数据交互,拖慢Redis。一般我们会关闭Swap机制,或针对物理机的内存作监控报警。

同时可以增加机器的内存,或考虑使用Redis集群

查询Redis是否出发了Swap机制

redis-cli info | grep process_id
cd /proc/5332
cat smaps | egrep '^(Swap|Size)'

内存大页

Linux内存大页机制(Transparent Huge Page)THP。Linux2.6.38支持了该机制,支持2MB大小的内存页分配,通常内存页的分配是按照4KB的粒度来执行的。 一般Redis实例要关闭这个特性。always表示开启,never表示关闭。

cat /sys/kernel/mm/transparent_hugepage/enabled
echo never /sys/kernel/mm/transparent_hugepage/enabled