Redisプロセス異常チェックアウトを終了

6664 ワード

Redisプロセス異常チェックアウトを終了
一、考え方を調べる
1.システムメモリ不足のためoom killerに殺されたかどうか.
oom killerが殺した場合、一般的に/var/log/*にログが残り、dmesgでも調べられるはずで、コマンドで検索できます.
dmesg | egrep -i 'killed process'
grep oom /var/log/*
grep total_vm /var/log/*

メモリ不足でoom killerに殺された場合は、次のように考えられます.
  • システムメモリを増やす;
  • redisを修正する.conf配置、合理的なmaxmemoryを設置し、機械が20%~30%のアイドルメモリを保証し、適切な回収戦略を使用する.
  • maxmemory 512mb
    maxmemory-policy volatile-lru
    
  • redisプロセスのoom adjスコアを下げる.

  • 「OOM killerは、使用可能なメモリが不足している場合にユーザープロセスを選択的に殺します.その実行ルールはどのようにして、どのユーザープロセスが「手をつける」かを選択します.OOM killerプロセスは、ユーザプロセスごとに重み値を設定します.この重み値が高いほど、「手をつける」確率が高くなり、逆に確率が低くなります.各プロセスの重み値は/proc/{progress_id}/oom_に格納されます.scoreでは、この値は/proc/{progress_id}/oom_adjの制御、oom_adjは異なるLinuxバージョンの最小値が異なり、Linuxソースコードのoomを参照することができる.h(-15から-17まで).oom_adjが最小値に設定されている場合、プロセスはOOM killerによって殺されません.」
    設定方法は次のとおりです.
    echo -17 > /proc/${process_id}/oom_adj
    
  • redisのメモリ使用と設定を最適化する.詳細は以下の説明および文末の関連リンクを参照してください.

  • 2.誰かにキルされていないか
  • 人為的なkillプロセスであれば、lastとhistoryの記録を検索し、何がユーザーにログインしていつ殺されたのかを確認することができる.
  • システムにauditがインストールされている場合はausearch検索コマンドレコードも使用可能:
  • ausearch -sc kill
    

    3.redis-cliがshutdownコマンドを送信したためか
    cliが送信したshutdownコマンドがredisを終了させた場合、redis自体のlogには次のような記録があります.
    3803:S 11 Oct 18:12:51.251 # User requested shutdown...
    3803:S 11 Oct 18:12:51.251 * Removing the pid file.
    3803:S 11 Oct 18:12:51.252 # Redis is now ready to exit, bye bye...
    

    まだredis logを開いていない場合はredis.confでパスを指定して再起動します.
    dir "/opt/redis-4.0.9/redis-cluster/7000"
    

    プロセスがcliによってリモートで閉じることを避けるには、パスワードを設定したり、redisに設定したりすることができます.confではshutdownコマンドを無効にし、後者を選択します.
    rename-command SHUTDOWN ""
    

    4.redis自体のバグによるクラッシュの有無
  • システムulimitを設定し、プロセスクラッシュ時にcore dumpを生成する:
  • ulimit -c unlimited
    

    変更/etc/sysctl.confファイルは、core dumpファイルが生成する名前とパスを指定する構成を追加します.
    kernel.core_uses_pid = 1
    kernel.core_pattern = /var/core/core_%e_%p
    

    注意linuxリリースによって設定方法が少し異なります.
  • straceコマンドを使用してプロセス動作を追跡:
  • screen -S redis_trace_7000
    strace -T -tt -e trace=all -p `ps -ef|grep redis|grep 7000|grep -v -i screen|grep -v grep|awk '{split($0,a);print a[2]}'`
    

    そしてctrl-a dはscreenを終了する
  • gdb attachを使用してredisプロセス
  • 同様に独立したscreenを使用してgdbを実行することを推奨します.また、gdbはptraceを使用する必要があります.ptrace: Operation not permittedのエラーが検出された場合は、straceコマンドなどのptraceコマンドを使用している他のプロセスを閉じる必要があります.
    gdb /usr/local/bin/redis-server 58414
    (gdb) continue
    

    redis-cliを使用してserverに接続し、debug segfaultコマンドを送信するとredis serverがクラッシュします.この場合、btを使用してスタック情報を表示できます.
    (gdb) bt
    #0  debugCommand (c=0x7ffc32005000) at debug.c:220
    #1  0x000000010d246d63 in call (c=0x7ffc32005000) at redis.c:1163
    #2  0x000000010d247290 in processCommand (c=0x7ffc32005000) at redis.c:1305
    #3  0x000000010d251660 in processInputBuffer (c=0x7ffc32005000) at networking.c:959
    #4  0x000000010d251872 in readQueryFromClient (el=0x0, fd=5, privdata=0x7fff76f1c0b0, mask=220924512) at networking.c:1021
    #5  0x000000010d243523 in aeProcessEvents (eventLoop=0x7fff6ce408d0, flags=220829559) at ae.c:352
    #6  0x000000010d24373b in aeMain (eventLoop=0x10d429ef0) at ae.c:397
    ......
    

    info registersを使用してレジスタ情報を表示する
    (gdb) info registers
    rax            0x0  0
    rbx            0x7ffc32005000   140721147367424
    rcx            0x10d2b0a60  4515891808
    rdx            0x7fff76f1c0b0   140735188943024
    rsi            0x10d299777  4515796855
    rdi            0x0  0
    rbp            0x7fff6ce40730   0x7fff6ce40730
    rsp            0x7fff6ce40650   0x7fff6ce40650
    r8             0x4f26b3f7   1327936503
    r9             0x7fff6ce40718   140735020271384
    r10            0x81 129
    ......
    

    最後に、gcoreを使用してcore dumpファイルを生成します.
    (gdb) gcore
    Saved corefile core.58414
    

    二、メモリ使用の最適化
  • キー値削減オブジェクト条件が許す場合は文字列長を39バイト以内に抑えることを推奨し、redisObjectメモリの作成回数を減らす.キー(key)と値(value)の長さを縮小します.key長:キーを設計する場合、ビジネスを完全に記述する場合、キー値が短いほど良い.value長:値オブジェクトの縮小は複雑で、ビジネスオブジェクトをバイナリ配列にシーケンス化してRedisに入れるのが一般的です.まず、ビジネス上でビジネス・オブジェクトを簡素化し、不要なプロパティを削除して無効なデータを格納しないようにします.次に、シーケンス化ツールの選択では、バイト配列のサイズを低減するために、より効率的なシーケンス化ツールを選択する必要があります.メモリが緊張している場合、汎用圧縮アルゴリズムを使用してjsonを圧縮し、xml後にRedisに格納することで、メモリ占有量を低減することができ、例えばGZIP圧縮後のjsonを使用すると約60%の空間を低減することができる.
  • 共有オブジェクトプール共有オブジェクトプールを使用する.整数オブジェクトプールはRedisで変数REDIS_を通過するSHARED_INTEGERS定義は、構成では変更できません.オブジェクトrefcountコマンドを使用して、オブジェクト参照数を表示して、整数オブジェクトプールテクノロジーが有効かどうかを確認できます.共有オブジェクトプールを使用すると、同じデータメモリの使用量が30%以上減少します.データが[0-9999]の整数を大量に使用する場合、共有オブジェクトプールは大量のメモリを節約できることがわかります.注意:maxmemoryを設定し、LRU関連の淘汰ポリシー(volatile-lru、allkeys-lruなど)を有効にすると、Redisは共有オブジェクトプールの使用を禁止します.
  • 文字列最適化append,setrangeのような文字列の頻繁な修正操作を最小限に抑え、setを直接使用して文字列を修正することに変更し、事前割り当てによるメモリの浪費とメモリの断片化を低減する.
  • 符号化最適化性能が要求されるシーンに対してziplistを使用し、長さは1000を超えないことを推奨し、各要素サイズは512バイト以内に制御する.intset符号化は、セットに整数のみが含まれ、set-max-intset-entries構成を超えない場合に使用されます.多数の小さなオブジェクトのストレージシーンでは、ziplist符号化hashタイプの制御キーを使用してメモリを低減するのに適しています.

  • 三、参考資料
    Redis最大使用メモリRedisのメモリ最適化Redis無効化コマンド、危険コマンドおよび回避方法Redis debugging guide Playing with ptrace,Part I神器strace,ltrace How to disable Redis RDB?Redis研究(19)—コマンド属性Virtual memory settings in Linux-The Problem with Overcommit What is the logic behind killing processes during an Out of Memory situation?How to reproduce a condition which invokes the OOM-Killer ?