重试机制的常见应用场景
重试机制是分布式系统和网络编程中一种常见的容错策略,主要用于应对临时性故障。以下是典型的应用场景:
1.网络通信场景
- 网络抖动:数据传输过程中因网络不稳定导致的丢包或延迟
- 连接超时:客户端与服务端建立连接超时
- DNS 解析失败:域名解析临时失败
2.微服务调用
- 服务暂时不可用:目标服务正在重启、发布或临时过载
- 负载均衡切换:请求命中了异常节点,重试时可能被路由到健康节点
- 下游依赖超时:调用的下游服务响应超时
3.数据库操作
- 连接池耗尽:数据库连接池暂时无可用连接
- 死锁或锁等待:事务发生冲突,重试时可能成功获取锁
- 主从切换:数据库主从切换期间的短暂不可用
4.消息队列
- 消息投递失败:Broker 暂时不可达
- 消费端处理失败:消费者处理消息时发生临时性异常
- 死信队列处理:消息多次消费失败后进入死信队列,人工干预后重试
5.第三方接口调用
- 支付回调:第三方支付平台回调通知失败
- 短信/邮件发送:网关拥堵或限流
- 第三方 API 限流:触发对方限流策略,需要等待后重试
6.分布式事务
- Confirm/Cancel 失败:TCC、SAGA 模式中某个步骤失败
- 分布式锁获取失败:抢锁失败后重试获取
7.缓存操作
- 缓存穿透/击穿:缓存失效瞬间大量请求打到数据库,重建缓存后重试
- 缓存更新失败:Redis 连接抖动导致写入失败
重试次数/间隔控制
- 最大重试次数:3次足够(最多5次)
- 初始间隔:1秒以上(避免瞬间压垮对方服务)
- 最大间隔:10秒以内(避免用户体验差)
为什么需要退避策略
退避策略是重试机制的核心灵魂,直接决定了重试的效率与安全性。核心思想是:每次重试之间增加等待时间,避免连续请求压垮对方服务。无退避的危险,瞬间爆发的重试流量会导致对方服务雪崩式崩溃,最终双方都不可用。
数据库重连机制
mysql出现ERROR : (2006, 'MySQL server has gone away')服务器在执行查询前已经关闭了连接。重连机制
/** * 获取连接. * * @param string $url * * @return Connection|null * * @throws \Exception */ protected function getConn($url) { $conn = null; for ($times = 1; $times <= 3; ++$times) { try { $config = new Configuration(); $conn = DriverManager::getConnection( array( 'url' => $url, 'driver' => 'pdo_mysql', ), $config ); break; } catch (\Exception $e) { $sleepTime = $times * 60 > 180 ? 180 : $times * 60; sleep($sleepTime); $logger->error(sprintf('第【%s】次获取数据库mysql连接异常, 异常信息为【%s】', $times, $url, $e->getMessage())); } } return $conn; } public function checkDbGoneAway($conn) { $result = true; try { $conn->execute("select 1"); } catch (\Exception $e) { $errMsg = $e->getMessage(); $errCode = $e->getCode(); if (2006 === $errCode && false !== strpos($errMsg, 'server has gone away')) { $result = false; } } return $result; }系统自带ping方法,不通不会出现异常
if (false === $conn->ping()) { $conn->close(); $conn->connect(); }