redisに大量の汚れページの問題がある追跡記録
4774 ワード
転載先:https://www.zybuluo.com/SailorXiao/note/136014
ケース現場
オンラインで1台の機械のメモリ負荷が重いことを発見して、topの後で1つのredisプロセスが大量のメモリを占めていることを発見して、TOPの内容は以下の通りです:
redisが18.6 Gの物理メモリを占めていることが分かった.redisはcacheのプログラムデータにしか使用されていないので不思議ですが、redisのinfoコマンドを実行すると、実際のデータ占有量は112 Mしかないことがわかりました.以下のようにします.
そこでpmap-x 27190を用いてredisプロセスのメモリイメージ情報を表示し、結果は以下の通りである.
メモリの汚れたページが大量に存在することがわかりました.メモリ負荷の高い問題は、redisの汚れたページが大量のメモリを消費しているため、明らかになった.しかし、redisはなぜそんなに多くの汚れたページが存在するのだろうか.
ケース分析
linuxの汚れたページの定義を見ました.
つまり、汚れたページは、メモリ内の多くのデータがディスクに更新されないためです.linuxシステムの汚れたページflushメカニズムを見ました.http://blog.chinaunix.net/uid-17196076-id-2817733.htmlメモリflushとの設定が可能であることがわかりました(/proc/sys/vmの下)
現在のシステムのflush構成を確認します.問題はありません.dirty_background_ratioは10%、dirty_ratioは20%、dirty_writeback_centisecsは5 s、dirty_expire_centisecsは30 sですが、なぜredisの汚れたページがflushにディスクに入らなかったのでしょうか.
一般的に汚れたページはメモリのデータflushをディスクに入れるのですが、redisの持続化が汚れたページを招いたのではないでしょうか.これらの構成についてredisを表示します.
以上のように、redis自体は完全に閉じて永続化されており、cacheとしてのみ使用され、最大メモリ使用のデフォルト値(制限なし)については、メモリの淘汰メカニズムはvolatile-lruであることが分かった.redisのドキュメントを参照して、対応する淘汰メカニズムを表示します.
現在の使用環境では、プログラムはredisの使用をcacheとし、データにexpireタイムアウト時間を設定し、期限切れになったらredisの削除を待つ.では、汚れたページの原因は、期限切れのデータクリーンアップメカニズムの問題(例えば、クリーンアップがタイムリーではないなど)ではないでしょうか.そのため、Redisが期限切れデータを削除する際に取ったポリシーを表示する必要があります.参照情報は、Redis内のメモリ解放と期限切れキー削除redis期限切れキーのクリアです.
redis期限切れキー削除メカニズム:
redisは、期限切れキー削除に不活性削除+定期削除+maxmemoryより大きい自動クリアのポリシーを使用します.
ケース位置決め
以上の分析を通じて、問題はすでに明らかになった.原因は以下の通りである.
何らかの理由により、redisが使用するメモリはますます大きくなる(不活性な削除によるexpireのデータの蓄積が多くなるか、またはredis内部の実装に依存する他の理由である可能性がある).
redisはcacheとしてのみ使用され、実際にファイルを読み書きしていないため、オペレーティングシステムはflushをディスクに支援しません(flushができる場所がないため)redisはmaxmemoryを設定していないため、デフォルトはマシンのメモリサイズであり、redis自身が使用するメモリがマシンのメモリに達した場合にのみ、redis自身がクリーンアップ(volatile-lruメカニズム)を行う.
従って、現在のredisのメモリはますます大きくなり、汚れたページのデータはますます多くなり(ほとんどが期限切れのデータである可能性がある)ケース解決
この問題を解決するために、比較的便利で合理的な方法は:
不活性削除は頼りにならない場合がありますが、特にいくつかのlogタイプのデータについては、redisに書き込むと無視され、タイムアウト時間が設定されていますが、効果はありません.
定期的な削除はexpire-keysにもあまり頼りにならず、ランダム性があり、期限切れのデータが削除されていない可能性があります.
対照的に、比較的合理的な方法は、使用状況に基づいてredisのmaxmemoryサイズを設定、redisに自身のデータクリーンアップメカニズムを実現させるために、memをmaxmemory設定範囲内に制限ことを確保することである.
ケース現場
オンラインで1台の機械のメモリ負荷が重いことを発見して、topの後で1つのredisプロセスが大量のメモリを占めていることを発見して、TOPの内容は以下の通りです:
27190 root 20 0 18.6g 18g 600 S 0.3 59.2 926:17.83 redis-server
redisが18.6 Gの物理メモリを占めていることが分かった.redisはcacheのプログラムデータにしか使用されていないので不思議ですが、redisのinfoコマンドを実行すると、実際のデータ占有量は112 Mしかないことがわかりました.以下のようにします.
# Memory
used_memory:118140384
used_memory_human:112.67M
used_memory_rss:19903766528
used_memory_peak:17871578336
used_memory_peak_human:16.64G
used_memory_lua:31744
mem_fragmentation_ratio:168.48
mem_allocator:libc
そこでpmap-x 27190を用いてredisプロセスのメモリイメージ情報を表示し、結果は以下の通りである.
27190: ./redis-server ../redis.conf
Address Kbytes RSS Dirty Mode Mapping
0000000000400000 548 184 0 r-x-- redis-server
0000000000689000 16 16 16 rw--- redis-server
000000000068d000 80 80 80 rw--- [ anon ]
0000000001eb6000 132 132 132 rw--- [ anon ]
0000000001ed7000 19436648 19435752 19435752 rw--- [ anon ]
00007f5862cb2000 4 0 0 ----- [ anon ]
メモリの汚れたページが大量に存在することがわかりました.メモリ負荷の高い問題は、redisの汚れたページが大量のメモリを消費しているため、明らかになった.しかし、redisはなぜそんなに多くの汚れたページが存在するのだろうか.
ケース分析
linuxの汚れたページの定義を見ました.
linux , , , , ,linux , , , , 。
つまり、汚れたページは、メモリ内の多くのデータがディスクに更新されないためです.linuxシステムの汚れたページflushメカニズムを見ました.http://blog.chinaunix.net/uid-17196076-id-2817733.htmlメモリflushとの設定が可能であることがわかりました(/proc/sys/vmの下)
dirty_background_bytes/dirty_background_ratio:
- (bytes ) , , ( bytes ,ratio )
dirty_bytes/dirty_ratio:
- (bytes ) , , ( bytes ,ratio )
dirty_expire_centisecs:
- ( ), dirty, flush 。 inode
dirty_writeback_centisecs:
- , dirty flush ( )
現在のシステムのflush構成を確認します.問題はありません.dirty_background_ratioは10%、dirty_ratioは20%、dirty_writeback_centisecsは5 s、dirty_expire_centisecsは30 sですが、なぜredisの汚れたページがflushにディスクに入らなかったのでしょうか.
一般的に汚れたページはメモリのデータflushをディスクに入れるのですが、redisの持続化が汚れたページを招いたのではないでしょうか.これらの構成についてredisを表示します.
rdb
# save 900 1
# save 300 10
# save 60 10000
# append
appendonly no
# 、
# maxmemory
# maxmemory-policy volatile-lru
以上のように、redis自体は完全に閉じて永続化されており、cacheとしてのみ使用され、最大メモリ使用のデフォルト値(制限なし)については、メモリの淘汰メカニズムはvolatile-lruであることが分かった.redisのドキュメントを参照して、対応する淘汰メカニズムを表示します.
volatile-lru: (server.db[i].expires) ( )
volatile-ttl: (server.db[i].expires)
volatile-random: (server.db[i].expires)
allkeys-lru: (server.db[i].dict)
allkeys-random: (server.db[i].dict)
no-enviction:
現在の使用環境では、プログラムはredisの使用をcacheとし、データにexpireタイムアウト時間を設定し、期限切れになったらredisの削除を待つ.では、汚れたページの原因は、期限切れのデータクリーンアップメカニズムの問題(例えば、クリーンアップがタイムリーではないなど)ではないでしょうか.そのため、Redisが期限切れデータを削除する際に取ったポリシーを表示する必要があります.参照情報は、Redis内のメモリ解放と期限切れキー削除redis期限切れキーのクリアです.
redis期限切れキー削除メカニズム:
:
- expire , , , , , 。
:
- cron , db expire-keys key( 20 ), key 。 ,
- , CPU 。
maxmemory :
- client server command ,server maxmemory
- max-memory, , maxmemory
- (LRU,TTL,RANDOM )
redisは、期限切れキー削除に不活性削除+定期削除+maxmemoryより大きい自動クリアのポリシーを使用します.
ケース位置決め
以上の分析を通じて、問題はすでに明らかになった.原因は以下の通りである.
何らかの理由により、redisが使用するメモリはますます大きくなる(不活性な削除によるexpireのデータの蓄積が多くなるか、またはredis内部の実装に依存する他の理由である可能性がある).
redisはcacheとしてのみ使用され、実際にファイルを読み書きしていないため、オペレーティングシステムはflushをディスクに支援しません(flushができる場所がないため)redisはmaxmemoryを設定していないため、デフォルトはマシンのメモリサイズであり、redis自身が使用するメモリがマシンのメモリに達した場合にのみ、redis自身がクリーンアップ(volatile-lruメカニズム)を行う.
従って、現在のredisのメモリはますます大きくなり、汚れたページのデータはますます多くなり(ほとんどが期限切れのデータである可能性がある)ケース解決
この問題を解決するために、比較的便利で合理的な方法は:
不活性削除は頼りにならない場合がありますが、特にいくつかのlogタイプのデータについては、redisに書き込むと無視され、タイムアウト時間が設定されていますが、効果はありません.
定期的な削除はexpire-keysにもあまり頼りにならず、ランダム性があり、期限切れのデータが削除されていない可能性があります.
対照的に、比較的合理的な方法は、使用状況に基づいてredisのmaxmemoryサイズを設定、redisに自身のデータクリーンアップメカニズムを実現させるために、memをmaxmemory設定範囲内に制限ことを確保することである.