Redis常见延迟问题怎么解决

使用复杂度高的命令

如果在使用Redis时,发现访问延迟突然增大,如何进行排查?

首先,第一步,建议你去查看一下Redis的慢日志。通过Redis的慢日志命令统计功能,我们可以设置以下选项来查看哪些命令在执行时产生了较大的延迟。

首先设置Redis的慢日志阈值,只有超过阈值的命令才会被记录,这里的单位是微妙,例如设置慢日志的阈值为5毫秒,同时设置只保留最近1000条慢日志记录:

# 命令执行超过5毫秒记录慢日志
CONFIG SET slowlog-log-slower-than 5000
# 只保留最近1000条慢日志
CONFIG SET slowlog-max-len 1000

Redis常见延迟问题及解决方案

设置完成之后,所有执行的命令如果延迟大于5毫秒,都会被Redis记录下来,我们执行SLOWLOG get 5查询最近5条慢日志:

127.0.0.1:6379>
SLOWLOG get 5
1) 1) (integer) 32693 # 慢日志ID
2) (integer) 1593763337 # 执行时间
3) (integer) 5299 # 执行耗时(微妙)
4) 1) "
LRANGE"
# 具体执行的命令和参数
2) "
user_list_2000"

3) "
0"

4) "
-1"

2) 1) (integer) 32692
2) (integer) 1593763337
3) (integer) 5044
4) 1) "
GET"

2) "
book_price_1000"

...

通过查看慢日志记录,我们就可以知道在什么时间执行哪些命令比较耗时,如果你的业务经常使用O(N)以上复杂度的命令,例如sort、sunion、zunionstore、keys、scan,或者在执行O(N)命令时操作的数据量比较大,这些情况下Redis处理数据时就会很耗时。

如果Redis实例的CPU使用率很高,但你的服务请求量并不大,很可能是因为使用了具有高复杂度的命令所导致的。

解决方案就是,不使用这些复杂度较高的命令,并且一次不要获取太多的数据,每次尽量操作少量的数据,让Redis可以及时处理返回。

存储bigkey

如果查询慢日志发现,并不是复杂度较高的命令导致的,例如都是SET、DELETE操作出现在慢日志记录中,那么你就要怀疑是否存在Redis写入了bigkey的情况。

当Redis写入新数据时,会为其分配内存空间,而当数据被从Redis中删除时,相应的内存空间也会被释放。

当一个键写入的数据非常大时,Redis分配内存也会变得更加耗时。同样的,当删除这个key的数据时,释放内存也会耗时比较久。

你需要检查你的业务代码,是否存在写入bigkey的情况,需要评估写入数据量的大小,业务层应该避免一个key存入过大的数据量。

针对bigkey的问题,Redis官方在4.0版本推出了lazy-free的机制,用于异步释放bigkey的内存,降低对Redis性能的影响。即使这样,我们也不建议使用bigkey,bigkey在集群的迁移过程中,也会影响到迁移的性能,这个后面在介绍集群相关的文章时,会再详细介绍到。

集中过期

有时你会发现,平时在使用Redis时没有延时比较大的情况,但在某个时间点突然出现一波延时,而且报慢的时间点很有规律,例如某个整点,或者间隔多久就会发生一次。

如果出现这种情况,就需要考虑是否存在大量key集中过期的情况。

如果有大量的key在某个固定时间点集中过期,在这个时间点访问Redis时,就有可能导致延迟增加。

Redis的过期策略采用定期删除+惰性删除两种策略;

注意,Redis的定期删除的定时任务,也是在Redis主线程中执行的,也就是说如果在执行主动过期的过程中,出现了需要大量删除过期key的情况,那么在业务访问时,必须等这个过期任务执行结束,才可以处理业务请求。此时就会出现,业务访问延时增大的问题,最大延迟为25毫秒。

而且这个访问延迟的情况,不会记录在慢日志里。慢日志中只记录真正执行某个命令的耗时,Redis主动过期策略执行在操作命令之前,如果操作命令耗时达不到慢日志阈值,它是不会计算在慢日志统计中的,但我们的业务却感到了延迟增大。

解决方案是,在集中过期时增加一个随机时间,把这些需要过期的key的时间打散即可。

实例内存达到上限

有时我们把Redis当做纯缓存使用,就会给实例设置一个内存上限maxmemory,然后开启LRU淘汰策略。

当实例的内存达到了maxmemory后,你会发现之后的每次写入新的数据,有可能变慢了。

导致变慢的原因是,当Redis内存达到maxmemory后,每次写入新的数据之前,必须先踢出一部分数据,让内存维持在maxmemory之下。

这个踢出旧数据的逻辑也是需要消耗时间的,而具体耗时的长短,要取决于配置的淘汰策略

fork耗时严重

如果你的Redis开启了自动生成RDB和AOF重写功能,那么有可能在后台生成RDB和AOF重写时导致Redis的访问延迟增大,而等这些任务执行完毕后,延迟情况消失。

遇到这种情况,一般就是执行生成RDB和AOF重写任务导致的。

生成RDB和AOF都需要父进程fork出一个子进程进行数据的持久化,在fork执行过程中,父进程需要拷贝内存页表给子进程,如果整个实例内存占用很大,那么需要拷贝的内存页表会比较耗时,此过程会消耗大量的CPU资源,在完成fork之前,整个实例会被阻塞住,无法处理任何请求,如果此时CPU资源紧张,那么fork的时间会更长,甚至达到秒级。这会严重影响Redis的性能。

绑定CPU

很多时候,我们在部署服务时,为了提高性能,降低程序在使用多个CPU时上下文切换的性能损耗,一般会采用进程绑定CPU的操作。

但在使用Redis时,我们不建议这么干,原因如下。

绑定CPU的Redis,在进行数据持久化时,fork出的子进程,子进程会继承父进程的CPU使用偏好,而此时子进程会消耗大量的CPU资源进行数据持久化,子进程会与主进程发生CPU争抢,这也会导致主进程的CPU资源不足访问延迟增大。

所以在部署Redis进程时,如果需要开启RDB和AOF重写机制,一定不能进行CPU绑定操作

使用Swap

如果你发现Redis突然变得非常慢,每次访问的耗时都达到了几百毫秒甚至秒级,那此时就检查Redis是否使用到了Swap,这种情况下Redis基本上已经无法提供高性能的服务。

我们知道,操作系统提供了Swap机制,目的是为了当内存不足时,可以把一部分内存中的数据换到磁盘上,以达到对内存使用的缓冲。

但当内存中的数据被换到磁盘上后,访问这些数据就需要从磁盘中读取,这个速度要比内存慢太多!

尤其是针对Redis这种高性能的内存数据库来说,如果Redis中的内存被换到磁盘上,对于Redis这种性能极其敏感的数据库,这个操作时间是无法接受的。可以临时关闭操作系统Swap

网卡负载过高

特点就是从某个时间点之后就开始变慢,并且一直持续。此时,你需要检查一下机器的网卡流量是否存在被耗尽的情况。

高网络负载会导致在网络层和TCP层级上出现数据发送延迟和数据丢失等问题。除了内存之外,Redis之所以具有高性能,是因为其网络IO表现出色。然而,随着请求量不断增加,网卡负载也会相应地增加。

如果出现这种情况,你需要排查这个机器上的哪个Redis实例的流量过大占满了网络带宽,然后确认流量突增是否属于业务正常情况,如果属于那就需要及时扩容或迁移实例,避免这个机器的其他实例受到影响。



Redis是一款高性能的键值对数据库,被广泛运用于各种互联网应用中。然而在某些情况下,Redis会出现延迟的现象,影响着系统的稳定性和性能。本文将介绍Redis常见的延迟问题以及相应的解决方案。
一、Redis延迟问题的原因
在Redis中,常见的延迟问题主要是由以下几个方面导致的:
1. 内存不足:当Redis使用的内存达到最大限制时,系统会使用操作系统的虚拟内存,这会导致Redis的操作变得缓慢。
2. 大量的写操作:Redis可能会出现延迟,尤其是在大量的写操作下。当Redis执行写操作时,会触发内存回收机制,从而导致系统延迟。
3. 网络延迟:Redis客户端与服务端之间的网络连接可能出现延迟,而这会导致客户端在请求服务端时等待超时。
二、Redis延迟问题的解决方案
1. 内存管理
为了避免Redis因为内存不足而出现延迟,我们可以通过以下措施来管理Redis的内存:
1.1 先适当降低maxmemory限制,让Redis更易存活。
1.2 使用Redis提供的内存管理命令monitor来了解Redis内存状况,避免Redis内存使用过高。
1.3 当Redis内存使用量超过了maxmemory限制,可以考虑使用Redis的缓存清理策略和数据抵消节约更多的内存。
2. 写操作优化
为了避免Redis因为大量写操作而出现延迟,我们可以通过以下方式来优化写操作:
2.1 优化Redis写操作的频率,尽量将多个写请求合并到一个命令中。
2.2 启用Redis的内存回收机制,避免Redis因为内存不足而出现延迟。
2.3 使用Redis的异步操作模式,将写操作改为异步方式,从而减少延迟。
3. 网络连接优化
为了解决Redis客户端与服务端之间的网络延迟,我们可以采取以下几个策略:
3.1 使用Redis批处理功能,将多个请求合并成一个请求,从而减少客户端与服务端之间的网络交互。
3.2 使用Redis的pipeline命令,将多个请求打包发送到Redis,从而减少客户端与服务端之间的网络延迟。
3.3 将Redis与客户端之间的网络连接优化,使用更好的网络设备和优化TCP包来提高网络通信速度。
总结
Redis作为一款高性能的键值对数据库,在应用中被广泛使用。但是,在使用Redis时,延迟问题是难以避免的。本文介绍了Redis常见的延迟问题以及相应的解决方案,希望能够帮助读者更好地理解Redis,提高Redis应用系统的性能和稳定性。