,jedis用接続プール時タイムアウト戻り値タイプエラー
これは今日発見されたバグです:redisの同時読み書きをテストする時(jedisはクライアントとして、接続プールを使用しています)、いつもjavaを報告します.lang.ClassCastException: java.util.ArrayList cannot be cast to java.lang.Long
at redis.clients.jedis.Connection.getIntegerReply(Connection.java:161)
at redis.clients.jedis.Jedis.del(Jedis.java:108)
同様のエラーは、戻り値タイプがドキュメント上の戻り値タイプと一致せず、不自然な感じがすることです.最初はjedisが実現したバグであることを疑い、その後、タイムアウト異常を投げたとき、後ろに上記のようなエラーが連続して発生し、最後にやっと問題点を発見した.
元のコードは次のとおりです.
このように書くのはOKのようですが、実際に問題があります.仮にjedisがこのコマンドを実行している間に、redis過負荷のためjedisがタイムアウトした異常を返す可能性があります.このとき何が起こったのか、この異常を処理せずに、このjedisのリンクを直接接続プールに戻したとしたら、問題はありませんか.
jedisソースコードを表示すると、彼のconnectionにはネットワーク出力ストリームがカプセル化されていることがわかります.その中にbufferが独自に構築されているので、異常が発生したとき、このbufferには前回送信されなかったコマンドや不完全なコマンドが残っています.このときは処理されず、その接続を接続プールに戻します.この接続を再利用して次のコマンドを実行すると、前回送信されなかったコマンドと一緒に送信されます.したがって、上記のエラー「戻り値タイプが間違っています」が発生します.
だから正しい書き方は、異常を送信したときに、この接続を破棄し、再利用できないはずです.
正しい書き方は以下の通りです.
以上の分析から、jedisが実現したバグだと思いますが、接続に異常が発生した場合、その接続のbufferをクリアすべきだと思いますが、どう思いますか?
at redis.clients.jedis.Connection.getIntegerReply(Connection.java:161)
at redis.clients.jedis.Jedis.del(Jedis.java:108)
同様のエラーは、戻り値タイプがドキュメント上の戻り値タイプと一致せず、不自然な感じがすることです.最初はjedisが実現したバグであることを疑い、その後、タイムアウト異常を投げたとき、後ろに上記のようなエラーが連続して発生し、最後にやっと問題点を発見した.
元のコードは次のとおりです.
public long del(String key) {
long rt = 0L;
Jedis jedis = null;
try {
jedis = getJedis();
rt = jedis.del(key);
}
finally
{
releaseJedisInstance(jedis);
}
return rt;
}
このように書くのはOKのようですが、実際に問題があります.仮にjedisがこのコマンドを実行している間に、redis過負荷のためjedisがタイムアウトした異常を返す可能性があります.このとき何が起こったのか、この異常を処理せずに、このjedisのリンクを直接接続プールに戻したとしたら、問題はありませんか.
jedisソースコードを表示すると、彼のconnectionにはネットワーク出力ストリームがカプセル化されていることがわかります.その中にbufferが独自に構築されているので、異常が発生したとき、このbufferには前回送信されなかったコマンドや不完全なコマンドが残っています.このときは処理されず、その接続を接続プールに戻します.この接続を再利用して次のコマンドを実行すると、前回送信されなかったコマンドと一緒に送信されます.したがって、上記のエラー「戻り値タイプが間違っています」が発生します.
だから正しい書き方は、異常を送信したときに、この接続を破棄し、再利用できないはずです.
正しい書き方は以下の通りです.
public long del(String key) {
long rt = 0L;
Jedis jedis = null;
try {
jedis = getJedis();
rt = jedis.del(key);
releaseNormalResource(jedis);
} catch (Exception e) {
returnBrokenResource(jedis);
throw Exception x;
}
return rt;
}
以上の分析から、jedisが実現したバグだと思いますが、接続に異常が発生した場合、その接続のbufferをクリアすべきだと思いますが、どう思いますか?