この記事では、Redis クライアントの一般的な例外の概要を紹介します (Jedis の記事)。一定の参考値があるので、困っている友達が参考になれば幸いです。
[はじめに] Jedis は、Java バージョンの Redis のクライアント実装です。 Redis クライアントの使用中、クライアントが不適切に使用されているか、Redis サーバーに問題があるかにかかわらず、クライアントはいくつかの例外に応答します。この記事では、Jedis の使用中に発生する一般的な例外を分析します。 [関連する推奨事項: Redis ビデオ チュートリアル ]
1. 接続プールから接続を取得できません
JedisPool 内の Jedis オブジェクトの数は制限されており、デフォルトは 8 です。ここではデフォルト設定が使用されることを想定しており、8 つの Jedis オブジェクトが占有されて返されない場合、呼び出し元が JedisPool から Jedis を借用したい場合は、待機する必要があります (たとえば、maxWaitMillis>0 が設定されている場合)。 maxWaitMillis 時間以内に Jedis オブジェクトを取得できない場合は、次の例外がスローされます。
redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool … Caused by: java.util.NoSuchElementException: Timeout waiting for idle object at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:449)
別の状況、つまり blockWhenExhausted=false が設定されている場合、呼び出し元がプールにリソースがないことを検出すると、待機せずにすぐに例外がスローされます。 blockWhenExhausted=false の効果。
redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool … Caused by: java.util.NoSuchElementException: Pool exhausted at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:464)
この問題に関して、議論する必要があるのは、接続プールにリソースがない理由です。リソースが不足している理由はさまざまに考えられます。
1. クライアント: 接続プールには、小さい場合、供給が需要を上回るため、上記のエラーが発生しますが、通常の状況では、JedisPool の処理効率が低下するため、通常の状況ではデフォルトの最大接続数 (8) を超えるだけで十分です。そしてジェダイは十分に高い。
2. クライアント: 接続プールが正しく使用されていません。たとえば、解放されていません。たとえば、次のコードに示すように: JedisPool を定義し、デフォルトの接続プール構成を使用します。
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig(); JedisPool jedisPool = new JedisPool(poolConfig, "127.0.0.1", 6379); //向JedisPool借用8次连接,但是没有执行归还操作。 for (int i = 0; i < 8; i++) { Jedis jedis = null; try { jedis = jedisPool.getResource(); jedis.ping(); } catch (Exception e) { e.printStackTrace(); } }
呼び出し元が接続プールから Jedis を借用すると (次のように)、例外がスローされます:
jedisPool.getResource().ping();
3. クライアント: 遅いクエリ操作があります。これらの遅いクエリによって保持されている Jedis オブジェクトは遅く返されるため、プールがいっぱいになります。
4. サーバー: クライアントは正常ですが、Redis サーバーが何らかの理由でクライアント コマンドの実行プロセスをブロックするため、クライアントもこの例外をスローします。この例外には多くの理由があることがわかります。例外の外観に騙されないでください。すべての問題を解決できるマスター キーはありません。開発と運用保守は、継続的に Redis に対する理解を強化し、手がかりをたどって徐々に問題を見つけてください。
2. クライアントの読み取りおよび書き込みタイムアウト
Jedis が Redis を呼び出すときに、読み取りおよび書き込みタイムアウトが発生すると、次の例外が表示されます:
redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: Read timed out
この例外の理由は次のとおりです。
読み取りおよび書き込みのタイムアウトの設定が短すぎます。
コマンド自体は比較的遅いです。
クライアントとサーバー間のネットワークが異常です。
Redis 自体がブロックされています。
3. クライアント接続タイムアウト
Jedis が Redis を呼び出すときに、読み取りおよび書き込みタイムアウトが発生すると、次の例外が表示されます:
redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: connect timed out
Theこの例外の理由は次のとおりです。
接続タイムアウトの設定が短すぎます。
Redis がブロックされているため、tcp-backlog がいっぱいになり、新しい接続が失敗します。
クライアントとサーバー間のネットワークが異常です。
4. クライアント バッファ例外
Jedis が Redis を呼び出すときに、クライアント データ フロー例外が発生すると、次の例外が発生します。
redis.clients.jedis.exceptions.JedisConnectionException: Unexpected end of stream.
この例外の理由は次のとおりです:
1. 出力バッファがいっぱいです。たとえば、通常のクライアントの出力バッファを 1M 1M 60 に設定します。
config set client-output-buffer-limit "normal 1048576 1048576 60 slave 268435456 67108864 60 pubsub 33554432 8388608 60"
get コマンドを使用してビッグキー (3M など) を取得すると、この例外が発生します。
2. 長期アイドル接続はサーバーによってアクティブに切断されます。タイムアウト構成設定と、独自の接続プール構成でアイドル状態の検出が必要かどうかを確認できます。
3. 異常な同時読み取りおよび書き込み: Jedis オブジェクトが複数のスレッドによって同時に操作されるため、上記の例外が発生する可能性があります。
5. Lua スクリプトが実行中です
Redis が現在 Lua スクリプトを実行中で、lua-time-limit を超えた場合、Jedis が Redis を呼び出すと、Jedis は次のメッセージを受け取ります。以下例外。この種の問題に対処する方法 (Lua lua-time-limit 構成は前の章で紹介されています)
redis.clients.jedis.exceptions.JedisDataException: BUSY Redis is busy running a script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE.
#6. Redis は永続化ファイルをロードしています #Jedis が Redis を呼び出す この時点で、Redis が永続ファイルをロードしている場合は、次の例外が発生します。
redis.clients.jedis.exceptions.JedisDataException: LOADING Redis is loading the dataset in memory7. Redis によって使用されるメモリが maxmemory 構成を超えています
Jedis が書き込み操作を実行するために Redis を呼び出すとき、Redis によって使用されるメモリが maxmemory 構成を超えている場合、 maxmemory を設定すると、次の例外が発生します。この時点で maxmemory を調整し、メモリ増大の原因を特定する必要があります (maxmemory については前の章で紹介されています)
redis.clients.jedis.exceptions.JedisDataException: OOM command not allowed when used memory > 'maxmemory'.8. クライアントの数接続が大きすぎます
クライアント接続の数が maxclients を超える場合、新しく要求された接続で次の例外が発生します:
redis.clients.jedis.exceptions.JedisDataException: ERR max number of clients reached
この時点で、新しいクライアント接続が実行されると、どのコマンドでも、戻り結果は次のようになります:
127.0.0.1:6379> get hello (error) ERR max number of clients reached
这个问题可能会比较棘手,因为此时无法执行Redis命令,一般来说可以从两个方面进行着手。
1.客户端:如果maxclients参数不是很小的话,应用方的客户端连接数基本不会超过maxclients,通常来看是由于应用方对于Redis客户端使用不当造成的。此时如果应用方是分布式结构的话,可以通过下线部分应用节点(例如占用连接较多的节点),使得Redis的连接数先降下来。从而让绝大部分节点可以正常运行,此时在再通过查找程序bug或者调整maxclients进行问题的修复。
2.服务端:如果此时客户端无法处理,而当前Redis为高可用模式(例如Redis Sentinel和Redis Cluster),可以考虑将当前Redis做故障转移。
此问题不存在确定的解决方式,但是无论从哪个方面进行处理,故障的快速恢复极为重要,当然更为重要的是找到问题的所在,否则一段时间后客户端连接数依然会超过maxclients。
附赠GenericObjectPoolConfig的重要属性
原文地址:https://mp.weixin.qq.com/s?__biz=MjM5NTk0MTM1Mw==&mid=2650650677&idx=1&sn=cbb1cb9fefdf9641a4a7c775660114e8&chksm=bef9c6b3898e4fa5a31ac6e572dca4c20a37d6c1dcb41004d831b34300c5c9ae0ed8c3a1bb45&scene=21#wechat_redirect 作者:付磊
更多编程相关知识,请访问:编程教学!!
以上がJedis 使用時の一般的なクライアント例外 (概要)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。