更新时间:2025-12-19
点击次数:
难道消息发送失败之后不停地进行重试就能够确保成功吗?实际上的情形要复杂许多,不恰当的重试反而会致使带来新的问题。
生产者发送重试
消息由生产者发往消息服务端之际; 就有可能因网络出现波动; 或者服务端出现短暂异常; 进而致使发送失败; 面向这类问题; 客户端一般会在内部装上自动重试机制; 开发人员在初始化客户端的时候; 能够设定最大重试次数; 好比默认设置成2次; 一旦发送失败; 便会依据这个设定去尝试重新发送 。
但是,重试这种行为,并非在每一处场景里,都能够发挥效用。举例来说,当处理那些涉及到数据库事务的业务消息之际,客户端时常仅仅会针对网络层出现的超时情况去开展“透明重试”的操作。针对其他各项缘由所导致使事务消息传递失败之事,常规的用来重试的逻辑是没法产生预期效果的。开发人员务必借助事务回滚等相关机制来确保其一致性,而做到这点,必须要业务代码拥有与之对应的异常处理方面的设计才行。
重试触发的条件
立即触发并非一失败就进行重试。通常错误被分为“流控错误”以及“非流控错误”这两种。当服务端因容量过载返回流控错误时分,客户端会采用指数退避策略来进行延迟重试,也就是等待时间会随着失败次数增加而延长。这有利于避免在服务端压力大的时候加剧其负担。
current_backoff = INITIAL_BACKOFF
current_deadline = now() + INITIAL_BACKOFF
while (TryConnect(Max(current_deadline, now() + MIN_CONNECT_TIMEOUT))!= SUCCESS)
SleepUntil(current_deadline)
current_backoff = Min(current_backoff * MULTIPLIER, MAX_BACKOFF)
current_deadline = now() + current_backoff + UniformRandom(-JITTER * current_backoff, JITTER * current_backoff)
针对其他并非流控方面的错误,像是偶然出现的网络丢包情况,客户端通常会马上开展下一次重试操作,其间不存在等待时段差距。这样一种立刻进行重试的策略,适用于去处理短暂、瞬间发生的故障,其目的在于能够快点完成消息传递工作,不过前提条件是服务端已经从短暂异常状况里恢复过来。
重试的副作用
其中一个主要副作用是,重试机制有可能致使消息出现重复情况。在分布式环境当中,一次请求会因为超时,而被客户端认定为失败,从而进行重试,然而服务端也许已经成功处理了首次请求。这样一来,同一条消息就会被服务端接收两次,进而有可能被消费者重复加以处理。
另外一个会产生的副作用是致使服务端压力增大,特别是在流控的情景状况下,要是数量众多的客户端因为突然出现的流量同时引发重试行为,并且重试间隔的策略运用得不恰当,那就有可能形成重试风暴,持续不断地冲击原本就已经处于满载状态的服务端,甚至还有可能引发雪崩效应,最终导致服务完全无法使用。
确保最终一致性
当客户端设置的内置重试机制,经过多次尝试最终还是失败的时候,消息依然存在丢失的可能性。有一种更为可靠的解决办法是,在业务服务器所处的本地环境,把发送失败的那些消息,持久化存储到数据库里或者文件当中。之后,由一个独自运行的后台任务,按照固定的时间间隔去扫描这些失败的记录,然后尝试再次进行发送操作,一直到发送成功才停止 。
这种方式把消息发送同核心业务逻辑进行了解耦,即便消息中间件当下暂时没办法使用,业务操作能够先去完成,失败的消息记录会被以异步的形式进行补发。这是以牺牲一定的实时性作为代价的,不过换来了更高的可靠性以及业务状态的最终一致,这是众多金融、交易类系统当中常见的实践 。
消费者消费重试
消费重试和发送重试不一样,它留意的是消息在被消费者应用去处理之际的失败情况。要是消费者处理消息之时抛出异常,或者返回失败标志,亦或是处理超时,服务端就会认定此次消费失败了,并且会依照配置好的重试策略,在过了一段时间后再度把消息投递给消费者。
消费重试的目的在于确保每条消息均会被完整处理,防止因部分消息消费出现失败,致使整体业务数据状态呈现不一致状况。举例而言,若一个扣减库存的消息其消费失败了,借助重试能够保证库存最终得以正确扣减,维持了订单与库存数据之间的逻辑统一性。
合理使用消费重试
消费重试作为异常补救办法并非常态流程有着诸多异样状况,一个反面例子是,通过主动返回“消费失败结果”构建限流举措,这样会致使大量消息在重试队列里被不断积压,重试队列实际的内部实现常常是以定时器为基础搭建,运行之时所产生的吞吐量终究有效总量数值较为低量,因此导致了大量消息堆集的时候由于积累众多产生越来越严重加剧的延迟,更甚至于因此影响了正常消息在获取的时候因受干扰达不到自身完成既定效果而产生处理问题的情况出现。
应实现幂等性是消费逻辑的另一个重要原则了,生产者重试或者服务端重投都有可能带来重复消息了,消费者得能够安全地多次处理同一条消息才行,就比如说基于订单ID等业务主键来判别该操作是不是已经执行过了,要是已经执行了那就直接返回成功,这可是避免重复发货、重复扣款的关键设计。
你对于消息重试机制持有怎样的看法呀,在你所经历的项目实践当中,是怎样去平衡消息可靠性以及系统性能的呢,欢迎在评论区域分享你的相关经验哦。