java 可靠消息服务_可靠消息最终一致(异步确保型)

2023-11-03 14:30

本文主要是介绍java 可靠消息服务_可靠消息最终一致(异步确保型),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

一致性设计在分布式系统中是一个重要问题。如果一个系统同时使用多个子数据系统来存储与读取数据,就必须设计满足功能需求的一致性定义。如果系统对不同数据子系统进行操作的结果不一致,不但可能会使用户困惑,更可能引发更严重的数据问题或系统错误。一致性有多种级别,适用于不同的业务场景。对于金融等对数据一致性要求较高的行业,传统的事务可以提供较高的一致性保证。对于分布式系统等对性能(performance)和可用性(availability)要求较高的场景,牺牲一定的强一致性来换取更好的用户体验也可接受。

在之前写过一次关于TCC事务的笔记,也了解了分布式事务产生的原因,以及部分解决方案,这次一起跟大家总结下最终一致性方案设计思路的相关内容;

场景

消息发送一致性的概念:是指产生消息的业务动作与消息发送的一致。

也就是说,如果业务操作成功,那么由这个业务操作所产生的消息一定要成功投递出去,否则就丢消息

最终一致性可以使用在类似如下功能场景当中:

对应支付系统会计异步记账业务

普通的积分账户增加积分的服务

也就是说:采用最终一致性的数据系统通常不要求数据操作失败时执行回滚(rollback)。用户或系统日志将得知操作失败,但在另一次成功的操作之前,数据的不一致问题并不会被自动修复。

ps:肯定会有小伙伴有疑问,我执行程序的时候代码报错了导致最终一致性的方案不成功怎么办???小朋友你是不是有很多???

如果是代码报错,本身说明了你的业务代码有问题,而不是最终一致性方案的锅~~。

实现流程

最终一致性可以借助消息中间件,消息队列等工具实现,需要根据自己的业务去定制不同的技术方案;

咱们要介绍的是基于RabbitMq实现的一个可靠消息服务系统来完成事务的执行,具体流程如下图:

084d0504760a8dd79bf7250fd5528e28.png

主动方应用先把消息发给消息中间件,消息状态标记为“待确认”;

消息中间件收到消息后,把消息持久化到消息存储中,但并不向被动方应用投递消息;

消息中间件返回消息持久化结果(成功/失败),主动方应用根据返回结果进行判断如何进行业务操作处理:

失败:放弃业务操作处理,结束(必要时向上层返回失败结果);

成功:执行业务操作处理;

业务操作完成后,把业务操作结果(成功/失败)发送给消息中间件;

消息中间件收到业务操作结果后,根据业务结果进行处理;

失败:删除消息存储中的消息,结束;

成功:更新消息存储中的消息状态为“待发送(可发送)”,紧接着执行消息投递;

被动方应用监听并接收“待发送”状态的消息,执行业务处理;

业务处理完成后,向消息中间件发送ACK,确认消息已经收到(消息)中间件将从队列中删除该消息)

除了以上几个流程,消息系统还应该提供ackMsg消息确认服务、消息状态查询服务。

异常的处理流程

26748f4b8ea25e01d4baeae74ab507ca.png

主动方角度

a7f74a406de3e03494bfef1d826f0d36.png

20e427b43af5fd40c8a3a1c541b02922.png

从中间件的角度

b895460cac9598e93760f5dcdbddaf74.png

181eb4ddb39154d46ea83f2cd4e6e1f0.png

异常情况的总结处理

9a0e534c92c1104a4b10e5e871716bff.png

方案落地

4f4c9037577756a29c0b0e0ddbd02ca2.png

消息系统组成

消息服务子系统:

是最重要的一个子系统,它接收并存储预发送的消息,并提供进一步的确认功能。一般需要实现以下接口服务。

存储预发送消息(主动方应用系统)

确认并发送消息(主动方应用系统)

查询状态确认超时的消息(消息状态确认子系统)

确认消息已被成功消费(被动方应用系统)

查询消费确认超时的消息(消息恢复子系统)

消息管理子系统:

提供一个可视化的管理界面,对可靠消息服务系统中的数据,进行查询和管理。比如可查看已死亡的消息,可通过界面手工重发等

消息状态确认子系统:

提供对异常情况的处理。当消息服务子系统收到并保存预发送消息,但因异常情况,没有收到确认发送消息时,这种消息不可能一直留存在数据库中。这种情况的数据,就需要消息状态确认子系统定期捞取这些待确认超时的数据,去调用主动方应用系统中的业务查询接口进行核对确认。根据核对结果决定是发送消息还是删除数据。

消息恢复子系统:

如果消息数据已经接收到业务确认,这种经过业务确认的消息,就一定要发送到MQ,并被消费方成功消费,绝不能丢。消息恢复子系统定期捞取那些状态是“发送中”,而没有被消费确认的超时消息,进行重新发送。

实时消息服务子系统(MQ):

消费方监听程序,接收MQ消息,成功处理后调用消息服务子系统的接口,确认消息已被成功消费,可以删除。

整体流程

用户下单,主动方应用预发送消息给消息服务子系统。

消息服务子系统存储预发送的消息。

返回存储预发送消息的结果。

如果第3步返回的结果是成功的,则执行业务操作,否则不执行。

