前言一致性设计是分布式系统中的一个重要问题。如果一个系统使用多个子数据系统同时存储和读取数据,则必须设计满足功能需求的一致性定义。如果系统对不同的数据子系统进行操作,结果不一致,不仅可能使用户感到困惑,还可能导致更严重的数据问题或系统错误。一致性有多种级别,适用于不同的业务场景。对于金融等对数据一致性要求高的行业,传统交易可以提供高一致性保障。对于分布式系统等对性能和可用性要求较高的场景,牺牲一定的强一致性来换取更好的用户体验是可以接受的。之前写过一篇关于TCC事务的笔记,也了解了分布式事务产生的原因和一些解决办法。本次总结一下最终一致性方案设计思路的相关内容;场景消息发送一致性的概念:指生成消息的业务动作与发送消息的业务动作一致。也就是说,如果业务操作成功,则业务操作产生的消息必须传递成功,否则消息会丢失。最终一致性可用于类似如下的功能场景:对应支付系统记账异步记账业务common为积分账户添加积分的服务意味着采用最终一致性的数据系统通常不需要在数据操作失败时回滚.用户或系统日志将被通知操作失败,但数据不一致将不会自动修复,直到另一个成功的操作。ps:肯定有小伙伴会有疑问。执行程序时代码报错,最终一致性方案失败怎么办???你有很多吗,孩子???如果代码报错,说明你的业务代码有问题,不是最终一致性方案的锅~~。要实现流程的最终一致性,可以使用消息中间件、消息队列等工具。您需要根据自己的业务定制不同的技术方案。我们要介绍的是一个基于RabbitMq的可靠的消息服务系统来完成交易的执行。具体流程如下:主动应用先向消息中间件发送消息,消息状态标记为“等待确认”;消息中间件收到消息后,将消息持久化到消息存储中,但不会传递给被动应用Message;消息中间件返回消息持久化结果(成功/失败),主动应用根据返回结果判断如何处理业务操作:失败:放弃业务操作处理并结束(如果返回失败结果给上层)必要的);成功:执行业务操作处理;业务操作完成后,将业务操作结果(成功/失败)发送给消息中间件;消息中间件收到业务操作结果后,根据业务结果进行处理;失败:删除消息存储中的消息,结束;成功:更新消息存储中消息的状态为“待发送(canbesent)”,然后进行消息投递;被动应用监听接收处于“待发送”状态的消息,并进行业务处理;业务处理完成后,发送ACK给消息中间件,确认消息已经收到(消息中间件会将该消息从队列中删除)除了以上流程,消息系统还应该提供ackMsg消息确认服务和消息状态查询服务。异常处理流程从主动方的角度,从中间件的角度总结异常情况消息系统的实现构成了消息服务子系统:它是最重要的子系统,接收和存储预发送的消息,并提供进一步的确认功能。一般需要实现以下接口服务。存储预发送消息(主动端应用系统)确认并发送消息(主动端应用系统)查询状态确认超时消息(消息状态确认子系统)确认消息已成功消费(被动端应用系统)查询消费确认超时Message(消息恢复子系统)消息管理子系统:提供可视化的管理界面,对可靠的消息服务系统中的数据进行查询和管理。比如可以查看死消息,也可以通过接口手动重发,确认消息状态。子系统:提供对异常情况的处理。当消息服务子系统收到并保存了预先发送的消息,但由于异常情况,没有收到发送消息的确认,这条消息不能一直保存在数据库中。对于本案例中的数据,消息状态确认子系统需要定时获取待确认超时的数据,并调用主动方应用系统中的业务查询接口进行验证确认。根据验证结果,决定是发送消息还是删除数据。消息恢复子系统:如果消息数据已经收到业务确认,业务确认的消息必须发送到MQ并被消费者成功消费,不能丢失。消息恢复子系统定时取回那些状态为“发送中”但未被消费确认的超时消息,并重新发送。实时消息服务子系统(MQ):消费者监听程序接收MQ消息,处理成功后调用消息服务子系统的接口,确认消息消费成功,可以删除。整体流程用户下单,主动方应用预发消息给消息服务子系统。消息服务子系统存储预先发送的消息。返回存储预发送消息的结果。如果第3步返回的结果成功,则执行业务操作,否则不执行。业务操作成功后,调用消息服务子系统进行消息确认和发送。发送存储在消息服务库中的预发送消息,更新消息状态为已发送(未消费)。消息中间件向消费者应用程序发送消息。消费者应用程序调用被动应用程序服务。被动应用程序将结果返回给消费者应用程序。消费者应用向消息中间件确认该消息,并向消息服务子系统确认消息消费成功,并要求消息服务子系统删除消息或设置状态为消费成功。消息状态子系统定时检查消息数据,查看是否有发送状态的超时消息,即未消费成功的消息。主动应用系统应该提供一个查询接口,查询某条消息对应的业务数据是否处理成功,如果业务数据处理成功,则再次调用确认并发送消息,即进入步骤6、如果业务数据处理失败,则调用消息服务子系统删除消息数据。感谢您的收看本文是学习过程中的笔记合集。如有不妥请及时联系我更正,以免误导童鞋。感谢您耐心观看本文。希望这篇文章对你有所帮助~我打算后面在Hyperf中写一个demo,有兴趣的可以关注我的GitHub。
