Python Tenacity库介绍(请求重试库、retry重试框架,当操作失败时,自动按策略重新执行)指数退避、随机抖动、RetryError、Retrying库
2026/5/12 4:00:51 网站建设 项目流程

文章目录

  • Python 重试利器:Tenacity 完全指南
  • 一、什么是 Tenacity
  • 二、为什么需要重试机制
  • 三、最基础的使用
    • 1)装饰器方式
  • 四、限制重试次数
    • stop_after_attempt
  • 五、等待时间(Wait)
    • 固定等待
  • 六、指数退避(非常重要)
  • 七、为什么指数退避很重要
  • 八、Jitter(随机抖动)
  • 九、组合等待策略
  • 十、只在特定异常时重试
    • retry_if_exception_type
  • 十一、异步 asyncio 支持(重点)
    • Async Retry
  • 十二、FastAPI 中的典型用法
  • 十三、RabbitMQ 消费重试
  • 十四、数据库重试
  • 十五、before / after Hook
    • before_log
    • after_log
  • 十六、RetryError
  • 十七、推荐生产配置
  • 十八、Tenacity vs Retrying
  • 十九、最佳实践
    • 1)不要无限重试
    • 2)必须设置 stop
    • 3)使用指数退避
    • 4)只重试临时错误
    • 5)保证幂等性
  • 二十、Tenacity 在现代架构中的位置
  • 二十一、总结

Python 重试利器:Tenacity 完全指南

在分布式系统、微服务、消息队列、数据库访问、第三方 API 调用中,“失败”其实是常态。

比如:

  • 网络瞬时抖动
  • 数据库连接超时
  • RabbitMQ 暂时不可用
  • OpenAI / DashScope API 限流
  • 对象存储偶发失败
  • Kubernetes Pod 重启期间短暂不可达

如果代码没有“自动重试”能力,系统稳定性会明显下降。

而在 Python 世界里,最流行、最优雅的重试库之一,就是:

Tenacity

它支持:

  • 同步 / 异步
  • 指数退避
  • 随机抖动(Jitter)
  • 自定义重试条件
  • 超时停止
  • 回调 Hook
  • asyncio 支持
  • 与 FastAPI / Celery / aio-pika 等生态完美结合

一、什么是 Tenacity

Tenacity 是一个:

“通用 Python 重试框架(Retrying Library)”

它的核心目标:

当操作失败时,自动按策略重新执行。

官方项目:

Tenacity GitHub

安装:

pipinstalltenacity

二、为什么需要重试机制

现实系统中,大量错误其实是:

“暂时性错误(Transient Errors)”

例如:

场景是否适合重试
网络超时
数据库连接断开
API Rate Limit
MQ 暂时不可用
DNS 解析失败
参数错误
数据格式错误
权限错误

所以:

重试不是为了掩盖 Bug
而是为了增强系统韧性(Resilience)


三、最基础的使用

1)装饰器方式

fromtenacityimportretry@retrydefconnect():print("connecting...")raiseException("network error")connect()

默认会:

  • 无限重试
  • 无等待间隔

通常生产环境不会这样使用。


四、限制重试次数

stop_after_attempt

fromtenacityimportretry,stop_after_attempt@retry(stop=stop_after_attempt(3))defcall_api():print("calling api")raiseException("failed")

含义:

最多尝试 3 次

执行流程:

第1次失败 第2次失败 第3次失败 最终抛异常

五、等待时间(Wait)

固定等待

fromtenacityimportretryfromtenacityimportwait_fixed@retry(wait=wait_fixed(2))deftask():raiseException()

表示:

每次失败后等待 2 秒

六、指数退避(非常重要)

生产系统中最常见:

Exponential Backoff(指数退避)

例如:

1s 2s 4s 8s 16s

Tenacity:

fromtenacityimportretry,wait_exponential@retry(wait=wait_exponential(multiplier=1))defrequest():raiseException()

退避公式核心思想:

t n = a ⋅ 2 n t_n = a \cdot 2^ntn=a2n

其中:

  • ( a ) (a)(a)为初始时间
  • ( n ) (n)(n)为重试次数

七、为什么指数退避很重要

如果大量客户端同时失败:

1000 个客户端 同时重试 再次打爆服务

这叫:

Retry Storm(重试风暴)

指数退避可以:

  • 降低服务压力
  • 避免雪崩
  • 给服务恢复时间

这是云原生系统中的标准做法。


八、Jitter(随机抖动)

仅指数退避还不够。

因为:

所有客户端: 1s 2s 4s 同时重试

还是会形成流量尖峰。

所以需要:

Jitter(随机抖动)

Tenacity:

fromtenacityimportwait_random_exponential@retry(wait=wait_random_exponential())deftask():raiseException()

效果:

客户端A:2.1s 客户端B:2.7s 客户端C:3.3s

这样重试会被打散。


九、组合等待策略

Tenacity 支持组合:

fromtenacityimportwait_fixedfromtenacityimportwait_random wait=wait_fixed(3)+wait_random(0,2)

效果:

固定 3 秒 再随机增加 0~2 秒

这是很多生产系统的经典策略。


十、只在特定异常时重试

不是所有错误都应该重试。

retry_if_exception_type

fromtenacityimportretryfromtenacityimportretry_if_exception_type@retry(retry=retry_if_exception_type(ConnectionError))deffetch():...

含义:

只有 ConnectionError 才重试

十一、异步 asyncio 支持(重点)

Tenacity 对 asyncio 支持非常好。

这也是它特别适合:

  • FastAPI
  • aio-pika
  • asyncpg
  • aiohttp

的重要原因。


Async Retry

fromtenacityimportretry,stop_after_attemptimportasyncio@retry(stop=stop_after_attempt(3))asyncdeffetch():awaitasyncio.sleep(1)raiseException()asyncio.run(fetch())

十二、FastAPI 中的典型用法

例如调用外部 Embedding API:

fromtenacityimportretryfromtenacityimportwait_exponentialfromtenacityimportstop_after_attempt@retry(wait=wait_exponential(min=1,max=30),stop=stop_after_attempt(5),)asyncdefembedding(text:str):returnawaitclient.embeddings.create(input=text)

非常适合:

  • OpenAI
  • DashScope
  • Claude API
  • 各种 LLM API

十三、RabbitMQ 消费重试

结合 aio-pika:

@retry(wait=wait_exponential(),stop=stop_after_attempt(5),)asyncdefprocess_message(msg):...

适合:

  • MQ 临时断连
  • DB 短暂不可用
  • 外部服务失败

十四、数据库重试

例如 PostgreSQL:

@retry(wait=wait_fixed(1),stop=stop_after_attempt(3),)asyncdefsave():awaitsession.commit()

适合:

  • Deadlock
  • Connection reset
  • 短暂超时

但注意:

事务重试要小心幂等性。


十五、before / after Hook

Tenacity 可以在:

  • 重试前
  • 重试后

执行回调。


before_log

importloggingfromtenacityimportbefore_log logger=logging.getLogger(__name__)@retry(before=before_log(logger,logging.INFO))deftask():...

after_log

fromtenacityimportafter_log

用于记录失败日志。

非常适合:

  • Prometheus Metrics
  • ELK
  • Loki
  • OpenTelemetry

十六、RetryError

达到最大重试次数后:

tenacity.RetryError

会被抛出。

你可以:

try:task()exceptRetryError:...

十七、推荐生产配置

很多公司常见:

@retry(wait=wait_random_exponential(multiplier=1,max=60),stop=stop_after_attempt(5),reraise=True,)

特点:

配置作用
exponential防止打爆服务
jitter打散流量
max防止等待无限增长
stop_after_attempt防止死循环
reraise抛原始异常

十八、Tenacity vs Retrying

Tenacity 是:

retrying

库的现代替代品。

优势:

对比Tenacity
asyncio
类型支持更好
API设计更现代
社区活跃更高
Python版本更新

如今新项目基本都推荐:

Tenacity

十九、最佳实践

1)不要无限重试

错误示例:

@retry

可能导致:

  • 死循环
  • 线程占满
  • 服务雪崩

2)必须设置 stop

推荐:

stop_after_attempt(3)

或者:

stop_after_delay(30)

3)使用指数退避

推荐:

wait_random_exponential()

4)只重试临时错误

不要重试:

  • 参数错误
  • 认证错误
  • 业务错误

5)保证幂等性

非常关键。

例如:

支付接口 扣款接口 创建订单

如果重试:

可能重复执行

所以:

重试前必须考虑幂等设计。


二十、Tenacity 在现代架构中的位置

Tenacity 非常适合:

系统用途
FastAPIAPI调用重试
Celery任务重试
aio-pikaMQ消费重试
asyncpgDB重试
boto3S3请求重试
Qdrant向量检索重试
Kubernetes云环境瞬时故障恢复

它本质上属于:

Resilience Engineering(韧性工程)

的重要组成部分。


二十一、总结

Tenacity 是 Python 世界最优秀的重试库之一。

它解决了:

  • 网络抖动
  • API 限流
  • 瞬时故障
  • 服务雪崩
  • 重试风暴

等生产环境中的核心问题。

如果你正在开发:

  • 微服务
  • AI 系统
  • FastAPI 服务
  • MQ 消费系统
  • 云原生平台

那么:

Tenacity 几乎是必备组件。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询