如何排查expire

如题所述

导读:本文将有助于你找出Redis 响应延迟的问题所在。如果你正在经历响应延迟问题,你或许能够根据应用程序的具体情况算出它的延迟响应时间。

关键词:Redis 数据库延迟 响应延迟

  本文将有助于你找出Redis 响应延迟的问题所在。

  文中出现的延迟(latency)均指从客户端发出一条命令到客户端接受到该命令的反馈所用的最长响应时间。Reids通常处理(命令的)时间非常的慢,大概在次微妙范围内,但也有更长的情况出现。

  计算延迟时间

  如果你正在经历响应延迟问题,你或许能够根据应用程序的具体情况算出它的延迟响应时间,或者你的延迟问题非常明显,宏观看来,一目了然。不管怎样吧,用redis-cli可以算出一台Redis 服务器的到底延迟了多少毫秒。踹这句:

 redis-cli --latency -h `host` -p `port`

  网络和通信引起的延迟

  当用户连接到Redis通过TCP/IP连接或Unix域连接,千兆网络的典型延迟大概200us,而Unix域socket可能低到30us。这完全基于你的网络和系统硬件。在通信本身之上,系统增加了更多的延迟(线程调度,CPU缓存,NUMA替换等等)。系统引起的延迟在虚拟机环境远远高于在物理机器环境。

  实际情况是即使Redis处理大多数命令在微秒之下,客户机和服务器之间的交互也必然消耗系统相关的延迟。一个高效的客户机因而试图通过捆绑多个命令在一起的方式减少交互的次数。服务器和大多数客户机支持这种方式。聚合命令象MSET/MGET也可以用作这个目的。从Redis 2.4版本起,很多命令对于所有的数据类型也支持可变参数。

  这里有一些指导:

如果你负担的起,尽可能的使用物理机而不是虚拟机来做服务器

不要经常的connect/disconnect与服务器的连接(尤其是对基于web的应用),尽可能的延长与服务器连接的时间。

如果你的客户端和服务器在同一台主机上,则使用Unix域套接字

尽量使用聚合命令(MSET/MGET)或可变参数命令而不是pipelining

如果可以尽量使用pipelining而不是序列的往返命令。

针对不适合使用原始pipelining的情况,如某个命令的结果是后续命令的输入,在以后的版本中redis提供了对服务器端的lua脚本的支持,实验分支版本现在已经可以使用了。

  在Linux上,你可以通过process placement(taskset)、cgroups、real-time priorities(chrt)、NUMA配置(numactl)或使用低延迟内核的方式来获取较低的延迟。请注意Redis 并不适合被绑到单个CPU核上。redis会在后台创建一些非常消耗CPU的进程,如bgsave和AOF重写,这些任务是绝对不能和主事件循环进程放在一个CPU核上的。大多数情况下上述的优化方法是不需要的,除非你确实需要并且你对优化方法很熟悉的情况下再使用上述方法。

  Redis的单线程属性

  Redis 使用了单线程的设计, 意味着单线程服务于所有的客户端请求,使用一种复用的技术。这种情况下redis可以在任何时候处理单个请求, 所以所有的请求是顺序处理的。这和Node.js的工作方式很像, 所有的产出通常不会有慢的感觉,因为处理单个请求的时间非常短,但是最重要的是这些产品被设计为非阻塞系统调用,比如从套接字中读取或写入数据。

  我提到过Redis从2.4版本后几乎是单线程的,我们使用线程在后台运行一些效率低下的I/O操作, 主要关系到硬盘I/O,但是这不改变Redis使用单线程处理所有请求的事实。

  低效操作产生的延迟

  单线程的一个结果是,当一个请求执行得很慢,其他的客户端调用就必须等待这个请求执行完毕。当执行GET、SET或者LPUSH 命令的时候这不是个问题,因为这些操作可在很短的常数时间内完成。然而,对于多个元素的操作,像SORT,LREM, SUNION 这些,做两个大数据集的交叉要花掉很长的时间。文档中提到了所有操作的算法复杂性。 在使用一个你不熟悉的命令之前系统的检查它会是一个好办法。

  如果你对延迟有要求,那么就不要执行涉及多个元素的慢操作,你可以使用Redis的replication功能,把这类慢操作全都放到replica上执行。可以用Redis 的Slow Log来监控慢操作。此外,你可以用你喜欢的进程监控程序(top, htop, prstat, 等...)来快速查看Redis进程的CPU使用率。如果traffic不高而CPU占用很高,八成说明有慢操作。

  延迟由fork产生

  Redis不论是为了在后台生成一个RDB文件,还是为了当AOF持久化方案被开启时重写Ap

  pend Only文件,都会在后台fork出一个进程。fork操作(在主线程中被执行)本身会引发延迟。在大多数的类unix操作系统中,fork是一个很消耗的操作,因为它牵涉到复制很多与进程相关的对象。而这对于分页表与虚拟内存机制关联的系统尤为明显。

  对于运行在一个linux/AMD64系统上的实例来说,内存会按照每页4KB的大小分页。为了实现虚拟地址到物理地址的转换,每一个进程将会存储一个分页表(树状形式表现),分页表将至少包含一个指向该进程地址空间的指针。所以一个空间大小为24GB的redis实例,需要的分页表大小为 24GB/4KB*8 = 48MB。当一个后台的save命令执行时,实例会启动新的线程去申请和拷贝48MB的内存空间。这将消耗一些时间和CPU资源,尤其是在虚拟机上申请和初始化大块内存空间时,消耗更加明显。

  在不同系统中的Fork时间

  除了Xen系统外,现代的硬件都可以快速完美的复制页表。Xen系统的问题不是特定的虚拟化,而是特定的Xen.例如使用VMware或者Virutal Box不会导致较慢的fork时间。下面的列表比较了不同Redis实例的fork时间。数据包含正在执行的BGSAVE,并通过INFO指令查看thelatest_fork_usecfiled。

