ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

Redis是不是真的变慢了?

2021-08-12 15:02:31  阅读:267  来源: 互联网

标签:AOF latency 变慢 Redis 是不是 内存 microseconds


大家好,今天我们来学习一下如何确定Redis是不是真的变慢了。

我们在使用redis时一定会遇到变慢的时候,那我们如何来判断Redis是否真的变慢了呢, 一个最直接的方法就是查看Redis的响应延迟,一般情况下,Redis延迟很低,但是在某些时刻, Redis实例会出现比较高的响应延迟,甚至能达到几秒到十几秒,当你发现Redis命令的执行时间突然就增长到了几秒,基本就可以认定 Redis 变慢了。这种方法是看 Redis 延迟的绝对值。当我们不能根据延迟的绝对值来判断redis是否真的变慢了,我们还有一种方法可以判断,那就是redis的基线性能。

redis从2.8.7版本开始,redis-cli命令提供了–-intrinsic-latency 选项,可以用来监测和统计测试期间内的最大延迟,这个延迟可以作为 Redis 的基线性能。其中,测试时长可以用–-intrinsic-latency 选项的参数来指定。比如我们执行redis-cli –-intrinsic-latency 30这个命令,该命令会打印出30秒内检测到的最大延迟。如下所示,这里的最大延迟是3595微妙,所以我们把该redis实例的基线性能是3595微妙。

./redis-cli –-intrinsic-latency 30

Max latency so far: 1 microseconds.
Max latency so far: 4 microseconds.
Max latency so far: 14 microseconds.
Max latency so far: 33 microseconds.
Max latency so far: 48 microseconds.
Max latency so far: 51 microseconds.
Max latency so far: 100 microseconds.
Max latency so far: 110 microseconds.
Max latency so far: 488 microseconds.
Max latency so far: 944 microseconds.
Max latency so far: 1590 microseconds.
Max latency so far: 1921 microseconds.
Max latency so far: 3595 microseconds.

584098163 total runs (avg latency: 0.0514 microseconds / 51.36 nanoseconds per run).
Worst run took 69994x longer than the average latency.

    一般来说,当你观察到Redis运行时延迟是其基线性能的2倍及以上,就可以认定 Redis 变慢了。在确定Redis变慢之后,我们需要去进一步去排查Redis变慢的原因。

    我们不能没有章法的去排查redis是如何变慢的,我们需要基于自己对Redis本身的工作原理的理解, 并且结合和它交互的操作系统、存储以及网络等外部系统关键机制,再借助一些辅助工具来定位原因,并制定有效的解决方案。 影响Redis性能的三大要素是Redis自身的操作特性、文件系统和操作系统。下面我们来分别看一下。

Redis自身操作特性的影响:

下面我们重点介绍两个常见的操作,这两个操作是经常导致redis变慢的罪魁祸首。

1.慢查询命令

当redis变慢时,我们可以通过日志或者latency monitor工具来查看Redis中查询变慢的请求,然后根据请求对应的具体命令以及官方文档,确认下是否采用了复杂度高的慢查询命令。如果的确有大量的慢查询命令,有两种处理方式:

  1. 用其它高效命令代替。
  2. 当你需要执行排序、交集、并集操作时,可以在客户端完成,而不要用 SORT、SUNION、SINTER 这些命令,以免拖慢 Redis 实例。

2.过期key操作

我们可以对edis的键值对设置过期时间。默认情况下,Redis每100毫秒会删除一些过期key,具体的算法如下:

  1. 采样ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP 个数的 key,并将其中过期的 key 全部删除;

  2. 如果超过 25% 的 key 过期了,则重复删除的过程,直到过期 key 的比例降至 25% 以下。

    如果我们同一时间有大量过期的key要删除,就会触发第二条策略,Redis 就会一直删除以释放内存空间。注意,删除操作是阻塞的(Redis 4.0 后可以用异步线程机制来减少阻塞影响)。所以,一旦该条件触发,Redis 的线程就会一直执行删除,这样一来,就没办法正常服务其他的键值操作了,就会进一步引起其他键值操作的延迟增加,Redis 就会变慢。所以我们需要避免给一批key设置相同的过期时间,

如果业务上确实需要一批key同时过期,我们可以在EXPIREAT 和 EXPIRE 的过期时间参数上 加上一个一定大小范围内的随机数,这样,既可以保证key 在一个邻近时间范围内被删除,又避免了同时过期造成的压力。

文件系统:AOF日志

Redis会采用AOF日志或者RDB来保证数据的可靠性。其中AOF日志提供了三种日志写回策略: no、everysec、always。这三种写回策略依赖文件系统的两个系统调用,也就是write和fsync。write 只要把日志记录写到内核缓冲区,就可以返回了,并不需要等待日志实际写回到磁盘;而fsync 需要把日志记录写回到磁盘后才能返回,时间较长。下面这张表展示了三种写回策略所执行的系统调用:

image.png

当AOF配置成everysec时,Redis允许丢失一秒的操作记录,所以Redis主线程不需要确保每个操作记录日志都写回到磁盘。所以,当配置为everysec时,Redis是使用后台的子线程异步完成fsync的操作。当AOF配置成always时,Redis需要确保每个操作记录日志都写回磁盘,如果采用后台子线程异步完成,主线程就无法及时地知道每个操作是否已经完成了。这就不符合 always 策略的要求了。所以,always 策略并不使用后台子线程来执行。

我们在这里知道,Redis持久化机制在使用 AOF 日志时,为了避免日AOF志文件变得太大,Redis 会采用后台子进程来进行AOF重写。但是,这里会出现一个风险点,AOF重写会对磁盘进行大量的IO操作,同时fsync需要等到数据写入到磁盘后才会返回。所以,当AOF重新操作磁盘压力比较大时,就会导致fsync被阻塞。尽管fsync是由后台子线程负责执行的,但是,主线程会监控fsync的执行进度。当主线程使用后台子线程执行了一次 fsync,需要再次把新接收的操作记录写回磁盘时,如果主线程发现上一次的 fsync 还没有执行完,那么它就会阻塞。所以,如果后台子线程执行的 fsync 频繁阻塞的话主线程也会阻塞,导致 Redis 性能变慢。

到目前为止,你已经知道了,当AOF重写导致磁盘压力大时,就会导致fsync阻塞,进而阻塞主线程 ,导致延迟增加。下面我们来看如何排查和解决这个问题。首先,我们可以先检查配置文件中的 appendfsync配置项,查看AOF的写入策略是什么样的。

image.png

如果我们的业务方对Redis的延迟很敏感,但是可以允许有一定数据的数据丢失,我们可以设置no-appendfsync-on-rewrite为yes

no-appendfsync-on-rewrite yes

这个配置项设置为 yes 时,表示在 AOF 重写时,不进行 fsync 操作。也就是说,Redis 实例把写命令写到内存后,不调用后台线程进行 fsync 操作,就可以直接返回了。当然,如果此时实例发生宕机,就会导致数据丢失。反之,如果这个配置项设置为 no(默认配置),在 AOF 重写时,Redis 实例仍然会调用后台线程进行 fsync 操作,这就会给实例带来阻塞。如果业务方既需要低延迟也需要高可靠性,我们可以采用固态硬盘作为AOF日志的写入设备。

操作系统:

1.内存swap。

内存 swap 是操作系统里将内存数据在内存和磁盘间来回换入和换出的机制,会涉及到磁盘的读写,所以,一旦触发 swap,其性能都会受到慢速磁盘读写的影响。

Redis是内存数据库,如果没有控制好内存的使用量,就可能会引起操作系统的swap。一旦swap被触发了,Redis的读写操作就会有可能请求到磁盘,从而影响Redis的主线程执行,所以会增大Redis的响应时间。

操作系统触发swap机制,主要是因为物理机的内存不足导致的,所以,当发现操作系统进行了内存swap,最直接的处理方式就是增加物理机的内存大小。

2.内存大页机制。

我们先来看看什么是内存大页?我们都知道,应用程序向操作系统申请内存时,是按内存页进行申请的,而常规的内存页大小是 4KB。Linux 内核从 2.6.38 开始,支持了内存大页机制,该机制允许应用程序以 2MB 大小为单位,向操作系统申请内存。 我们在Redis持久化机制里知道,Redis的持久化是采用写时复制的,也就是说,一旦有数据要被修改,Redis 并不会直接修改内存中的数据,而是将这些数据拷贝一份,然后再进行修改。

如果采用了内存大页,那么,即使客户端请求只修改 1kb 的数据,Redis 也需要拷贝 2MB 的大页。相反,如果是常规内存页机制,只用拷贝 4KB。两者相比,你可以看到,当客户端请求修改或新写入数据较多时,内存大页机制将导致大量的拷贝,这就会影响 Redis 正常的访存操作,最终导致性能变慢。解决这个问题的方式,就是关闭大页机制。

我们在linux执行

cat /sys/kernel/mm/transparent_hugepage/enabled

如果是always,就表明启动了内存大页机制,我们执行

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

来关闭内存大页机制就好了。

 

今天的分享就到这里。更多硬核知识,请关注公众号“程序员学长”。

 

 

 



标签:AOF,latency,变慢,Redis,是不是,内存,microseconds
来源: https://www.cnblogs.com/laohanshuibi/p/15132731.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有