.. automodule:: redis.retry :members:
>>> from redis.backoff import ExponentialBackoff
>>> from redis.retry import Retry
>>> from redis.client import Redis
>>> from redis.exceptions import (
>>> BusyLoadingError,
>>> ConnectionError,
>>> TimeoutError
>>> )
>>>
>>> # Run 3 retries with exponential backoff strategy
>>> retry = Retry(ExponentialBackoff(), 3)
>>> # Redis client with retries on custom errors
>>> r = Redis(host='localhost', port=6379, retry=retry, retry_on_error=[BusyLoadingError, ConnectionError, TimeoutError])
>>> # Redis client with retries on TimeoutError only
>>> r_only_timeout = Redis(host='localhost', port=6379, retry=retry, retry_on_timeout=True)
As you can see from the example above, Redis client supports 3 parameters to configure the retry behaviour:
retry
: :class:`~.Retry` instance with a :ref:`backoff-label` strategy and the max number of retriesretry_on_error
: list of :ref:`exceptions-label` to retry onretry_on_timeout
: ifTrue
, retry on :class:`~.TimeoutError` only
If either retry_on_error
or retry_on_timeout
are passed and no retry
is given,
by default it uses a Retry(NoBackoff(), 1)
(meaning 1 retry right after the first failure).
>>> from redis.backoff import ExponentialBackoff
>>> from redis.retry import Retry
>>> from redis.cluster import RedisCluster
>>>
>>> # Run 3 retries with exponential backoff strategy
>>> retry = Retry(ExponentialBackoff(), 3)
>>> # Redis Cluster client with retries
>>> rc = RedisCluster(host='localhost', port=6379, retry=retry, cluster_error_retry_attempts=2)
Retry behaviour in Redis Cluster is a little bit different from Standalone:
retry
: :class:`~.Retry` instance with a :ref:`backoff-label` strategy and the max number of retries, default value isRetry(NoBackoff(), 0)
cluster_error_retry_attempts
: number of times to retry before raising an error when :class:`~.TimeoutError` or :class:`~.ConnectionError` or :class:`~.ClusterDownError` are encountered, default value is3
Let's consider the following example:
>>> from redis.backoff import ExponentialBackoff
>>> from redis.retry import Retry
>>> from redis.cluster import RedisCluster
>>>
>>> rc = RedisCluster(host='localhost', port=6379, retry=Retry(ExponentialBackoff(), 6), cluster_error_retry_attempts=1)
>>> rc.set('foo', 'bar')
- the client library calculates the hash slot for key 'foo'.
- given the hash slot, it then determines which node to connect to, in order to execute the command.
- during the connection, a :class:`~.ConnectionError` is raised.
- because we set
retry=Retry(ExponentialBackoff(), 6)
, the client tries to reconnect to the node up to 6 times, with an exponential backoff between each attempt. - even after 6 retries, the client is still unable to connect.
- because we set
cluster_error_retry_attempts=1
, before giving up, the client starts a cluster update, removes the failed node from the startup nodes, and re-initializes the cluster. - after the cluster has been re-initialized, it starts a new cycle of retries, up to 6 retries, with an exponential backoff.
- if the client can connect, we're good. Otherwise, the exception is finally raised to the caller, because we've run out of attempts.