业务操作成功后,调用消息服务子系统进行确认发送消息。

将消息服务库中存储的预发送消息发送,并更新该消息的状态为已发送(但不是已被消费)。

消息中间件发送消息到消费端应用。

消费端应用调用被动方应用服务。

被动方应用返回结果给消费端应用。

消费端应用向消息中间件ack此条消息,并向消息服务子系统进行确认成功消费消息,

让消息服务子系统删除该条消息或者将状态置为已成功消费。

消息状态子系统定时去查一下消息数据,看看有没有是已发送状态的超时消息,就是一直没有变成已成功消费的那种消息,主动方应用系统应该提供查询接口,针对某条消息查询该条消息对应的业务数据是否为处理成功

如果业务数据是处理成功的状态,那么就再次调用确认并发送消息,即进入第6步。

如果业务数据是处理失败的,那么就调用消息服务子系统进行删除该条消息数据。

谢谢观赏

本文是学习过程中的笔记整理,如果有不对的地方请大家联系我,及时纠正,避免误导童鞋们,谢谢各位童鞋的耐心观看,希望本文会帮助到您~后期计划在Hyperf中写一个demo,感兴趣的可以留意我的GitHub。

b739ec46bb5c46d9c0aa4ce35ba1ea56.png

关于找一找教程网

本站文章仅代表作者观点,不代表本站立场,所有文章非营利性免费分享。

本站提供了软件编程、网站开发技术、服务器运维、人工智能等等IT技术文章,希望广大程序员努力学习,让我们用科技改变世界。

[可靠消息最终一致(异步确保型)]http://www.zyiz.net/tech/detail-138649.html

这篇关于java 可靠消息服务_可靠消息最终一致(异步确保型)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/338799

相关文章

Java实现检查多个时间段是否有重合

《Java实现检查多个时间段是否有重合》这篇文章主要为大家详细介绍了如何使用Java实现检查多个时间段是否有重合,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录流程概述步骤详解China编程步骤1:定义时间段类步骤2:添加时间段步骤3:检查时间段是否有重合步骤4:输出结果示例代码结语作

Java中String字符串使用避坑指南

《Java中String字符串使用避坑指南》Java中的String字符串是我们日常编程中用得最多的类之一,看似简单的String使用,却隐藏着不少“坑”,如果不注意,可能会导致性能问题、意外的错误容... 目录8个避坑点如下:1. 字符串的不可变性:每次修改都创建新对象2. 使用 == 比较字符串,陷阱满

Java判断多个时间段是否重合的方法小结

《Java判断多个时间段是否重合的方法小结》这篇文章主要为大家详细介绍了Java中判断多个时间段是否重合的方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录判断多个时间段是否有间隔判断时间段集合是否与某时间段重合判断多个时间段是否有间隔实体类内容public class D

IDEA编译报错“java: 常量字符串过长”的原因及解决方法

《IDEA编译报错“java:常量字符串过长”的原因及解决方法》今天在开发过程中,由于尝试将一个文件的Base64字符串设置为常量,结果导致IDEA编译的时候出现了如下报错java:常量字符串过长,... 目录一、问题描述二、问题原因2.1 理论角度2.2 源码角度三、解决方案解决方案①:StringBui

Java覆盖第三方jar包中的某一个类的实现方法

《Java覆盖第三方jar包中的某一个类的实现方法》在我们日常的开发中,经常需要使用第三方的jar包,有时候我们会发现第三方的jar包中的某一个类有问题,或者我们需要定制化修改其中的逻辑,那么应该如何... 目录一、需求描述二、示例描述三、操作步骤四、验证结果五、实现原理一、需求描述需求描述如下:需要在

Java中ArrayList和LinkedList有什么区别举例详解

《Java中ArrayList和LinkedList有什么区别举例详解》:本文主要介绍Java中ArrayList和LinkedList区别的相关资料,包括数据结构特性、核心操作性能、内存与GC影... 目录一、底层数据结构二、核心操作性能对比三、内存与 GC 影响四、扩容机制五、线程安全与并发方案六、工程

JavaScript中的reduce方法执行过程、使用场景及进阶用法

《JavaScript中的reduce方法执行过程、使用场景及进阶用法》:本文主要介绍JavaScript中的reduce方法执行过程、使用场景及进阶用法的相关资料,reduce是JavaScri... 目录1. 什么是reduce2. reduce语法2.1 语法2.2 参数说明3. reduce执行过程

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2

Java调用DeepSeek API的最佳实践及详细代码示例

《Java调用DeepSeekAPI的最佳实践及详细代码示例》:本文主要介绍如何使用Java调用DeepSeekAPI,包括获取API密钥、添加HTTP客户端依赖、创建HTTP请求、处理响应、... 目录1. 获取API密钥2. 添加HTTP客户端依赖3. 创建HTTP请求4. 处理响应5. 错误处理6.

Spring AI集成DeepSeek的详细步骤

《SpringAI集成DeepSeek的详细步骤》DeepSeek作为一款卓越的国产AI模型,越来越多的公司考虑在自己的应用中集成,对于Java应用来说,我们可以借助SpringAI集成DeepSe... 目录DeepSeek 介绍Spring AI 是什么?1、环境准备2、构建项目2.1、pom依赖2.2