作者:付祥
现居珠海,次要负责 Oracle、MySQL、mongoDB 和 Redis 保护工作。
本文起源:原创投稿
* 爱可生开源社区出品,原创内容未经受权不得随便应用,转载请分割小编并注明起源。
景象
监控告警某台机器闲暇内存低于 10%,执行 top 命令,按内存降序排序,局部输入如下:
[root@mysql-slaver ~]# top
top - 13:45:43 up 1835 days, 20:52, 2 users, load average: 0.02, 0.03, 0.05
Tasks: 210 total, 1 running, 208 sleeping, 1 stopped, 0 zombie
%Cpu(s): 0.5 us, 0.6 sy, 0.0 ni, 98.9 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 32780028 total, 905684 free, 19957900 used, 11916444 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 3448260 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
2677 mysql 20 0 20.1g 15.1g 3392 S 0.0 48.2 430:17.58 mysqld
10549 polkitd 20 0 3277476 3.1g 632 S 0.3 9.9 146:47.24 redis-server
18183 root 20 0 877308 215868 1892 T 2.7 0.7 2736:45 xxxxxx
442 root 20 0 160244 93016 88552 S 0.3 0.3 314:14.86 systemd-journal
32537 root 20 0 731620 58360 54588 S 0.3 0.2 29:09.61 rsyslogd
total=32G,used=19G,buff/cache=11G,available=3G, 最耗内存过程为 MySQL、Redis,总计约 18.2G,其余过程占用内存都比拟低,buff/cache 内存中只有 3G 是无效的,残余 8G 内存去哪里?
剖析
执行 free 命令进一步查看:
[root@MySQL-slaver ~]# free -m
total used free shared buff/cache available
Mem: 32011 19490 881 8762 11639 3366
Swap: 0 0 0
其中 shared 占用居然占用了 8G 内存,通过 man 查看帮忙:
shared Memory used (mostly) by tmpfs (Shmem in /proc/meminfo, available on kernels 2.6.32, displayed as zero if not avail‐
able)
shared Memory 来源于 /proc/meminfo 中 Shmem,被 tmpfs 应用,df - h 查看:
[root@MySQL-slaver ~]# df -h
Filesystem Size Used Avail Use% Mounted on
devtmpfs 16G 0 16G 0% /dev
tmpfs 16G 16K 16G 1% /dev/shm
tmpfs 16G 8.6G 7.1G 55% /run
tmpfs 16G 0 16G 0% /sys/fs/cgroup
目录 /run 应用了 8.6G 内存,和 shared 占用内存统一,内存都耗费到哪些子目录了?
[root@MySQL-slaver ~]# du -am /run|sort -rn -k1|head -10
8761 /run
7137 /run/systemd
7126 /run/systemd/users
1624 /run/log/journal/89308070e0c04c6a86bf577f4064efca
1624 /run/log/journal
1624 /run/log
内存次要耗费在 /run/systemd/users 和 /run/log/journal 目录,占用内存别离为 7126M、1624M, 较为异样的是 /run/systemd/users 占用内存过高,持续剖析这个目录下有哪些文件
[root@MySQL-slaver ~]# ls -l /run/systemd/users
total 44
-rw-r--r-- 1 root root 41056 Mar 23 14:14 0
乍一看,只有一个文件占用约 40k,这和 du 统计的差别也太大了吧,是不是有暗藏文件:
[root@MySQL-slaver ~]# find /run/systemd/users|less
/run/systemd/users
/run/systmd/users/0
/run/systemd/users/.#0kRUlqC
/run/systemd/users/.#0Qxvu5J
/run/systemd/users/.#03DvfrF
......
[root@MySQL-slaver ~]# find /run/systemd/users|wc -l
337632
[root@MySQL-slaver ~]# ls -l /run/systemd/users/.#00009iJ
-rw-r--r-- 1 root root 20480 Sep 26 2018 /run/systemd/users/.#00009iJ
[root@MySQL-slaver ~]# ll /run/systemd/users/.#0SEEqoi
-rw-r--r-- 1 root root 20480 Mar 23 14:34 /run/systemd/users/.#0SEEqoi
[root@MySQL-slaver ~]# uptime
14:45:13 up 1835 days, 21:51, 2 users, load average: 0.02, 0.08, 0.12
不看不晓得,一看吓一跳,暗藏文件数高达 30w+, 最早的文件有 2018 年的,最新的文件明天产生的,轻易关上一个文件看看:
[root@MySQL-slaver ~]# less /run/systemd/users/.#03DvfrF
# This is private data. Do not parse.
NAME=root
STATE=active
RUNTIME=/run/user/0
SLICE=user-0.slice
DISPLAY=4231719
REALTIME=1521010223727718
MONOTONIC=79029110787
SESSIONS=4232100 4232099 4232098 ......
保留的是 root 用户 session 信息,loginctl 查看 session 信息:
[root@MySQL-slaver ~]# loginctl list-sessions
SESSION UID USER SEAT
24597 0 root
146401 0 root
133160 0 root
82494 0 root
82514 0 root
106049 0 root
......
[root@MySQL-slaver ~]# loginctl list-sessions|awk '{print $3}'|sort|uniq -c
1
1 listed.
2131 root
1 USER
root 用户 session 数居然高达 2131 个,轻易拿一个 session 看看:
[root@MySQL-slaver ~]# loginctl session-status 24597
24597 - root (0)
Since: Tue 2018-03-27 08:35:01 CST; 4 years 11 months ago
Leader: 25599
Service: crond; type unspecified; class background
State: active
Unit: session-24597.scope
[root@MySQL-slaver ~]#
crond 产生的 session,这些 session 都没有调配相干过程,以后状态为 active,按 session 排序后,筛选最近的 session 查看,都是 2018 年产生的:
[root@MySQL-slaver ~]# loginctl session-status 243335
243335 - root (0)
Since: Sat 2018-07-14 03:29:01 CST; 4 years 8 months ago
Leader: 28376
Service: crond; type unspecified; class background
State: active
Unit: session-243335.scope
[root@MySQL-slaver ~]#
做了一个定时工作测试,session 能失常调配过程,工作实现后 session 敞开:
Mar 23 15:20:01 [localhost] CROND[12334]: (root) CMD (sleep 1200)
[root@MySQL-slaver ~]# loginctl session-status 4232206
4232206 - root (0)
Since: Thu 2023-03-23 15:20:01 CST; 19min ago
Leader: 12330 (crond)
Service: crond; type unspecified; class background
State: opening
Unit: session-4232206.scope
├─12330 /usr/sbin/CROND -n
└─12334 sleep 1200
[root@MySQL-slaver ~]# loginctl session-status 4232206
Failed to get session: No session '4232206' known
[root@MySQL-slaver ~]# lsof -p `pidof dbus-daemon`|grep sessions|wc -l
2126
[root@MySQL-slaver ~]# lsof -p `pidof dbus-daemon`|tail -5
dbus-daem 560 dbus 2139w FIFO 0,18 0t0 416861417 /run/systemd/sessions/156582.ref
dbus-daem 560 dbus 2140w FIFO 0,18 0t0 417383549 /run/systemd/sessions/156774.ref
dbus-daem 560 dbus 2141w FIFO 0,18 0t0 417291412 /run/systemd/sessions/156740.ref
dbus-daem 560 dbus 2142w FIFO 0,18 0t0 620267085 /run/systemd/sessions/242902.ref
dbus-daem 560 dbus 2143w FIFO 0,18 0t0 621086290 /run/systemd/sessions/243335.ref
[root@MySQL-slaver ~]#
解决
集体感觉可选解决方案如下:
1、服务器上次要服务为 MySQL 和 Redis,MySQL 作为从库应用,未承载业务读流量,Redis 近期将会迁徙,/run/systemd/users 目录占用内存尽管在增长,5 年了也只占用 8G,增量很迟缓,故能够在线膨胀 MySQL innodb_buffer_pool_size 应用内存,开释一部分内存给操作系统,等 Redis 迁徙了再做机器重启解决。
2、假如主机不能够重启,通过 lsof 可知这些暗藏文件以后未被应用,故能够迁徙到其余磁盘目录,看看是否能达到开释内存目标,且这些 session 都是 crond 2018 年产生的,并未调配相干过程,故通过 loginctl kill-session ID 干掉。
目前采取计划 1 解决。