重试助手#

class redis.retry.Retry(backoff, retries, supported_errors=(<class 'redis.exceptions.ConnectionError'>, <class 'redis.exceptions.TimeoutError'>, <class 'socket.timeout'>))[source]#

在失败后重试特定次数

call_with_retry(do, fail)[source]#

执行可能失败的操作并返回其结果,或根据 Backoff 对象引发抛出的异常。 do: 要调用的操作。不接受任何参数。 fail: 失败处理程序,接受最后抛出的错误

update_supported_errors(specified_errors)[source]#

使用指定的错误类型更新支持的错误

参数

specified_errors (list) –

在 Redis 独立模式中重试#

>>> 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)

如上例所示,Redis 客户端支持 3 个参数来配置重试行为

  • retry: Retry 实例,带有 Backoff 策略和最大重试次数

  • retry_on_error: 重试的异常列表,参见 Exceptions

  • retry_on_timeout: 如果为 True,仅在遇到 TimeoutError 时重试

如果同时传递了 retry_on_errorretry_on_timeout,并且没有指定 retry,则默认使用 Retry(NoBackoff(), 1)(表示在第一次失败后立即重试一次)。

Redis 集群中的重试#

>>> 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)

Redis 集群中的重试行为与独立模式略有不同

让我们考虑以下示例

>>> 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')
  1. 客户端库计算键“foo”的哈希槽。

  2. 根据哈希槽,它确定连接到哪个节点以执行命令。

  3. 在连接过程中,抛出了 ConnectionError

  4. 因为我们设置了 retry=Retry(ExponentialBackoff(), 6),客户端会尝试最多 6 次重新连接到节点,每次尝试之间会进行指数级回退。

  5. 即使经过 6 次重试,客户端仍然无法连接。

  6. 因为我们设置了 cluster_error_retry_attempts=1,在放弃之前,客户端会启动集群更新,从启动节点中移除失败的节点,并重新初始化集群。

  7. 集群重新初始化后,会开始新的重试循环,最多重试 6 次,每次尝试之间会进行指数级回退。

  8. 如果客户端可以连接,我们就成功了。否则,异常最终会传递给调用者,因为我们已经用尽了尝试次数。