大家好,今天我们来学习一下如何确定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. Linux中cut,sort,uniq和wc的用法

    一.cut是一个选取命令,就是将一段数据经过分析,取出我们想要的.一般来说,选取信息通常是针对"行"来进行分析的,并不是整篇信息分析的.1.语法格式为:cut [-bn] [fil ...

  2. 7.1、controller节点配置

    0.配置openstack版本yum源: yum install centos-release-openstack-rocky 1.安装 OpenStack 客户端: yum install pyth ...

  3. 4、git和gitlab的配置(2)

    4.10.使用 gitlib 模拟开发流程: 1.项目经理指定开发计划: project01 需求 开发者 完成日期 v1.0 首页 dev01 4.28 支付 dev02 4.30 2.rpm(项目 ...

  4. 广州小公司:List集合你是熟悉的,对吧?

    <对线面试官>系列目前已经连载27篇啦!有深度风趣的系列! [对线面试官]Java注解 [对线面试官]Java泛型 [对线面试官] Java NIO [对线面试官]Java反射 & ...

  5. SpringBoot Cache 入门

    首先搭载开发环境,不会的可以参考笔者之前的文章SpringBoot入门 添加依赖 <dependency> <groupId>org.springframework.boot& ...

  6. yum安装GitLab-v11.11.8(git私服)

    GitLab 是一个用于仓库管理系统的开源项目,使用Git作为代码管理工具,并在此基础上搭建起来的web服务.(跟github.gitee类似) 1. 安装依赖软件 $ yum -y install ...

  7. java:编写jar包加密工具,防止反编译

    懒人方案 网盘: 链接:https://pan.baidu.com/s/1x4OB1IF2HZGgtLhd1Kr_AQ提取码:glx7 网盘内是已生成可用工具,下载可以直接使用,使用前看一下READ. ...

  8. 保存TextBox中的文字为Path功能

    保存TextBox中的文字为Path功能 今天再设计一个我自己程序的Icon时使用了Path+textbox做了图形,我不想导出为PNG,因为颜色比较单一,我又想通过代码控制颜色,所以我想完整的保存为 ...

  9. mongodb的基本命令与常规操作

    1. 查看当前数据库的版本号:db.version()2. 查看当前所在数据库:db 默认是test数据库3. 查看当前数据库的连接地址:db.getMongo()4. 查看所有数据库:show da ...

  10. 「CF576D」 Flights for Regular Customers

    「CF576D」 Flights for Regular Customers 对不起我又想网络流去了 你看这长得多像啊,走过至少多少条边就是流量下界,然后没上界 但是这个题求的最少走多少条边啊...完 ...