心の中でバグが時折バグの調査は、ライブラリ-PY-クラスタ--redis

 アカウントを実行している調査:
  1. プラットフォームを監視することで、我々は多くの臨時のビューを推奨インターフェース遅延のリストが0.5秒以上であることがわかりました
  2. ユニットテストを書く、再現することはできません。テスト環境で再現することはできません。唯一の散発的なフォーマルな環境を再現することができます。
  3. 再現するために待機して、ログに埋もれ
  4. 継続的にログを追加した後埋葬発見は、Redisののhmget操作をしました
    1. それから私は、その理由を推測します
      1. hmgetコマンドがあります、それは問題のhmgetコマンドではありません
      2. スロークエリログRedisのビュー、および何の遅いクエリを見つかりませんでした。Redisのが遅い実装の理由を除外
      3. 現在の負荷を表示、負荷が低く、多くはない同時です。だから、Redisのは、待機の理由をコマンド除外
      4. マルチコルーチン、20 hmgetは、いないすべてのカードは、カードはほんの数は、それが正常に戻ってますでしょう
      5. Hmget通常の使用には、周りの0.01秒、カードに必要な0.3-0.9sです
      6. 自分のスクリプトを書く、hmgetを実行するために、マルチコルーチンを使用し続け、再現することはできません。
    2. ソリューションを推測:
      1. 3〜20、マルチコルーチンプールの数を変更します
      2. ユーザー情報を取得する代わりに、シリアル
  5. コードJiamaiポイントログ内のコマンドをhmgetを続行
    1. それは、サードパーティのライブラリを修正しているので、とても気をつけて
    2. ソースコードを読み取ることにより、基本的なプロセスhmgetは、クライアントファイルrediscluster機能EXECUTE_COMMAND内部のモジュールの中に発見されます
    3. 修正後は、何の問題の後、テスト対象のテスト環境ユニットは、正式な環境にデプロイ
  6. ()内にあることを最終的な位置決めをSelf.connection_pool.nodes.initializeするコード行を取ります
  7. refresh_table_asap = trueがソリューションので、このコード行を実行する場合にのみ
    1. なぜrefresh_table_asapはtrueに等しくなります
      1. 場合にのみ、エラーがRedisのClusterDownErrorまたはMovedErrorを接続するときは真refresh_table_asap =を設定することを発見
      2. ログに埋もれ。MovedErrorは異常によって引き起こされることが判明しました。
      3. 埋没ログを増加し続けると、全体のプロセスがトリガされることがわかりました。
        1. トリガー異常ConnectionError
        2. 設定しtry_random_node =真
        3. 次回は、ランダムなノードを取り、この時間は、間違ったノードのスロットを得ることができます
        4. ノードを接続した後、それは異常なMovedErrorが報告され、ターゲット・ノードに戻って情報を送信し、真refresh_table_asap =を設定します。
        5. この時点でスロットは背面にノード情報に対応するノードを設定します
        6. ノードを再接続し、成功したコマンドを実行します
        7. しかし、この時間が設定されているrefresh_table_asap = Trueの場合、次のコマンドを実行するときにself.connection_pool.nodes.initializeに実行されます()
        8. マルチコルーチン、およびself.connection_pool.nodes.initialize()コマンドの使用に起因するがロックされていない、それが増加し、時間がかかるにつながります
      4. 印刷トレースバックすることで、なぜ異常なトリガーConnectionError参照、Redisのサーバーが切断されました。
      5. この時点ではRedisのメカニズムがあることを思い出して、来て一定の時間をかけて指令がない、それは接続を閉じます。タイムアウト設定のRedis、通常は300秒で。これは散発的である理由だから、これは説明しています。
      6. 接続を確立した後、ユニットテストを記述し、コマンド待ち350S、安定的かつ再現性のあるバグを実行します。
    2. なぜそんなに遅いがかかり初期化
      1. 初期化コマンドが遅いではないテストによって、およそ0.04sを行うことができるよりも大きいが、マルチコルーチンは約0.5秒です。
      2. ないロックが存在しないので、コルーチン複数のこのコマンドが実行されるようにそのため、考慮すべきことは、元の10倍で最終結果と、、、マルチコルーチンであります
  8. Redisのは、テストケースを書いて、=の5Sをタイムアウトテスト環境を変更し、テスト環境で再現するために安定化させることができます。
  9. だから、rediscluster問題、解決策を見つけます
    1. 複数のRedisのコルーチン上でコマンドを実行しないでください(悪い感じ)
    2. 私は解決することができるかどうかを確認し、ライブラリをアップグレードします。このライブラリのgitのアドレス(閲覧https://github.com/Grokzen/redis-py-cluster)の最新バージョンを、問題がまだ存在しています。
    3. それはtry_random_node = trueの場合、再試行提供されない場合、サーバが切断されているかどうかを区別する場合catchConnectionError異常
    4. ロックされたときのinit
    5. 再接続するには切断サーバーの例外の再試行でキャッチの練習を参照することによりRedis.py
  10. 思考5の最終的な選択。
redisclusterライブラリclient.pyでEXECUTE_COMMAND機能(不要なコードセグメントを除去することをさらに含む、埋込みログ)
@clusterdown_wrapper
デフEXECUTE_COMMAND(自己、* argsを、** kwargsから):
    「」」
    クラスタ内のノードにコマンドを送信します
    「」」
    インポートのログ
    ログイン= logging.getLogger( 'service.logに')
    log.error(u'redis EXECUTE_COMMAND 1%S '%のSTR(引数))
 
    外部から設定されている場合#我々は、任意のコマンドを呼び出す前に、それを更新する必要があります
    もしself.refresh_table_asap:self.connection_pool.nodes.initializeを行う#のコードセグメント()の
        log.error(u'redis EXECUTE_COMMAND 2%S '%のSTR(引数))
        self.connection_pool.nodes.initialize()
        log.error(u'redis EXECUTE_COMMAND 3%S '%のSTR(引数))
        self.refresh_table_asap =偽
    log.error(u'redis EXECUTE_COMMAND 4%S '%のSTR(引数))
 
    redirect_addr =なし
    = Falseを求めて
 
    try_random_node =偽
    log.error(u'redis EXECUTE_COMMAND%S '%のSTR(引数))
    スロット= self._determine_slot(*引数)
    log.error(u'redis EXECUTE_COMMAND 8%S '%のSTR(引数))
    TTL = INT(self.RedisClusterRequestTTL)
 
    しばらくTTL> 0:
        TTL  -  = 1
 
 
        求めている場合:
            ノード= self.connection_pool.nodes.nodes [redirect_addr]
            R = self.connection_pool.get_connection_by_node(ノード)
        elifのtry_random_node:
            R = self.connection_pool.get_random_connection()
            try_random_node =偽
        他:
            self.refresh_table_asap場合:
                #MOVED
                ノード= self.connection_pool.get_master_node_by_slot(スロット)
            他:
                ノード= self.connection_pool.get_node_by_slot(スロット)
            R = self.connection_pool.get_connection_by_node(ノード)
 
        試してみてください。
              r.send_command(*引数)
              log.error(u'redisはEXECUTE_COMMAND 10%S '%のSTR(引数))
              RET = self.parse_response(R、コマンド、** kwargsから)
              log.error(u'redisはEXECUTE_COMMAND 11%S '%のSTR(引数))
              右を返します
 
        (RedisClusterException、BusyLoadingError)を除きます:
            上げます
        (ConnectionError、TimeoutError)を除きます:
            try_random_node =真
            log.error(u'redisはEXECUTE_COMMAND 14%S '%のSTR(引数))
            TTL <self.RedisClusterRequestTTL / 2の場合:
                log.error(u'redisはEXECUTE_COMMAND 15%S '%のSTR(引数))
                time.sleep(0.1)
        eとClusterDownError除きます:
            log.error(u'redisはEXECUTE_COMMAND 17%S '%のSTR(引数))
            self.connection_pool.disconnect()
            self.connection_pool.reset()
            self.refresh_table_asap =真
            上げ、
        eとMovedError除きます:
            MovedErrorのこれまでのx個の#再初期化。
            #このカウンタは速く増加したときに、同じクライアントオブジェクト
            #は、複数のスレッド間で共有されています。頻度を減らすために、あなた
            #は、コンストラクタで変数「reinitialize_steps」を設定することができます。
            輸入トレースバック
            印刷traceback.format_exc()
            log.error(u'redisはEXECUTE_COMMAND 16%S '%のSTR(引数))
            self.refresh_table_asap =真
            self.connection_pool.nodes.increment_reinitialize_counter()
 
 
            ノード= self.connection_pool.nodes.set_node(e.host、e.port、SERVER_TYPE = 'マスター')
            self.connection_pool.nodes.slots [e.slot_id] [0] =ノード
 

 

最適化:

ザ・
              r.send_command(*引数)
              RET = self.parse_response(R、コマンド、** kwargsから)
              右を返します

変更

試してみてください。
    r.send_command(*引数)
    リターンself.parse_response(R、コマンド、** kwargsから)
eとConnectionError除きます:
    redis.connectionインポートSERVER_CLOSED_CONNECTION_ERRORから
    e.messageでSERVER_CLOSED_CONNECTION_ERROR場合:
        r.disconnect()
        r.send_command(*引数)
        リターンself.parse_response(R、コマンド、** kwargsから)
    他:
        上げます
 

 許可なしに、転載しないでください

おすすめ

転載: www.cnblogs.com/Xjng/p/11767101.html