前言 前文《[linux][redis]bgsave引起的latency突刺问题分析》中记录了在执行bgsave的时候,因为fork子进程之后,会出现page fault导致了redis的延迟受到了影响。 前文《[THP][redis]THP对redis的影响》中分析了THP(transparent hugepage)对redis的延迟突刺的影响。 大约两年半以前,作者给redis提了PR(https://github.com/redis/redis/pull/5124),但是maintainer并没有回复,一段时间后关闭。 几个月前,第二次提PR(https://github.com/redis/redis/pull/7381)希望解决这个问题,新任的maintainer Oran对THP问题比较感兴趣,同时也把三年多以前的另外一个PR(https://github.com/redis/redis/pull/4001)翻了出来。大约经过一周的讨论和修改,两个PR都已经合入了upstream。 分析 THP的内核逻辑 内核提供了THP开关可以控制,/sys/kernel/mm/transparent_hugepage/enabled,这个开关需要root权限,且是系统级别的影响。 always表示所有的进程都会被khugepaged扫描,尝试使用2M的透明大页。 madvise表示如果有进程调用了THP开关,则打开/关闭。 never表示khugepaged不会对任何进程生效,包括使用madvise的进程。 warning判断 redis的原有的逻辑是在启动阶段检查系统的THP配置,如果不是never,就会产生一个warning。redis自身并没有使用过madvise进行THP操作,即使使用了jemalloc,也不会对主要的内存进行THP操作。所以改成不是always就应该是安全的,所以,Oran接受了这个改动(https://github.com/redis/redis/pull/4001)。 关闭redis的进程THP 更加理想的做法是不管系统配置如何,redis都可以把自己进程的THP开关禁用掉,这样子不需要root权限控制,且不会影响其他的进程。Linux恰好提供了这样了一个syscall,所以在(https://github.com/redis/redis/pull/7381)中,会关闭掉。同时,根据Oran的意见,增加了配置项,在多数情况下,默认都是会自动关闭掉THP,除非用户强制指定了不关闭的配置。这样下来,在大多数情况下,用户都可以避免THP引起的fork之后的剧烈抖动问题。 关于conf的描述 在redis.conf中增加了一个新的配置项“disable-thp”,作者最初的描述是
#################### KERNEL transparent hugepage CONTROL ######################
# Since Linux 3.15, it is possible to disable THP(transparent hugepage) setting
# for a specified process.
#
# Transparent Hugepage Support is an alternative means of using huge pages for
# the backing of virtual memory with huge pages that supports the automatic
# promotion and demotion of page sizes and without the shortcomings of hugetlbfs.
# But fixing a Copy-On-Write page fault for THP takes more time, and latency
# jitter may occurs after forking a child process.
#
# For general purpose, the recommended config is 'yes', redis will try to disable
# THP for itself when startup. And if you have a specific use of THP, set this
# to 'no'.
disable-thp yes
然而Oran建议是
#################### LINUX KERNEL THP CONTROL #################################
# Usually the kernel Transparent Huge Pages control is set to "madvise" or
# or "never" by default (/sys/kernel/mm/transparent_hugepage/enabled), in which
# case this config has no effect. On systems in which it is set to "always",
# redis will attempt to disable it specifically for the redis process in order
# to avoid latency problems specifically with fork(2) and CoW.
# If for some reason you prefer to keep it enabled, you can set this config to
# "no" and the kernel global to "always".
#
# disable-thp yes
对于end-user来说,后者应该更加友好一些。让配置简单易懂,这也是redis这么流行的原因之一吧。 详细的讨论过程见上文的PR。