大家好,今天我们来学习一下如何确定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 需要把日志记录写回到磁盘后才能返回,时间较长。下面这张表展示了三种写回策略所执行的系统调用:

当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的写入策略是什么样的。

如果我们的业务方对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

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

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

 

Redis是不是真的变慢了?的更多相关文章

  1. Fundebug网站升级HTTP/2,真的变快了!

    作为新一代的HTTP协议,HTTP/2可以提高网站性能,优化用户体验,Fundebug也是时候升级HTTP/2了,虽然已经有点晚了. 升级HTTP/2是一件很简单的事情,改1行Nginx配置就好了,但 ...

  2. iOS11有哪些新功能?旧iPhone是否真的变慢了

    1. [iOS 11] iOS 11十大实用新功能简介 2.[iOS 11] iPhone二维码扫描,通过内建相机就可以完成! 3. iOS 11内建屏幕录制功能!再也不需要通过第三方应用录屏 4.  ...

  3. 腾讯T8纯手写66个微服务架构设计模式,全部学会真的“变强”了

    微服务的概念虽然直观易懂,但“细节是魔鬼”,微服务在实操落地的环节中存在诸多挑战.我们在为企业提供PaaS.人工智能.云原生平台等数字化转型解决方案时也发现,企业实现云原生,并充分利用PaaS能力的第 ...

  4. Redis为什么变慢了?透彻解读如何排查Redis性能问题

    Redis 作为优秀的内存数据库,其拥有非常高的性能,单个实例的 OPS 能够达到 10W 左右.但也正因此如此,当我们在使用 Redis 时,如果发现操作延迟变大的情况,就会与我们的预期不符. 你也 ...

  5. Redis变慢?深入浅出Redis性能诊断系列文章(一)

    (本文首发于"数据库架构师"公号,订阅"数据库架构师"公号,一起学习数据库技术)   Redis 作为一款业内使用率最高的内存数据库,其拥有非常高的性能,单节点 ...

  6. 你离高薪 offer 只差一个Redis入门,我是认真的

    说起来,可能有些小伙伴会不相信,我是第一次用 Redis,真的.因为公司小,业务量小,Redis 根本派不上用场.不过,最近打算把系统升级一下,顺带把当下时髦的技术入个门,"与时俱进&quo ...

  7. Redis 忽然变慢了如何排查并解决?

    Redis 通常是我们业务系统中一个重要的组件,比如:缓存.账号登录信息.排行榜等. 一旦 Redis 请求延迟增加,可能就会导致业务系统"雪崩". 我在单身红娘婚恋类型互联网公司 ...

  8. Redis变慢?深入浅出Redis性能诊断系列文章(二)

    (本文首发于"数据库架构师"公号,订阅"数据库架构师"公号,一起学习数据库技术) 本篇为Redis性能问题诊断系列的第二篇,本文主要从应用发起的典型命令使用上进 ...

  9. redis 学习指南

    一.介绍 Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.一个高性能的key-value数据库.并提供多种语言的API.说到Key-Value数据库NoSQL数 ...

随机推荐

  1. 我是怎么写 Git Commit message 的?

    目录 作用 用的什么规范? type scope subject body footer 参考文章 用的什么辅助工具? 作用 编写格式化的 commit message 能够大大提高代码的维护效率. ...

  2. keycloak~管理平台的查询bug与自定rest中文检索

    对于keycloak来说,它的管理平台在它的源码中的admin-client中,它会定义相关的rest接口规范:在我们使用keycloak管理平台时,其中有一个组的查询,在我们查询中文组时,它是不支持 ...

  3. 基于socket通信的javaDH通信实现

    基于socket通信的javaDH通信实现 https://files.cnblogs.com/files/blogs/692137/DH.rar

  4. maven与eclipse的集成

    由于篇幅问题,本文将不介绍maven的安装和配置. 一.maven的概念 Maven(翻译为"专家","内行")是跨平台的项目管理工具.主要服务于基于Java平 ...

  5. Redis和Memcached到底有什么区别?

    前言 我们都知道,Redis和Memcached都是内存数据库,它们的访问速度非常之快.但我们在开发过程中,这两个内存数据库,我们到底要如何选择呢?它们的优劣都有哪些?为什么现在看Redis要比Mem ...

  6. 单选按钮(radio)的取值和点击事件

    笔记走一波:获取单选按钮(radio)的选中值,以及它的点击事件的实现 首先要引入Jquery <script type="text/javascript" src=&quo ...

  7. Android hacking event 2017

    1.you can't find me, 老规矩先打开jeb,然后看下主活动, 发现又调用了mainthread类的startWrites方法,继续跟进去. 发现是新建了一个随机输入流的文件对象,然后 ...

  8. Helm Template初体验,方便管理多环境

    我最新最全的文章都在南瓜慢说 www.pkslow.com,文章更新也只在官网,欢迎大家来喝茶~~ 1 简介 Helm作为一个优秀的包管理器,这部分我们之前已经做了介绍,文章如下: 用Helm部署Ku ...

  9. 如何使用Meter-WebSocketSampler

    安装 JMeter-WebSocketSampler 下载最新的 JMeter-WebSocketSampler,如 JMeterWebSocketSamplers-1.2.1.jar. 下载地址:h ...

  10. java网络编程基础——TCP网络编程二

    1.半关闭的Socket 前面的服务器和客户端通信时总是以行为最小数据单位,但是在某些协议里,通信的数据单位可能是多行的,当出现多行数据时就 出现一个问题:Socket输出流如何表示输出数据已经结束. ...