From 21f6f5ce125c114aa94d2900d9fd79a20464bfd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=ED=95=98=EC=9B=90=ED=98=B8?= Date: Wed, 29 May 2024 21:01:30 +0900 Subject: [PATCH] Adjusting disconnectedBehavior Option to Prevent Timeout During Redis Shutdown We often need to shut down Redis for maintenance, such as version upgrades. During these times, requests do not fail immediately but instead experience timeouts, increasing application latency. This issue can be resolved by adjusting some options. Currently, our Redis client options are configured as follows: ```java ClientOptions options = ClientOptions.builder() .autoReconnect(true) .disconnectedBehavior(DisconnectedBehavior.REJECT_COMMANDS) ``` The DisconnectedBehavior.REJECT_COMMANDS option appears to cancel commands when the connection is lost. However, if autoReconnect is not set to false, commands in the CommandHandler.stack are not canceled but are placed into the disconnectedBuffer. Therefore, ongoing commands are not rejected if autoReconnect is true, even with the client option modified. For services heavily relying on Redis, latency is crucial. Additionally, we want to avoid writing custom code for reconnections by using the auto-reconnect feature. Adjusting the autoReconnect option can solve this issue immediately, but it would require significant changes to implement automatic reconnection. Proposal We propose that the condition for canceling commands in the CommandHandler.stack should be based solely on rejectCommandsWhileDisconnected and not combined with autoReconnect. I've submitted a PR with a simple code change. Please let me know your thoughts. === Additionally our applications, to maintain low latency and avoid queuing many requests in the buffer when the connection is down, we have configured the client to execute commands only when the connection is active. As a result, only a few requests in the CommandHandler.stack encounter timeouts, but this still negatively impacts the application. --- src/main/java/io/lettuce/core/protocol/DefaultEndpoint.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/lettuce/core/protocol/DefaultEndpoint.java b/src/main/java/io/lettuce/core/protocol/DefaultEndpoint.java index 07fbacf77a..4ec8640071 100644 --- a/src/main/java/io/lettuce/core/protocol/DefaultEndpoint.java +++ b/src/main/java/io/lettuce/core/protocol/DefaultEndpoint.java @@ -678,7 +678,7 @@ public void notifyDrainQueuedCommands(HasQueuedCommands queuedCommands) { cancelCommands("Connection closed", queuedCommands.drainQueue(), it -> it.completeExceptionally(lazy.get())); cancelCommands("Connection closed", drainCommands(), it -> it.completeExceptionally(lazy.get())); return; - } else if (reliability == Reliability.AT_MOST_ONCE && rejectCommandsWhileDisconnected) { + } else if (rejectCommandsWhileDisconnected) { Lazy lazy = Lazy.of(() -> new RedisException("Connection disconnected")); cancelCommands("Connection disconnected", queuedCommands.drainQueue(), it -> it.completeExceptionally(lazy.get()));