Linux beefy VM on VMware 6.0GB RSS forked 77 微秒 (每GB 12.8 微秒 ).

Linux running on physical machine (Unknown HW) 6.1GB RSS forked 80 微秒(每GB 13.1微秒)

Linux running on physical machine (Xeon @ 2.27Ghz) 6.9GB RSS forked into 62 微秒 (每GB 9 微秒).

Linux VM on 6sync (KVM) 360 MB RSS forked in 8.2 微秒 (每GB 23.3 微秒).

Linux VM on EC2 (Xen) 6.1GB RSS forked in 1460 微秒 (每GB 239.3 微秒).

Linux VM on Linode (Xen) 0.9GBRSS forked into 382 微秒 (每GB 424 微秒).

  你能看到运行在Xen上的VM的Redis性能相差了一到两个数量级。我们相信这是Xen系统的一个验证问题,我们希望这个问题能尽快处理。

  swapping (操作系统分页)引起的延迟

  Linux (以及其他一些操作系统) 可以把内存页存储在硬盘上,反之也能将存储在硬盘上的内存页再加载进内存,这种机制使得内存能够得到更有效的利用。如果内存页被系统移到了swap文件里,而这个内存页中的数据恰好又被redis用到了(例如要访问某个存储在内存页中的key),系统就会暂停redis进程直到把需要的页数据重新加载进内存。这个操作因为牵涉到随机I/O,所以很慢,会导致无法预料的延迟。

  系统之所以要在内存和硬盘之间置换redis页数据主要因为以下三个原因:

系统总是要应对内存不足的压力,因为每个运行的进程都想申请更多的物理内存,而这些申请的内存的数量往往超过了实际拥有的内存。简单来说就是redis使用的内存总是比可用的内存数量更多。

redis实例的数据,或者部分数据可能就不会被客户端访问,所以系统可以把这部分闲置的数据置换到硬盘上。需要把所有数据都保存在内存中的情况是非常罕见的。

一些进程会产生大量的读写I/O。因为文件通常都有缓存,这往往会导致文件缓存不断增加,然后产生交换(swap)。请注意,redis RDB和AOF后台线程都会产生大量文件。

  所幸Linux提供了很好的工具来诊断这个问题,所以当延迟疑似是swap引起的,最简单的办法就是使用Linux提供的工具去确诊。

  首先要做的是检查swap到硬盘上的redis内存的数量,为实现这个目的要知道redis实例的进程id:

  $ redis-cli info | grep process_id
  process_id:5454

  进入进程目录:

  $ cd /proc/5454在这里你会发现一个名为smaps 的文件,它描述了redis进程的内存布局 (假定你使用的是Linux 2.6.16或者更新的版本)。这个文件包括了很多进程所使用内存的细节信息,其中有一项叫做Swap的正是我们所关心的。不过仅看这一项是不够的,因为smaps文件包括有redis进程的多个不同的的内存映射区域的使用情况(进程的内存布局远不是线性排列那么简单)。

  从我们对所有进程的内存交换情况感兴趣以来,我们首先要做的事情是使用grep命令显示进程的smaps文件

  $ cat smaps | grep 'Swap:'
  Swap: 0 kB
  Swap: 0 kB
  Swap: 0 kB
  Swap: 0 kB
  Swap: 0 kB
  Swap: 12 kB
  Swap: 156 kB
  Swap: 8 kB
  Swap: 0 kB
  Swap: 0 kB
  Swap: 0 kB
  Swap: 0 kB
  Swap: 0 kB
  Swap: 0 kB
  Swap: 0 kB
  Swap: 0 kB
  Swap: 0 kB
  Swap: 4 kB
  Swap: 0 kB
  Swap: 0 kB
  Swap: 4 kB
  Swap: 0 kB
  Swap: 0 kB
  Swap: 4 kB
  Swap: 4 kB
  Swap: 0 kB
  Swap: 0 kB
  Swap: 0 kB
  Swap: 0 kB

  Swap: 0 kB假如所有的数据显示为0kb或者某些数据偶尔显示为4kb,表示当前一切正常。实际上我们的例子是一个真实的运行着Redis并每秒为数百的用户提供服务的网站,会显示更多的交换页。为了研究是否存在一个严重的问题,我们改变命令打印出分配的内存尺寸

  $ cat smaps | egrep '^(Swap|Size)'
  Size: 316 kB
  Swap: 0 kB
  Size: 4 kB
  Swap: 0 kB
  Size: 8 kB
  Swap: 0 kB
  Size: 40 kB
  Swap: 0 kB
  Size: 132 kB
  Swap: 0 kB
  Size: 720896 kB
  Swap: 12 kB
  Size: 4096 kB
  Swap: 156 kB
  Size: 4096 kB
  Swap: 8 kB
  Size: 4096 kB
  Swap: 0 kB
  Size: 4 kB
  Swap: 0 kB
  Size: 1272 kB
  Swap: 0 kB
  Size: 8 kB
  Swap: 0 kB
  Size: 4 kB
  Swap: 0 kB
  Size: 16 kB
  Swap: 0 kB
  Size: 84 kB
  Swap: 0 kB
  Size: 4 kB
  Swap: 0 kB
  Size: 4 kB
  Swap: 0 kB
  Size: 8 kB
  Swap: 4 kB
  Size: 8 kB
  Swap: 0 kB
  Size: 4 kB
  Swap: 0 kB
  Size: 4 kB
  Swap: 4 kB
  Size: 144 kB
  Swap: 0 kB
  Size: 4 kB
  Swap: 0 kB
  Size: 4 kB
  Swap: 4 kB
  Size: 12 kB
  Swap: 4 kB
  Size: 108 kB
  Swap: 0 kB
  Size: 4 kB
  Swap: 0 kB
  Size: 4 kB
  Swap: 0 kB
  Size: 272 kB
  Swap: 0 kB
  Size: 4 kB
  Swap: 0 kB

  在输出信息中,你能看到有一个720896kb的内存分配(有12kb的交换)还有一个156kb的交换是另一个进程的。基本上我们的内存只会有很小的内存交换,因此不会产生任何的问题.

  假如进程的内存有相当部分花在了swap上,那么你的延迟可能就与swap有关。假如redis出现这种情况那么可以用vmstat 命令来验证一下猜测:

  $ vmstat 1
  procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
  r b swpd free buff cache si so bi bo in cs us sy id wa
  0 0 3980 697932 147180 1406456 0 0 2 2 2 0 4 4 91 0
  0 0 3980 697428 147180 1406580 0 0 0 0 19088 16104 9 6 84 0
  0 0 3980 697296 147180 1406616 0 0 0 28 18936 16193 7 6 87 0
  0 0 3980 697048 147180 1406640 0 0 0 0 18613 15987 6 6 88 0
  2 0 3980 696924 147180 1406656 0 0 0 0 18744 16299 6 5 88 0
  0 0 3980 697048 147180 1406688 0 0 0 4 18520 15974 6 6 88 0

  输出中我们最感兴趣的两行是si 和 so,这两行分别统计了从swap文件恢复到内存的数量和swap到文件的内存数量。如果在这两行发现了非0值那么就说明系统正在进行swap。

  最后,可以用iostat命令来查看系统的全局I/O行为。

  $ iostat -xk 1
  avg-cpu: %user %nice %system %iowait %steal %idle
  13.55 0.04 2.92 0.53 0.00 82.95
  Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await svctm %util
  sda 0.77 0.00 0.01 0.00 0.40 0.00 73.65 0.00 3.62 2.58 0.00
  sdb 1.27 4.75 0.82 3.54 38.00 32.32 32.19 0.11 24.80 4.24 1.85

  如果确认延迟是由于swap引起的,那么就需要减小系统的内存压力,要么给机器增加内存,要么不要在同一个机器上运行其他消耗内存的程序。

 转载,仅供参考,祝你愉快,满意请采纳。
