原文內容來自於LZ(樓主)的印象筆記,如出現排版異常或圖片丟失等問題,可查看當前鏈接:https://app.yinxiang.com/shard/s17/nl/19391737/9652651a-7449-4e8e-b77e-1c60ea8b7d12
本篇主要說明以下問題:
1、服務器
buffer/cache 的產生原因和釋放buffer/cache 的兩種方式(自動 & 手動)
2、
生產環境遇到服務 buffer/cache 過高如何排查是由那幾個進程引起的(
hcache ,lsof 的使用方式
)
服務器 buffer/cache 的產生原因和釋放buffer/cache 的兩種方式(自動 & 手動)
1、什么是buffer/cache ?
buffer/cache 其實是作為服務器系統的文件數據緩存使用的,尤其是針對進程對文件存在 read/write 操作的時候,所以當你的服務進程在對文件進行讀寫的時候,Linux內核為了提高服務的讀寫速度,則將會把文件放在此處的 buffer/cache 中進行緩存使用,由於 Linux服務的特點便是任何事物都會以文件的形式進行存在,所以你會發現不管你是否對文件做了大規模的讀寫,機器的 buffer/cache 是一直都存在的,並且持續的增高不下,這是因為服務器所產生的網絡連接也好,用戶協議的(UDP)套接字也好,這部分的數據系統都會為應用程序創建對應的文件描述符,而這些文件描述符的使用,則又都會重新進入 buffer/cache 中做讀寫使用,所以這也是你的機器始終都會存在較高 buffer/cache 的原因,(因為所有的文件讀寫都會用到 buffer/cache,在內存合理的情況下)
2、buffer/cache 需要注意的一些特點
在服務內存夠用的情況下,Linux內核為了加快對文件的讀寫效率會將文件放入之 buffer/cache 中 以保證讀寫效率,
但其實,盡管當你的應用程序對文件的讀寫運行結束后,buffer/cache 也不會自動釋放該部分內存
,而是作為緩沖進行保留,等到你的服務進程在下一次進行相同文件的讀寫時就可以直接使用,省去了各種重新進行內存初始化的操作;所以這將會導致,當你的應用進程頻繁對不同的文件進行讀寫時,你會發現服務所可以直接使用的free內存將會越來越少的一個重要原因;
難道 buffer/cache 在這樣無休止的緩存當中就不會自動釋放?
當然不是,
當服務器在內存壓力較大的情況下時,則將會自動進行內存的回收,作為free空間分給其它進程使用,這其中主要回收的一個內存則是 buffer/cache 的緩沖區內存塊;
3、如何進行手動 buffer/cache 回收?
除了在系統進程內存使用較大壓力的情況下進行內存的回收外,我們也可以進行手動的buffer/cache回收,但由於buffer/cache主要是用於文件的讀寫使用,所以進行文件回收時,一般常伴隨系統的IO彪高,因為系統內核也對比cache中的數據與硬盤中的數據是否一致,如果不一致需要寫會,然后才能進行內存的回收;
將內存中數據強制先刷新到磁盤中
sync;
清理Buffer緩存區域
echo 3 > /proc/sys/vm/drop_caches 表示清除pagecache和slab分配器中的緩存對象
echo 1 > /proc/sys/vm/drop_caches:表示清除pagecache。
echo 2 > /proc/sys/vm/drop_caches:表示清除回收slab分配器中的對象(包括目錄項緩存和inode緩存)。slab分配器是內核中管理內存的一種機制,其中很多緩存數據實現都是用的pagecache。
關於buffer/cache 的相關描述,具體也可以參考如下鏈接:
生產環境遇到服務 buffer/cache 過高如何排查是由那幾個進程引起的(hcache 的使用方式)
1、hcache的下載地址
2、 hcache的使用方式
當前下載完對應的hcache后,則直接是一個對應的 bin文件,此時直接將對應的bin文件進行 chmod 授權后即可使用
將該bin文件設置為可執行文件
chmod 755 hcache
將該hcache移動到usr的bin目錄中,使其可以被全局調用該命令
mv hcache /usr/local/bin/
3、hcache常用命令
全局顯示10個最大的被緩存文件
hcache --top 10
| Name | Size (bytes) | Pages | Cached | Percent |
|-----------------------------------------------------------------------------------+----------------+-
| /app/java/jdk1.8.0_92/jre/lib/amd64/server/libjvm.so | 41943040 | 10240 | 8682 | 084.785 |
| libmergedlo.so | 101021431 | 24664 | 5858 | 023.751 |
| dockerd-current | 33398384 | 8154 | 3425 | 042.004 |
| libjvm.so | 16938578 | 4136 | 2429 | 058.728 |
| libjvm.so | 13363349 | 3263 | 1696 | 051.977 |
| docker-containerd-current | 10807760 | 2639 | 1171 | 044.373 |
查看指定進程ID所使用的buffer/cache 的使用情況
hcache -pid 16322
通過上述所獲取到的被緩存最大的文件名稱后,可以直接通過 lsof file_name 得到當前所開啟該文件的所有進程信息;
顯示使用 kbase-psrt.jar 的進程信息
[root@xiaoi-3614 ~]# lsof /app/kbase-psrt-wscc/kbase-psrt.jar
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
java 6048 root mem REG 8,2 59936357 137027366 /app/kbase-psrt-wscc/kbase-psrt.jar
java 6048 root 5r REG 8,2 59936357 137027366 /app/kbase-psrt-wscc/kbase-psrt.jar
java 6048 root 6r REG 8,2 59936357 137027366 /app/kbase-psrt-wscc/kbase-psrt.jar
java 6050 root mem REG 8,2 59936357 137027366 /app/kbase-psrt-wscc/kbase-psrt.jar
java 6050 root 5r REG 8,2 59936357 137027366 /app/kbase-psrt-wscc/kbase-psrt.jar
java 6050 root 6r REG 8,2 59936357 137027366 /app/kbase-psrt-wscc/kbase-psrt.jar
獲取當前進程號所打開的所有文件信息
[root@xiaoi-3614 ~]# lsof -p 6048
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
java 6048 root cwd DIR 8,2 4096 136958862 /app/kbase-psrt-wscc
java 6048 root rtd DIR 8,2 4096 128 /
java 6048 root txt REG 8,2 7734 202909666 /app/java/jdk1.8.0_92/bin/java
java 6048 root mem REG 8,2 88776 203501791 /usr/lib64/libgcc_s-4.8.5-20150702.so.1
java 6048 root mem REG 8,2 256702 135314838 /app/java/jdk1.8.0_92/jre/lib/amd64/libsunec.so
java 6048 root mem REG 8,2 106075056 2663 /usr/lib/locale/locale-archive
java 6048 root mem REG 8,2 93112 135314912 /app/java/jdk1.8.0_92/jre/lib/amd64/libnio.so
更多關於LSOF的使用,可以參考如下鏈接: