消息发送一致性
微服务架构下,需要通过网络进行通信,就自然引入了数据传输的不确定性,也就是CAP原理中的P-分区容错,而这里的消息发送一致性
是可靠消息的保证。
生成消息的业务动作与消息发送的一致(e.g: 如果业务操作成功,那么由这个业务操作所产生的消息一定会成功投递出去,否则就丢失消息)
如上图,保证消息发送一致性的一般流程如下:
- Producer先把消息发送给消息中间件服务,消息的状态标记为
待确认
,这个状态并不会被Consumer消费,对于长期待确认
的消息,消息中间件会调用Producer的查询接口,查看最新状态,根据结果决定是否删除消息。 - Producer执行完业务操作后,向消息中间件服务,发送确认消息
- 这时消息的状态会被更改为
待发送(可发送)
- Consumer监听并接收待发送状态的消息,执行业务处理
- Consumer业务处理后,向消息中间件服务发送
ACK
,确认消息已经收到(消息中间件服务将从队列中删除该消息)
消息的ACK确认流程中,任何一个环节都可能会出问题!
对未ACK
的消息,采用按规则重新投递的方式进行处理(很多MQ都提供at least once的投递,持久化和重试机制),一般还会设置重发
的次数, 超过次数的消息会进入dead letter queue
,等待人工干预或者延后定时处理。
业务接口的幂等性
消息的重复发送会导致业务接口出现重复调用的问题,主要原因就是消息没有及时收到ACK确认导致的, 那如何实现幂等性设计呢?
在实际的业务场景中, 业务接口的幂等性设计,常结合查询操作一起使用,
比如根据唯一标识
查询消息是否被处理过, 或者根据消费日志表,来维护消息消费的记录。
保证最终一致性的模式
- 可查询模式,任何一个服务操作都提供一个可查询接口,用来向外部输出操作执行的状态,下游Consumer可以通过接口得知服务操作执行的状态,然后根据不同的状态做不同的处理操作(执行或者取消), 该模式对业务接口有一定侵入性。
- 补偿模式, 有了查询模式,我们能够知道操作的具体状态,如果处于不正常状态,我们可以
修正
操作中出现的问题,或许是重新执行,或许取消已经完成的操作,通过修复是的整个分布式系统达到最终一致。 - 最大努力通知模式, 在调用支付宝交易接口或微信支付接口时,一般会在回调页面和接口里,解密参数,然后调用系统中更新交易状态相关的服务,将订单更新为付款成功。同时,只有当回调页面中输出了success字样或者标识业务处理成功相应状态码时,支付宝才会停止回调请求。否则,支付宝会每间隔一段时间后,再向客户方发起回调请求,直到输出成功标识为止。