诊断延迟问题
查找响应缓慢的原因
Redis 堆栈 | Redis 社区版 |
---|
本文档将帮助您了解如果您 遇到 Redis 的延迟问题。
在此上下文中,latency 是客户端 发出命令,并且 客户。通常 Redis 处理时间非常短,在亚微秒内 范围,但在某些情况下会导致更高的延迟数据。
我时间不多,给我清单
以下文档对于在 一种低延迟的方式。但是我知道我们是忙碌的人,所以 让我们从一个快速清单开始。如果您未能按照这些步骤作,请 返回此处阅读完整文档。
- 确保您没有运行阻止服务器的慢速命令。使用 Redis 慢日志功能来检查这一点。
- 对于 EC2 用户,请确保使用基于 HVM 的现代 EC2 实例,例如 m3.medium。否则 fork() 太慢。
- 必须在内核中禁用透明大页面。用
echo never > /sys/kernel/mm/transparent_hugepage/enabled
以禁用它们,然后重新启动 Redis 进程。 - 如果您使用的是虚拟机,则可能存在与 Redis 无关的固有延迟。使用
./redis-cli --intrinsic-latency 100
.注意:您需要在服务器中运行此命令,而不是在客户端中运行此命令。 - 启用并使用 Redis 的延迟监控功能,以便获得 Redis 实例中延迟事件和原因的可读描述。
通常,请使用下表进行持久性与延迟/性能的权衡,从更高的安全性到更好的延迟排序。
- AOF + fsync always:这很慢,只有在你知道自己在做什么的情况下才应该使用它。
- AOF + fsync per second:这是一个很好的折衷方案。
- AOF + fsync every second + no-appendfsync-on-rewrite 选项设置为 yes:这与上面一样,但避免在重写期间使用 fsync 以降低磁盘压力。
- AOF + fsync 从不。在此设置中,Fsyncing 取决于内核,甚至更小的磁盘压力和延迟峰值的风险。
- RDB 的在这里,您需要根据配置的保存触发器进行大量权衡。
现在,对于有 15 分钟时间的人来说,细节......
测量延迟
如果您遇到延迟问题,您可能知道如何测量 它在您的应用程序的上下文中,或者您的延迟问题非常 即使在宏观上也很明显。但是,redis-cli 可用于测量 Redis 服务器的延迟(以毫秒为单位),只需尝试:
redis-cli --latency -h `host` -p `port`
使用内部 Redis 延迟监控子系统
从 Redis 2.8.13 开始,Redis 提供了延迟监控功能,该功能 能够对不同的执行路径进行采样,以了解 服务器正在阻塞。这使得调试 此文档要简单得多,因此我们建议启用延迟监控 尽快。请参阅 Latency monitor 文档。
虽然延迟监控采样和报告功能将使 了解 Redis 系统中的延迟来源更简单,它仍然是 建议您广泛阅读本文档以更好地理解 Redis 和延迟峰值的主题。
延迟基线
有一种延迟本质上是环境的一部分,其中 您运行 Redis,即您的作系统内核提供的延迟 如果您使用的是虚拟化,则由您正在使用的虚拟机管理程序提供。
虽然无法消除这种延迟,但研究它很重要,因为 它是基准,或者换句话说,您将无法实现 Redis 延迟,这比在 环境将因内核或虚拟机监控程序实现而体验 或 setup。
我们将这种延迟称为 intrinic latency,并且redis-cli
开始
从 Redis 版本 2.8.7 开始能够测量它。这是一个示例运行
在 Linux 3.11.0 下,在入门级服务器上运行。
注意:参数100
是执行测试的秒数。
我们运行测试的时间越多,我们就越有可能发现
延迟峰值。100 秒通常是合适的,但您可能希望
在不同时间执行几次运行。请注意,测试是 CPU
intensive 的,并且可能会使系统中的单个内核饱和。
$ ./redis-cli --intrinsic-latency 100
Max latency so far: 1 microseconds.
Max latency so far: 16 microseconds.
Max latency so far: 50 microseconds.
Max latency so far: 53 microseconds.
Max latency so far: 83 microseconds.
Max latency so far: 115 microseconds.
注意:在这种特殊情况下,redis-cli 需要在运行或计划运行 Redis 的服务器中运行,而不是在客户端中运行。在这种特殊模式下,redis-cli 根本不连接到 Redis 服务器:它只会尝试测量内核不提供 CPU 时间来运行到 redis-cli 进程本身的最长时间。
在上面的例子中,系统的固有延迟仅为 0.115 毫秒(或 115 微秒),这是一个好消息,但请记住 固有延迟可能会随时间而变化,具体取决于 系统。
虚拟化环境不会显示那么好的数字,尤其是在 load 或如果有嘈杂的邻居。以下是在 Linode 4096 上运行的 运行 Redis 和 Apache 的实例:
$ ./redis-cli --intrinsic-latency 100
Max latency so far: 573 microseconds.
Max latency so far: 695 microseconds.
Max latency so far: 919 microseconds.
Max latency so far: 1606 microseconds.
Max latency so far: 3191 microseconds.
Max latency so far: 9243 microseconds.
Max latency so far: 9671 microseconds.
这里我们的固有延迟为 9.7 毫秒:这意味着我们不能向 Redis 提出比这更好的要求。但是,其他运行在不同时间、不同的虚拟化环境中具有更高的负载或嘈杂的邻居很容易显示更差的值。我们能够在 40 毫秒内测量 否则系统显然运行正常。
网络和通信引起的延迟
客户端使用 TCP/IP 连接或 Unix 域连接连接到 Redis。 1 Gbit/s 网络的典型延迟约为 200 us,而延迟 使用 Unix 域套接字可以低至 30 us。这实际上取决于你的 网络和系统硬件。除了通信本身之外,系统 增加了一些延迟(由于线程调度、CPU 缓存、NUMA 放置、 等等......系统引起的延迟在虚拟化的 环境比在物理机上更重要。
结果是,即使 Redis 在亚微秒内处理大多数命令 range,则执行多次往返服务器的客户端将不得不支付 对于这些与网络和系统相关的延迟。
因此,高效的客户端将尝试通过以下方式限制往返次数 将多个命令一起流水线。服务器完全支持这一点 和大多数客户。MSET/MGET 等聚合命令也可用于 那个目的。从 Redis 2.4 开始,许多命令还支持 所有数据类型的可变参数。
以下是一些准则:
- 如果您负担得起,请首选物理机而不是 VM 来托管服务器。
- 不要系统地连接/断开与服务器的连接(尤其是 对于基于 Web 的应用程序)。尽可能延长您的连接寿命。
- 如果您的 Client 端与服务器位于同一主机上,请使用 Unix 域套接字。
- 更喜欢使用聚合命令 (MSET/MGET) 或带有可变参数的命令 参数(如果可能)通过管道。
- 更喜欢使用 pipelining (如果可能) 而不是 sequence of roundtrips。
- Redis 支持 Lua 服务器端脚本来覆盖不合适的情况 对于原始流水线(例如,当命令的结果是 以下命令)。
在 Linux 上,有些人可以通过玩 process 来获得更好的延迟
放置 (taskset)、cgroups、实时优先级 (chrt)、NUMA
配置 (numactl) 或使用低延迟内核。请注意
原版 Redis 并不适合绑定到单个 CPU 核心上。
Redis 可以分叉可能非常消耗 CPU 的后台任务
喜欢BGSAVE
或BGREWRITEAOF
.这些任务绝不能在同一内核上运行
作为 main event 循环。
在大多数情况下,不需要这种系统级优化。 仅在需要时执行它们,并且您熟悉它们。
Redis 的单线程特性
Redis 主要使用单线程设计。这意味着单个进程 使用一种称为多路复用的技术为所有客户端请求提供服务。 这意味着 Redis 可以在每个给定的时刻提供单个请求,因此 所有请求都按顺序提供。这与 Node.js 也有效。然而,这两种产品通常都不被认为是缓慢的。 这部分是由于完成单个请求的时间很短。 但主要是因为这些产品旨在不阻止系统调用, 例如,从 socket 读取数据或将数据写入 socket。
我说 Redis 大部分是单线程的,因为实际上从 Redis 2.4 开始 我们在 Redis 中使用线程,以便在 背景,主要与磁盘 I/O 有关,但这并不能改变事实 Redis 使用单个线程为所有请求提供服务。
慢速命令产生的延迟
单线程的结果是,当请求提供速度较慢时
所有其他客户端将等待此请求得到处理。执行
普通命令,如GET
或SET
或LPUSH
这不是问题
完全没有,因为这些命令是在恒定(且非常小)的时间内执行的。
但是,有一些命令可以作用于许多元素,例如SORT
,LREM
,SUNION
和其他。例如,取两个大集合的交集
可能需要相当长的时间。
记录了所有命令的算法复杂性。良好的做法 是在使用您不熟悉的命令时系统地检查它。
如果您有延迟问题,则不应对 值,或者您应该使用 Redis 运行副本 复制,您可以在其中运行所有慢速查询。
可以使用 Redis 慢速日志功能监控慢速命令。
此外,您可以使用您最喜欢的每进程监控程序 (top、htop、prstat 等......快速检查 主 Redis 进程。如果它很高而流量不高,则通常为 使用慢速命令的标志。
重要提示:执行产生的非常常见的延迟来源
的慢速命令是使用KEYS
命令。KEYS
,如 Redis 文档中所述,应仅用于
调试目的。从 Redis 2.8 开始,引入了一个新命令,以便
增量迭代 Key Space 和其他大型集合,请检查
这SCAN
,SSCAN
,HSCAN
和ZSCAN
命令了解更多信息。
fork 产生的延迟
为了在后台生成 RDB 文件,或者在启用 AOF 持久性的情况下重写 Append Only File,Redis 必须对后台进程进行分叉。 fork作(在主线程中运行)本身可能会导致延迟。
在大多数类 Unix 系统上,分叉是一项昂贵的作,因为它涉及 复制大量链接到进程的对象。这一点尤其 true 表示与虚拟内存机制关联的页表。
例如,在 Linux/AMD64 系统上,内存被划分为 4 kB 页面。 为了将虚拟地址转换为物理地址,每个进程都会存储 至少包含一个指针的页表 (实际上表示为树) 进程地址空间的每页。因此,一个大型 24 GB 的 Redis 实例 需要 24 GB / 4 kB * 8 = 48 MB 的页表。
执行后台保存时,必须分叉此实例, 这将涉及分配和复制 48 MB 的内存。这需要时间 和 CPU,尤其是在 ALLOCATION 和 INITIALIZATION 大内存块的开销可能很大。
不同系统中的分叉时间
现代硬件在复制页表方面非常快,但 Xen 不是。
Xen 的问题不在于虚拟化,而在于 Xen 。例如,使用 VMware 或 Virtual Box 不会导致分叉时间变慢。
下表比较了不同 Redis 实例的 fork 时间
大小。通过执行 BGSAVE 获取数据并查看latest_fork_usec
在INFO
命令输出。
然而,好消息是,基于 EC2 HVM 的新型实例很多 分叉时间更好,几乎与物理服务器相当,例如: 使用 m3.medium(或更好)实例将提供良好的结果。
- VMware 上的 Linux 强大 VM 6.0GB RSS 在 77 毫秒内分叉(每 GB 12.8 毫秒)。
- 在物理机上运行的 Linux(未知硬件)6.1GB RSS 在 80 毫秒内分叉(每 GB 13.1 毫秒)
- 在物理机 (Xeon @ 2.27Ghz) 上运行的 Linux 6.9GB RSS 分叉为 62 毫秒(每 GB 9 毫秒)。
- 6sync (KVM) 上的 Linux VM 360 MB RSS 分叉时间为 8.2 毫秒(每 GB 23.3 毫秒)。
- EC2 上的 Linux VM,旧实例类型 (Xen) 6.1GB RSS 在 1460 毫秒(每 GB 239.3 毫秒)内分叉。
- EC2 上的 Linux VM,新实例类型 (Xen) 1GB RSS 在 10 毫秒内分叉(每 GB 10 毫秒)。
- Linode (Xen) 0.9GBRSS 上的 Linux VM 分叉为 382 毫秒(每 GB 424 毫秒)。
如您所见,在 Xen 上运行的某些 VM 的性能影响在 1 个数量级到 2 个数量级之间。对于 EC2 用户,建议很简单:使用基于 HVM 的现代实例。
透明大页面引起的延迟
不幸的是,当 Linux 内核启用了透明的大页面时,Redis
在fork
call 用于
persist on disk (保留在磁盘上)。大页面是导致以下问题的原因:
- Fork 时,将创建两个具有共享大页面的进程。
- 在繁忙的实例中,一些事件循环运行将导致命令以几千个页面为目标,从而导致几乎整个进程内存的写入时复制。
- 这将导致较大的延迟和较大的内存使用量。
确保使用以下命令禁用透明大页面:
echo never > /sys/kernel/mm/transparent_hugepage/enabled
交换引起的延迟(作系统分页)
Linux(和许多其他现代作系统)能够重新定位内存 页面从内存到磁盘,反之亦然,为了使用 系统内存。
如果内核将 Redis 页面从内存移动到交换文件,则当 存储在此内存页中的数据被 Redis 使用(例如,访问 一个密钥)内核将停止 Redis 进程 以便将页面移回主内存。这是一个缓慢的作 涉及随机 I/O(与访问内存中已有的页面相比) 并将导致 Redis 客户端遇到异常延迟。
内核将 Redis 内存页重新定位到磁盘上,主要有三个原因:
- 由于正在运行的进程要求很高,因此系统面临内存压力 物理内存多于可用内存量。最简单的 此问题只是 Redis 使用的内存多于可用内存。
- Redis 实例数据集或数据集的一部分大部分是完全空闲的 (客户端永远不会访问),因此内核可以交换磁盘上的空闲内存页。 这个问题非常罕见,因为即使是一个中等速度的实例也会触及所有 内存页,迫使内核将所有页保留在内存中。
- 某些进程在系统上生成大量读取或写入 I/O。因为 文件一般都会被缓存,这往往会给内核带来增加的压力 文件系统缓存,因此生成交换活动。请注意 包括 Redis RDB 和/或 AOF 后台线程,它们可以生成大文件。
幸运的是,Linux 提供了很好的工具来调查问题,因此最简单的 要做的是,当怀疑由于交换导致的延迟时,只是检查一下 事实就是如此。
首先要做的是检查交换的 Redis 内存量 在磁盘上。为此,您需要获取 Redis 实例 pid:
$ redis-cli info | grep process_id
process_id:5454
现在输入此过程的 /proc 文件系统目录:
$ cd /proc/5454
在这里,您将找到一个名为 smaps 的文件,它描述了 Redis 进程(假设您使用的是 Linux 2.6.16 或更高版本)。 此文件包含有关我们的进程内存映射的非常详细的信息。 一个名为 Swap 的字段正是我们正在寻找的。然而 由于 Smaps 文件包含 Redis 进程的不同内存映射(进程的内存布局 比简单的页面线性数组更复杂)。
由于我们对进程交换的所有内存感兴趣,因此第一件事 要做的是对所有文件的 Swap 字段进行 grep:
$ 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
如果所有内容均为 0 kB,或者存在零星的 4k 条目,则所有内容均为 完全正常。实际上,在我们的示例实例中(真实 Web 的实例 站点运行 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
从输出中可以看出,有一个 720896 kB 的映射 (仅交换了 12 kB)和在另一张地图中交换了 156 kB: 基本上,我们的内存量非常小,所以这不是 根本不会制造任何问题。
相反,如果磁盘上交换了大量的进程内存,则您的 延迟问题可能与交换有关。如果您的 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
^C
对于我们的需求,输出中有趣的部分是两列 si 和 so,它计算从交换文件交换/交换到交换文件的内存量。如果 您在这两列中看到非零计数,则存在交换活动 在您的系统中。
最后,iostat 命令可用于检查 系统。
$ 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
如果您的延迟问题是由于磁盘上的 Redis 内存交换造成的,您需要 以降低系统中的内存压力,如果 Redis 使用的内存多于可用内存,或避免运行其他内存 hungry 进程。
由于 AOF 和磁盘 I/O 导致的延迟
延迟的另一个来源是由于 Redis 上的 Append Only File 支持。 AOF 基本上使用两个系统调用来完成其工作。一是 write(2) 用于将数据写入 append only 文件,以及 另一个是 fdatasync(2),用于刷新内核 file 缓冲区,以确保 用户。
write(2) 和 fdatasync(2) 调用都可能是延迟的来源。 例如,当存在系统范围的同步时,write(2) 可以同时阻止两者 正在进行,或者当输出缓冲区已满且内核需要 在磁盘上刷新以接受新的写入。
与许多组合一样,fdatasync(2) 调用是更糟糕的延迟来源 使用的内核和文件系统可能需要几毫秒到 几秒钟即可完成,尤其是在其他进程的情况下 执行 I/O。因此,Redis 会尽可能地调用 fdatasync(2) 在 Redis 2.4 之后的不同线程中。
我们将了解配置如何影响延迟的数量和来源 使用 AOF 文件时。
AOF 可以配置为在磁盘上以三种不同的方式执行 fsync 方式(此设置可以是 在运行时使用 CONFIG SET 命令进行修改)。
-
当 appendfsync 设置为 no 的值时,Redis 不会执行 fsync。 在此配置中,延迟的唯一来源可以是 write(2)。 发生这种情况时,通常没有解决方案,因为磁盘不能 应对 Redis 接收数据的速度,但这是 如果磁盘没有被其他进程严重减慢,则不常见 I/O 的
-
当 appendfsync 设置为每秒一次的值时,Redis 会执行 fsync 的 fsync 值。它使用不同的线程,如果 fsync 仍然 正在进行 Redis 使用缓冲区将 write(2) 调用延迟最多两秒 (因为如果 fsync 正在针对 同一文件)。但是,如果 fsync 花费的时间太长,Redis 最终会 执行 write(2) 调用,即使 fsync 仍在进行中,并且此 可能是延迟的来源。
-
当 appendfsync 设置为 always 的值时,将执行 fsync 在每次写入作时,使用 OK 代码回复客户端 (实际上 Redis 会尝试将同时执行的许多命令聚集在一起 转换为单个 fsync)。在这种模式下,性能通常非常低,并且 强烈建议使用快速磁盘和文件系统实现 可以在短时间内执行 fsync。
大多数 Redis 用户将对 appendfsync 配置指令。最小延迟的建议是 以避免其他进程在同一系统中执行 I/O。 使用 SSD 磁盘也会有所帮助,但通常即使是非 SSD 磁盘也可以执行 如果磁盘在 Redis 写入时是备用的,则使用 Append Only 文件 附加到 Append Only 文件中,而不执行任何查找。
如果您只想调查与附加相关的延迟问题 文件,您可以在 Linux 下使用 strace 命令:
sudo strace -p $(pidof redis-server) -T -e trace=fdatasync
上面的命令将显示 Redis 在主线程中。使用上述命令,您将看不到 fdatasync 系统调用时,后台线程执行的 appendfsync config 选项设置为 everysec。为了做到这一点 只需将 -f 开关添加到 strace 即可。
如果您愿意,还可以使用 以下命令:
sudo strace -p $(pidof redis-server) -T -e trace=fdatasync,write
但是,由于 write(2) 也被用来将数据写入客户端 sockets 这可能会显示太多与磁盘 I/O 无关的内容。 显然,没有办法告诉 strace 只显示慢速系统调用,因此 我使用以下命令:
sudo strace -f -p $(pidof redis-server) -T -e trace=fdatasync,write 2>&1 | grep -v '0.0' | grep -v unfinished
expires 产生的延迟
Redis 通过两种方式驱逐过期的密钥:
- 一种惰性方式在命令请求密钥时使密钥过期,但发现密钥已经过期。
- 一种活动方式每 100 毫秒使几个密钥过期。
活动过期设计为自适应的。过期周期每 100 毫秒启动一次(每秒 10 次),并将执行以下作:
- 样本
ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP
keys 中,驱逐所有已过期的 key。 - 如果发现超过 25% 的密钥已过期,请重复此作。
鉴于ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP
默认设置为 20,进程每秒执行 10 次,通常每秒只有 200 个 key 主动过期。即使长时间未访问已过期的密钥,这也足以足够快地清理数据库,因此惰性算法无济于事。同时,每秒仅过期 200 个密钥对 Redis 实例的延迟没有影响。
但是,该算法是自适应的,如果它在采样密钥集中发现超过 25% 的密钥已过期,则会循环。但鉴于我们每秒运行算法 10 次,这意味着随机样本中超过 25% 的 key 的不幸事件至少在同一秒内过期。
基本上,这意味着,如果数据库中有很多很多键在同一秒内过期,并且这些键至少占当前设置过期的键总数的 25%,Redis 可以阻塞以使已经过期的键的百分比低于 25%。
为了避免为已经过期的密钥使用过多的内存,需要这种方法,并且通常是绝对无害的,因为大量密钥将在同一秒内过期是很奇怪的,但用户使用EXPIREAT
广泛使用相同的 Unix 时间。
简而言之:请注意,许多密钥同时过期可能是延迟的来源。
Redis 软件看门狗
Redis 2.6 引入了 Redis 软件看门狗,它是一个调试工具 旨在跟踪那些出于某种原因的延迟问题 使用普通工具转义分析。
软件看门狗是一项实验性功能。虽然它旨在 在生产环境中使用时,应注意备份数据库 ,因为它可能会与 Redis 服务器的正常执行。
重要的是,仅在无法通过其他方式跟踪问题时将其用作最后的手段。
此功能的工作原理如下:
- 用户使用
CONFIG SET
命令。 - Redis 开始持续监控自身。
- 如果 Redis 检测到服务器被阻止执行某些返回速度不够快的作,这可能是延迟问题的根源,则会在日志文件中转储有关服务器被阻止位置的低级别报告。
- 用户联系开发人员,在 Redis Google Group 中编写消息,并在消息中包含监视程序报告。
请注意,此功能不能使用 redis.conf 文件启用,因为它设计为仅在已运行的实例中启用,并且仅用于调试目的。
要启用该功能,只需使用以下内容:
CONFIG SET watchdog-period 500
该时间段以毫秒为单位指定。在上面的示例中,我指定仅在服务器检测到 500 毫秒或更长时间的延迟时记录延迟问题。最小可配置周期为 200 毫秒。
使用完软件看门狗后,您可以将其关闭,将watchdog-period
parameter 设置为 0。重要提示:请记住这样做,因为让带有看门狗的实例保持开启状态的时间通常不是一个好主意。
以下是软件看门狗检测到延迟超过配置的延迟后,您将在日志文件中看到的内容示例:
[8547 | signal handler] (1333114359)
--- WATCHDOG TIMER EXPIRED ---
/lib/libc.so.6(nanosleep+0x2d) [0x7f16b5c2d39d]
/lib/libpthread.so.0(+0xf8f0) [0x7f16b5f158f0]
/lib/libc.so.6(nanosleep+0x2d) [0x7f16b5c2d39d]
/lib/libc.so.6(usleep+0x34) [0x7f16b5c62844]
./redis-server(debugCommand+0x3e1) [0x43ab41]
./redis-server(call+0x5d) [0x415a9d]
./redis-server(processCommand+0x375) [0x415fc5]
./redis-server(processInputBuffer+0x4f) [0x4203cf]
./redis-server(readQueryFromClient+0xa0) [0x4204e0]
./redis-server(aeProcessEvents+0x128) [0x411b48]
./redis-server(aeMain+0x2b) [0x411dbb]
./redis-server(main+0x2b6) [0x418556]
/lib/libc.so.6(__libc_start_main+0xfd) [0x7f16b5ba1c4d]
./redis-server() [0x411099]
------
注意:在示例中,使用DEBUG SLEEP命令来阻止服务器。如果服务器在不同的上下文中阻塞,则堆栈跟踪会有所不同。
如果您碰巧收集了多个看门狗堆栈跟踪,我们鼓励您将所有内容发送到 Redis Google Group:我们获得的跟踪越多,就越容易了解您的实例的问题所在。