JedisのUnexpected end of streamソリューション


JedisのUnexpected end of streamソリューション
  • redisサービス側バージョン番号:2.8.X
  • Jedisクライアントバージョン番号:2.8.1
  • 単一スレッド、同時動作なし
  • Jedisシングルリンク、JedisPool、ShardedJeddisPoolは、いずれの方法でredisサービスを操作してもUnexpected end of streamという問題が発生しています.
    ソースコードを確認すると、エラーの特定の場所は、RedisInputStreamクラスのensureFill()メソッドです.
    private void ensureFill() throws JedisConnectionException {
        if (count >= limit) {
          try {
            limit = in.read(buf);
            count = 0;
            if (limit == -1) {
              throw new JedisConnectionException("Unexpected end of stream.");
            }
          } catch (IOException e) {
            throw new JedisConnectionException(e);
          }
        }
      }

    ソリューション:
    第1ステップでは、redis configのclient-output-buffer-limit構成を確認します.
    client-output-buffer-limit normal 0 0 0
    client-output-buffer-limit slave 0 0 0
    client-output-buffer-limit pubsub 0 0 0

    実際の状況に応じてRedis出力バッファ制限を合理的に設定してください.バッファが小さすぎてリンクが閉じたのではなく、Unexpected end of streamを引き起こしたのではないかと判断してください.一時的に「0(バッファ制限を閉じる)」に設定して、このようなシーンを検証することができます.
    ステップ2では、redis configのtimeout構成を確認します.
    この時間が短すぎると、同じjedisリンクがredisサービスに2回アクセスする間隔>${timeout}となり、サービス側は一方的にこのjedisリンクを閉じ、2回目にこのjedisオブジェクトを使用してredisを操作するとUnexpected end of streamが発生し、「0(期限切れなし)」に設定してこのシーンを検証できます.
    第3歩、クライアントコードを最適化し、再試行メカニズムを増加する
    前の2段階のデバッグを経て、業務の実情に応じて配置を調整するが、Unexpected end of streamの発生を完全に根絶することはできない.例えば、「ネットワークジッタ」のようなシーンでは、依然としてこの問題が発生する(実際の生産環境では、このような状況が発生する確率は極めて低い)が、この異常によるjvmダウンタイムを防止するために、コードレベルで再試行メカニズムを増やすことを提案する.
    話外編:
    Redisをストレージ・レイヤとして使用すると、数データが一致しない場合があります(redisにトランザクションはありません)
    参照先:
    https://github.com/xetorthio/jedis/issues/932
    https://github.com/xetorthio/jedis/issues/1029