CassandraでOSが不安定になったので調査したらLinuxメモリ管理設定が原因だった

事象

Casssandra起動してから、ある一定期間経つと突然nodetoolがとても遅くなり、ring情報見るだけでも10秒ほどかかる場合も出ていました。CassandraだけでなくOS全体が不安定になり、SSH経由の操作すらも遅くなる事象が発生しました。

Nagiosで監視をしているのですが、nrpe自体や個別のコマンドが遅くなるのでTimeOutのアラートがいくつも飛んできて何度も夜中に起こされました。

CPUやメモリ、Diskもぱっと見た数字上では余裕があり、処理自体も遅くなっていない状態。Cassandraを再起動すると解消する。ただ、再起動後数日経過するとまた同じ事象が起こるという具合でした。

環境

S/W

S/W的には以下の環境です。

$ cat /etc/redhat-release
CentOS release 6.4 (Final)
$ uname -r
2.6.32-358.el6.x86_64
$ nodetool -hlocalhost version
ReleaseVersion: 1.0.11
$ java -version
java version "1.6.0_39"
Java(TM) SE Runtime Environment (build 1.6.0_39-b04)
Java HotSpot(TM) 64-Bit Server VM (build 20.14-b01, mixed mode)

H/W

H/W的には古いサーバでは起こらず、比較的新しいサーバでのみ事象が発生していました。

原因

色々調べた結果から書くと、メモリの回収処理(reclaim)が詰まってしまっているのが原因でした。

perf recordコマンドでkernelの処理確認すると、

# perf record -F 99 -g -a -- sleep 30
# perf report

メモリ関連の処理で不自然に時間かかっていることがわかりました、shrink_inactive_listとかisolate_lru_pages.cloneとか。

更にsar -Bを見るとDirect Reclaimによる大量のPage Scan(pgscand)をしているにも関わらず、ほとんどページが確保できていない(pgsteal)のがわかりました。

pgscandpgstealから計算されたvmeffは30%以下は少ないと言われているのですが、ここでは0.1%以下であることも少なくありません。

そして、このDirect Reclaimは同期処理なので、ページ確保できるまでプロセスに待ちが発生していると考えられます。

通常はkswapdというkernelのデーモンがバックエンド非同期でページ回収してくれていると思っていたので(以下で言うとpgscank)何かおかしいと感じました。

$ sar -B
140701秒  pgpgin/s pgpgout/s   fault/s  majflt/s  pgfree/s pgscank/s pgscand/s pgsteal/s    %vmeff
140801秒    655.63     30.83   2662.59      8.29   1522.72      0.00 638273.75    168.05      0.03
140901秒    539.37     14.31    716.82      6.69    426.47      0.00 1875896.07    160.74      0.01
141001秒    455.73     13.63    190.68      5.38    615.35      0.00 3670099.57    136.37      0.00
141101秒    454.44     12.17     89.00      5.32    155.59      0.00  35332.69     59.10      0.17
141201秒    472.06     15.51   1310.03      5.43   1033.46      0.00 1864225.67    237.58      0.01
141301秒    563.48     14.52    102.78      6.71    415.28      0.00 2596664.08     50.05      0.00
141402秒    589.45     12.08    120.35      6.70    214.24      0.00 105146.50     94.81      0.09
141501秒    486.19     11.56    125.22      5.71    240.56      0.00  71915.65    126.72      0.18
141601秒    452.47     11.56     91.90      5.26    316.78      0.00  35276.47     10.66      0.03

対策 Direct Reclaimを避ける

何故、ここまで多くのDirect Reclaimが発生しているかと思って調べていったところ、こちらの記事に当たりました。

engineering.linkedin.com

ここに記載のあるzone_reclaim_modeが有効化されているとDirect Reclaimが実行されるようです。

調べたところ確かに、NUMAでかつzone_reclaim_mode=1の設定がされているサーバで事象が発生しているのが確認できました。

NUMAかどうかはnumastatnumactl -Hとかでnodeが複数表示されるかで判断できます。nodeが複数あればNUMA構成のサーバです。

Cassandraでもzone_reclaim_modeを無効化するべきと、Datastaxのページにもしっかり書いてありました。

docs.datastax.com

Linuxカーネルは、zone_reclaim_modeの有効化/無効化が一貫していないことがあります。この結果、パフォーマンスに予期しない問題が生じることがあります。

ということでzone_reclaim_modeを無効化する作業を行いました。

設定方法

zone_reclaim_modeが有効化されていることの確認

# cat  /proc/sys/vm/zone_reclaim_mode   
1

