Linux系統長時間運行會出現記憶體片段化的問題,本文主要提供了應對該問題的一些措施。
問題現象
執行個體內部署的業務偶然出現回應時間過長或者系統調用時間過長,系統的sys
指標也會相應的增高,夥伴系統會缺少高階記憶體(order
大於3的記憶體)。例如,運行cat /proc/buddyinfo命令的返回結果如下所示,其中從第4列開始,每一列對應夥伴系統的不同order
空閑記憶體。
cat /proc/buddyinfo
Node 0, zone DMA 1 0 0 1 2 1 1 0 1 1 3
Node 0, zone DMA32 3173 856 529 0 0 0 0 0 0 0 0
Node 0, zone Normal 19030 8688 7823 0 0 0 0 0 0 0 0
可能原因
Linux系統在長時間運行後,連續的大塊實體記憶體會被分解為小塊的實體記憶體。此時,系統中部署的業務如果需要連續的大塊記憶體,則系統會先進入耗時較長的記憶體規整流程,進而會引起系統效能抖動。一般情況下,記憶體片段化會產生類似於如下所示的核心堆棧資訊。
0xffffffff8118f9cb compaction_alloc ([kernel.kallsyms])
0xffffffff811c88a9 migrate_pages ([kernel.kallsyms])
0xffffffff811901ee compact_zone ([kernel.kallsyms])
0xffffffff8119041b compact_zone_order ([kernel.kallsyms])
0xffffffff81190735 try_to_compact_pages ([kernel.kallsyms])
0xffffffff81631cb4 __alloc_pages_direct_compact ([kernel.kallsyms])
0xffffffff811741d5 __alloc_pages_nodemask ([kernel.kallsyms])
0xffffffff811b5a79 alloc_pages_current ([kernel.kallsyms])
0xffffffff811c0005 new_slab ([kernel.kallsyms])
0xffffffff81633848 __slab_alloc ([kernel.kallsyms])
0xffffffff811c5291 __kmalloc_node_track_caller ([kernel.kallsyms])
0xffffffff8151a8c1 __kmalloc_reserve.isra.30 ([kernel.kallsyms])
0xffffffff8151b7cd alloc_sib ([kernel.kallsyms])
0xffffffff815779e9 sk_stream_alloc_skb ([kernel.kallsyms])
0xffffffff8157872d tcp_sendmsg ([kernel.kallsyms])
0xffffffff815a26b4 inet_sendmsg ([kernel.kallsyms])
0xffffffff81511017 sock_aio_write ([kernel.kallsyms])
0xffffffff811df729 do_sync_readv_writev ([kernel.kallsyms])
0xffffffff811e0cfe do_readv_writev ([kernel.kallsyms])
解決方案
應對Linux記憶體片段化,您可以採取如下措施:
調整min水位線
多數情況下阿里雲建議您將min水位線設定為總記憶體的1%~3%。推薦您設定為總記憶體的2%,當記憶體資源緊張時,提前進入非同步回收。調整min水位線的命令如下:
sysctl -w vm.min_free_kbytes = memtotal_kbytes * 2%
其中,變數memtotal_kbytes * 2%表示當前執行個體內總記憶體的2%對應的記憶體大小。
調整min水位線和low水位線之間的差值
您可以通過核心的
watermark_scale_factor
調整min水位線和low水位線之間的差值,以應對業務突發申請記憶體的情況。watermark_scale_factor
的預設值為總記憶體的0.1%,最小值(即min水位線和low水位線之間的最小差值)為0.5*min水位線
。調整watermark_scale_factor
的命令如下:sysctl -w vm.watermark_scale_factor = value
其中,變數value為您手動設定的min水位線和low水位線之間的差值。
定期進行記憶體規整
您可以在業務空閑時段,主動觸發非同步記憶體規整。觸發命令如下:
echo 1 > /proc/sys/vm/compact_memory
定期手動釋放緩衝
以上措施均不能有效應對記憶體片段化時,您還可以在業務空閑時段執行釋放緩衝(
drop cache
)的操作,然後記憶體會重新分配。釋放緩衝是避免記憶體片段化的有效措施,但在執行釋放緩衝時會出現短時間的系統效能抖動。手動釋放緩衝的命令如下:echo 3 > /proc/sys/vm/drop_caches