Retry Mechanism for Clients Accessing GeminiDB Redis API
The retry mechanism for clients accessing GeminiDB Redis API can ensure high availability and stability of applications if the network is unstable or a server is temporarily faulty.
There may be the following temporary faults.
Cause |
Description |
---|---|
HA is triggered. |
GeminiDB Redis API automatically monitors node health. If a node breaks down, a primary/standby switchover or shard takeover is automatically triggered. Generally, HA may be triggered when: |
The network fluctuates. |
Complex network environments between clients and servers running GeminiDB Redis instances may cause problems such as occasional network jitter and data retransmission. In this case, requests initiated by the clients may temporarily fail. |
Servers are overloaded. |
Requests initiated by clients may not be responded immediately due to heavy loads and slow queries on GeminiDB Redis servers. As a result, the requests time out. |
When setting the retry mechanism for clients, follow the rules below.
Rule |
Description |
---|---|
Configure a proper interval and retry times. |
Configure a proper interval and retry times based on business requirements. If an excessive number of retries are attempted, it takes a longer time to recover from a fault. If the interval between retries is shorter than expected, servers may become overwhelmed. In heavy-load scenarios, you are advised to increase the retry interval exponentially to prevent server breakdown due to a large number of concurrent retries. |
Retry only idempotent operations. |
Commands have been executed on a server, but a timeout occurs when the result is returned to a client. In this case, the commands may be executed repeatedly. Therefore, you are advised to retry only idempotent operations (for example, the SET command), and the result remains unchanged after multiple operations. For non-idempotent operations (for example, the INCR command), you need to confirm whether duplicate data can be tolerated, and multiple operations may increase a counter value. |
Generate client logs. |
You are advised to configure the system to generate client logs during the retry process, such as the connected IP address and port number, error commands, and keys, to facilitate troubleshooting. |
The following SDK code examples are used for reference only.
package nosql.cloud.huawei.jedis; import redis.clients.jedis.DefaultJedisClientConfig; import redis.clients.jedis.HostAndPort; import redis.clients.jedis.JedisClientConfig; import redis.clients.jedis.UnifiedJedis; import redis.clients.jedis.providers.PooledConnectionProvider; import java.time.Duration; // UnifiedJedis API supported in Jedis >= 4.0.0 public class UnifiedJedisDemo { private static final int MAX_ATTEMPTS = 5; private static final Duration MAX_TOTAL_RETRIES_DURATION = Duration.ofSeconds(15); public static void main(String[] args) { // Basic connection config JedisClientConfig jedisClientConfig = DefaultJedisClientConfig.builder().password("xxx").build(); // Implement retry PooledConnectionProvider provider = new PooledConnectionProvider(HostAndPort.from("{ip}:{port}"), jedisClientConfig); //Sets MAX_ATTEMPTS to a proper number of retry attempts. UnifiedJedis jedis = new UnifiedJedis(provider, MAX_ATTEMPTS, MAX_TOTAL_RETRIES_DURATION); try { System.out.println("set key: " + jedis.set("key", "value")); } catch (Exception e) { // Signifies reaching either the maximum number of failures, MAX_ATTEMPTS, or the maximum query time, MAX_TOTAL_RETRIES_DURATION e.printStackTrace(); } } }
The following is an example of how to set RETRY_ATTEMPTS and RETRY_INTERVAL to the number of retry attempts and an interval.
package nosql.cloud.huawei.jedis; import org.redisson.Redisson; import org.redisson.api.RBucket; import org.redisson.api.RedissonClient; import org.redisson.config.Config; public class RedissonDemo { private static final int TIME_OUT = 3000; private static final int RETRY_ATTEMPTS = 5; private static final int RETRY_INTERVAL = 1500; public static void main(String[] args) { Config config = new Config(); config.useSingleServer() .setPassword("xxx") .setTimeout(TIME_OUT) .setRetryAttempts(RETRY_ATTEMPTS) .setRetryInterval(RETRY_INTERVAL) // Sets a proper number of retry attempts and retry interval. .setAddress("redis://{ip}:{port}"); RedissonClient redissonClient = Redisson.create(config); RBucket<String> bucket = redissonClient.getBucket("key"); bucket.set("value"); } }
The following is an example of how to set MaxRetries, MinRetryBackoff, and MaxRetryBackoff to the number of retry attempts and intervals.
package main import ( "context" "fmt" "time" "github.com/redis/go-redis/v9" ) var ctx = context.Background() func main() { client := redis.NewClient(&redis.Options{ Addr: "localhost:6379", Password: "", // no password set DB: 0, // use default DB MaxRetries: 3, // set max retry times MinRetryBackoff: time.Duration(1) * time.Second, // set retry interval MaxRetryBackoff: time.Duration(2) * time.Second, // set retry interval }) // Execute command err := client.Set(ctx, "key", "value", 0).Err() if err != nil { panic(err) } // Test pong, err := client.Ping(ctx).Result() if err != nil { fmt.Println("Failed:", err) return } fmt.Println("Success:", pong) }
The following is an example of how to set a proper number of retry attempts by setting parameters of the Retry function.
import redis from redis.retry import Retry from redis.exceptions import ConnectionError from redis.backoff import ExponentialBackoff from redis.client import Redis from redis.exceptions import ( BusyLoadingError, ConnectionError, TimeoutError ) # Run 3 retries with exponential backoff strategy retry_strategy = Retry(ExponentialBackoff(), 3) # Redis client with retries client = redis.Redis( host = 'localhost', port = 6379, retry = retry_strategy, # Retry on custom errors retry_on_error = [BusyLoadingError, ConnectionError, TimeoutError], # Retry on timeout retry_on_timeout = True ) try: client.ping() print("Connected to Redis!") except ConnectionError: print("Failed to connect to Redis after retries.") try: client.set('key', 'value') print("Set key and value success!") except ConnectionError: print("Failed to set key after retries.")
Hiredis is a minimalistic C client library and does not provide a preset automated retry mechanism. You need to manually compile the logic.
The following is a simple example of how to implement an automated connection retry in a loop and with a delay, similar to command retry settings.
#include <hiredis/hiredis.h> #include <stdio.h> #include <unistd.h> redisContext* connect_with_retry(const char *hostname, int port, int max_retries, int retry_interval) { redisContext *c = NULL; int attempt = 0; //Uses a loop and delay to implement automatic retries during connection establishment. while (attempt < max_retries) { c = redisConnect(hostname, port); if (c != NULL && c->err == 0) { printf("Connection success!\n"); return c; } if (c != NULL) { printf("Connection error: %s\n", c->errstr); redisFree(c); } else { printf("Connection failed\n"); } printf("Retrying in %d seconds...\n", retry_interval); sleep(retry_interval); attempt++; } return NULL; } int main() { const char* hostname = "127.0.0.1"; int port = 6379; int max_retries = 5; int retry_interval = 2; redisContext *c = connect_with_retry(hostname, port, max_retries, retry_interval); if (c == NULL) { printf("Failed to connect to Redis after %d attempts\n", max_retries); return 1; } redisFree(c); return 0; }
Feedback
Was this page helpful?
Provide feedbackThank you very much for your feedback. We will continue working to improve the documentation.See the reply and handling status in My Cloud VOC.
For any further questions, feel free to contact us through the chatbot.
Chatbot