適当な名前でsysctl.dのファイルを作成してsysctlコマンドで反映させます。

# vi /etc/sysctl.d/numa_optimization.conf
vm.zone_reclaim_mode=0

# sysctl -p /etc/sysctl.d/numa_optimization.conf

再起動無しでも反映されるはずです。

# cat  /proc/sys/vm/zone_reclaim_mode   
0

結果

Direct Reclaim(pgscand)が無くなって、kswapdでページ回収がされいます。vmeffも高い値を保っています。

OSが不安定になる事象も発生しなくなりました。

19時10分01秒  pgpgin/s pgpgout/s   fault/s  majflt/s  pgfree/s pgscank/s pgscand/s pgsteal/s    %vmeff
19時11分01秒    314.69     12.23    118.90      3.54    209.09    120.34      0.00    110.58     91.89
19時12分01秒    546.60     12.65   3963.30      6.36   1756.96    210.37      0.00    192.52     91.52
19時13分01秒    492.46     12.03     79.09      5.57    197.04    119.81      0.00    108.96     90.95
19時14分01秒    469.91     12.04    136.78      5.47    189.31    126.31      0.00    114.79     90.88
19時15分01秒    346.22     11.10    207.99      4.21    255.74    119.87      0.00    109.57     91.41
19時16分01秒    420.94     11.91    124.01      4.78    107.71      0.00      0.00      0.00      0.00
19時17分01秒    449.21     12.84   3962.40      5.12   1825.96    259.98      0.00    237.26     91.26
19時18分01秒    448.44     13.51     78.63      5.07     98.60      0.00      0.00      0.00      0.00
平均値:     623.25     15.07   1068.97      7.38    643.41    174.10      0.00    156.45     89.86

その他のチューニング項目

上記のメモリ回収のチューニングでOSが不安定になるという事象は解消したのですが、せっかくなのでいくつかメモリ周りのチューニングも行いました。

もう一つ気になっていたのがmin_free_kbytesが90MB程度なのに対して、常に4GB程度未使用のメモリがあるということです。

$ cat /proc/sys/vm/min_free_kbytes
90112

メモリの断片化起きてそうということでbuddyinfo見ました。連続した空き領域が確認できます。左から4K、8K、16K....4Mという並びです。小さい空き領域が多いと断片化が進んでいます。左側の数字が大きいので結構断片化起きているように見えます。

$ cat /proc/buddyinfo
Node 0, zone      DMA      0      1      1      1      1      0      1      0      1      1      3
Node 0, zone    DMA32   9989   4420   1167    155     10      1      3      2      2      8    245
Node 0, zone   Normal  61577  51053  75974   9744    297     42      7      4     15      1      0
Node 1, zone   Normal 104937 146173  47587   2124    114     17      8      5     36      1      0

対策② HugePage

まず、Cassandra(というかJVM)はHugePageに対応しているのでHugePageの設定を行いました。

設定方法はこちらを参照 https://tobert.github.io/tldr/cassandra-java-huge-pages.html

対策③ THP無効化

ついでにTHPもDirect Reclaim起こすらしいので、こちらも無効化しました。RedhatもDBでのTHPは推奨してないです。

5.2. Huge pages および transparent huge pages

ただし、THP はデータベースのワークロードには推奨されません。

設定方法はこちらの記事に纏まっていました。

Transparent HugePagesを無効化する - 人生は、お天気いろいろ

結果②・③

まず、Muninのグラフ見てみると、設定内容通りにメモリが使われずに常に空きメモリが多くのこってしまっていました(グラフ左側の円)。チューニング(16時頃)後はほとんどのメモリがキャッシュで使われていることがわかります(グラフ右側の円)

f:id:yomon8:20160810195120p:plain

buddyinfo見てもかなりキレイになりました。

$ cat /proc/buddyinfo
Node 0, zone      DMA      0      1      1      1      1      0      1      0      1      1      3
Node 0, zone    DMA32    365    158     79     59     48     37      6      3      3      2     10
Node 0, zone   Normal   3612    639    778    349     86     25      8      2      2      1      0
Node 1, zone   Normal   4051    847    423    263    209     59     22      3      0      1      0

参考にした情報

カーネルソースコード

https://www.kernel.org/pub/linux/kernel/v2.6/

SlideShare

http://www.slideshare.net/siburu/page-reclaim Transparent Hugepages in RHEL 6

WEB Page

https://www.kernel.org/doc/Documentation/sysctl/vm.txt

https://www.kernel.org/doc/Documentation/vm/transhuge.txt

書籍