需求背景:
近期某个StarRocks集群,内存128G了,但是架不住有些复杂的大的查询啊。最近出现一次某个大查询导致BE内存暴涨,最后把其中一个ECS节点拖死的情况。
为了尽可能减少这种情况的发生,DBA目前想到了2个方案:
1、完善自动化巡检,show processlist 检测到执行时间超过N秒的会话自动kill掉并通过IM通知出来
2、通过第三方的工具(这里用的是earlyoom),在主机内存不足的情况下即时回收内存(kill掉占用内存最高的进程),避免把宿主机拖死。
earlyoom的安装
项目地址 https://github.com/rfjakob/earlyoom/
git clone https://github.com/rfjakob/earlyoom.git
cd earlyoom
make
make install
即可
> ./earlyoom -h
earlyoom (unknown version)
Usage: ./earlyoom [OPTION]...
-m PERCENT[,KILL_PERCENT] set available memory minimum to PERCENT of total
(default 10 %).
earlyoom sends SIGTERM once below PERCENT, then
SIGKILL once below KILL_PERCENT (default PERCENT/2).
-s PERCENT[,KILL_PERCENT] set free swap minimum to PERCENT of total (default
10 %).
Note: both memory and swap must be below minimum for
earlyoom to act.
-M SIZE[,KILL_SIZE] set available memory minimum to SIZE KiB
-S SIZE[,KILL_SIZE] set free swap minimum to SIZE KiB
-n enable d-bus notifications
-N /PATH/TO/SCRIPT call script after oom kill
-g kill all processes within a process group
-d, --debug enable debugging messages
-v print version information and exit
-r INTERVAL memory report interval in seconds (default 1), set
to 0 to disable completely
-p set niceness of earlyoom to -20 and oom_score_adj to
-100
--ignore-root-user do not kill processes owned by root
--sort-by-rss find process with the largest rss (default oom_score)
--prefer REGEX prefer to kill processes matching REGEX
--avoid REGEX avoid killing processes matching REGEX
--ignore REGEX ignore processes matching REGEX
--dryrun dry run (do not kill any processes)
--syslog use syslog instead of std streams
-h, --help this help text
开一个窗口1,执行
./earlyoom -M 4096000 -r 1 --sort-by-rss
另开一个窗口2,执行一个模拟内存泄露的场景
tail /dev/zero
然后再开一窗口3,观察 内存使用情况
watch -n 1 'free -g'
在窗口2执行了tail /dev/zero后,可以到窗口3看下内存监控,大致如下:
然后回到窗口1上,可以看到类似如下图:
可以看到earlyoom命令检测到内存不足,先尝试执行了sigterm命令,然后又执行了sigkill命令,将tail /dev/zero 给暴力kill掉了,然后释放出内存。
窗口2,也可以看到被kill的日志,类似如下:
注意,earlyoom的kill逻辑:
earlyoom sends SIGTERM once below PERCENT, then SIGKILL once below KILL_PERCENT (default PERCENT/2)
以下内容来自官方github的翻译。
earlyoom 力求简洁可靠。它采用纯 C 语言编写,没有任何依赖项。丰富的测试套件(单元测试和集成测试)则使用 Go 语言编写。
earlyoom 每秒最多检查 10 次可用内存和空闲交换空间(如果可用内存充足,则检查频率会降低)。默认情况下,如果两者均低于 10%,它将终止最大的进程(highest oom_score
)。百分比值可通过命令行参数配置。
为什么要检查“可用”内存而不是“空闲”内存?在健康的 Linux 系统上,“空闲”内存应该接近于零,因为 Linux 使用所有可用的物理内存来缓存磁盘访问。当需要将内存用于其他用途时,这些缓存可以随时被删除。
“可用”内存就是为了解决这个问题。它总结了所有未使用或可立即释放的内存。
请注意,您需要最新版本的 free
Linux 内核 3.14 及以上版本才能查看“可用”列。如果您使用的是较新的内核,但使用的是旧版本的free
,则可以从 中获取值grep MemAvailable /proc/meminfo
。
当可用内存和空闲交换都低于用户空间进程可用内存总量 (=total-shared) 的 10% 时,它会SIGTERM
向内核认为使用最多内存的进程发送信号 ( /proc/*/oom_score
)。
earlyoom 不使用echo f > /proc/sysrq-trigger
,因为:
在某些内核版本(在 v4.0.5 上测试)中,手动触发内核 oom killer 根本不起作用。也就是说,它可能只会释放一些图形内存(这些内存会立即再次分配),而不会真正终止任何进程。您可以在这里看到在我的机器(Intel 集成显卡)上的情况。
该问题已在 Linux v5.17 中修复(提交 f530243a)。
就像 Linux 内核一样,earlyoom 通过阅读来找到它的受害者/proc/*/oom_score
。
关于2 MiB
( VmRSS
),尽管只有220 kiB
是私有内存 ( )。其余的是与其他进程共享的RssAnon
libc 库 ( )。所有内存都使用 锁定,以确保 earlyoom 在内存不足的情况下不会变慢。RssFilemlockall()
只需启动刚刚编译的可执行文件:
./earlyoom
它会告诉您有多少内存和交换空间、最小值是多少、有多少可用内存以及有多少空闲交换空间。
./earlyoom
eearlyoom v1.8
mem total: 23890 MiB, user mem total: 21701 MiB, swap total: 8191 MiB
sending SIGTERM when mem avail <= 10.00% and swap free <= 10.00%,
SIGKILL when mem avail <= 5.00% and swap free <= 5.00%
mem avail: 20012 of 21701 MiB (92.22%), swap free: 5251 of 8191 MiB (64.11%)
mem avail: 20031 of 21721 MiB (92.22%), swap free: 5251 of 8191 MiB (64.11%)
mem avail: 20033 of 21723 MiB (92.22%), swap free: 5251 of 8191 MiB (64.11%)
[...]
如果值低于最小值,进程将被终止,直到再次高于最小值。每个操作都会记录到 stderr。
如果您将 earlyoom 作为 systemd 服务运行,您可以使用以下命令查看最后 10 行
systemctl status earlyoom
命令行标志--prefer
指定优先终止的进程;同样,--avoid
指定避免终止的进程。详情请参阅https://github.com/rfjakob/earlyoom/blob/master/MANPAGE.md#--prefer-regex 。
如果您将 earlyoom 作为系统服务运行(通过 systemd 或 init.d),则可以通过 中提供的文件调整其配置/etc/default/earlyoom
。该文件已在注释中包含一些示例,您可以使用这些示例根据支持的命令行选项构建自己的配置集,例如:
EARLYOOM_ARGS="-m 5 -r 60 --avoid '(^|/)(init|Xorg|ssh)$' --prefer '(^|/)(java|chromium)$'"
调整文件后,只需重启服务即可应用更改。例如,对于 systemd:
systemctl restart earlyoom
请注意,此配置文件对 systemd/init.d 之外的 earlyoom 实例没有影响。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。