温馨提示:内容为网友见解,仅供参考
无其他回答

如何排查expire
如果你正在经历响应延迟问题,你或许能够根据应用程序的具体情况算出它的延迟响应时间,或者你的延迟问题非常明显,宏观看来,一目了然。不管怎样吧,用redis-cli可以算出一台Redis 服务器的到底延迟了多少毫秒。踹这句: redis-cli --latency -h `host` -p `port` 网络和通信引起的延迟 当用户连接到Redis通过TCP\/...

xy烈焰登陆器为什么老出Expire?
首先,清理电脑缓存是一个有效的方法。您可以在浏览器设置中找到清理缓存的选项。通常,这需要您选择“清除浏览数据”的选项,并确保勾选“缓存和网站数据”。完成后,请关闭并重新打开网页,尝试再次登录游戏。如果清理缓存后问题仍然存在,您可以考虑更换浏览器。不同的浏览器可能对某些网站的支持程度不同...

订单失效了,第三方支付却推来了支付成功的消息,你遇到过吗?_百度知 ...
查看错误日志,果然找到了该订单已过期的信息,说明问题应该是问题2。找到订单相应的支付回调通知参数,果然找到第三方支付的成功通知。解决方案1 预支付时设置过期时间 微信支付订单过期参数: time_expire 支付宝支付订单过期参数:time_expire 温馨提示: 在排查时,看到同事写的支付代码里传了time_express...

运维排查篇 | Redis占用内存过高怎么办?
解决方法:在排查过程中发现,Redis 中的键过期时间设置过长,且未配置最大内存使用限制,内存回收策略为 noeviction。这导致了原先数据未过期,又有新的数据写入,内存使用量持续增加。解决此问题的方法是调整配置,设置最大内存使用限制和选择适当的内存回收策略。通过修改配置文件,可以限制 Redis 的最大...

Flink Checkpoint 问题排查实用指南
通过理解Checkpoint流程,我们可以针对不同异常情况采取针对性的排查,如Checkpoint Decline(包括Checkpoint Cancel)、Checkpoint Expire(超时失败)和Checkpoint慢的几个原因,如Source Trigger Checkpoint慢、增量Checkpoint使用、作业反压或数据倾斜、barrier对齐问题等。最后,作者建议在遇到问题时逐步定位和调整,...

Redis有哪些慢操作?
如果在慢日志中发现了SET\/DEL这种复杂度不高的命令,此时你就应该排查一下是否是由于写入bigkey导致的。「如何定位bigkey?」Redis提供了扫描bigkey的命令 可以看到命令的输入有如下3个部分 这个命令的原理就是redis在内部执行了scan命令,遍历实例中所有的key,然后正对key的类型,分别执行strlen,llen,...

为什么连着wifi,还是显示无法连接网络?
你的DNS设置出现问题 1:首先点击右下角的网络图标,打开"网络和Internet设置"2:在WLAN选项卡中,点击"更改适配器选项"3:右击你当前的网络设备,打开属性 4:打开IPv4协议 5:选中"自动获得DNS服务器地址"即可

Redisson解决Redis分布式锁提前释放问题
1、lock加锁操作@Overridepublic void lock() {try {lock(-1, null, false);} catch (InterruptedException e) {throw new IllegalStateException();}}\/\/ 租约期限, 也就是expire时间, -1代表未设置 将使用系统默认的30sprivate void lock(long leaseTime, TimeUnit unit, boolean interruptibly) throws ...

如何找出网关
当本地系统需要与远程主机建立连接时, 它会检查路由表以决定是否有已知的路径存在。如果远程主机属于一个我们已知如何到达 (克隆的路由) 的子网内,那么系统会检查看沿着那个接口是否能够连接。如果所有已知路径都失败,系统还有最后一个选择: “默认”路由。这个路由是特殊类型的网关路由 (通常只有一个...

MySQL出现重启问题解决方法分享mysql不能重启
一、检查MySQL配置 我们需要检查MySQL的配置文件是否正确,包括my.cnf文件和\/etc\/init.d\/mysql文件。排查这些文件中的错误、语法和拼写错误,以确保MySQL能够正常启动。my.cnf文件的位置一般为:\/etc\/my.cnf、\/etc\/mysql\/my.cnf 或 \/usr\/local\/mysql\/etc\/my.cnf。编辑my.cnf文件时需要注意以下几点:...

相似回答