はじめに:ブロガーはサイクリングレスリングを気にしないので、最近、自宅で自分自身を与え、療養が影響を与えただけでなく、会社に影響を与えて、時間に登録しませんでした。私は再び、携帯電話の手を取ることはありません、自転車に乗ったときに注意する必要があります願っています:道路千万、安全第一、非標準を駆動する、涙の親戚の2行。まあ、これは血液の教訓です。今日のトピックは、ハッハッハ、自転車に乗る方法教示されていません。自宅に近いが、自宅で使用して、頻繁に尋ねたマイクロサービスアーキテクチャのインタビューの中で分散トランザクションの問題を解決する方法をまとめ静養。この問題のため、そして、答えはまた、多くの情報を確認するためにダウンではなく、非常に良いですが、何か間違った大物も指導の多くを求めることができますがある場合、についての学習の経験を総括。
まず、理論的
まず、問題はこの質問を考慮することがされていないスタンドアロンシステムでは、マイクロサービスアーキテクチャ、分散環境であり、我々は最初のベースキャップの原則を見て、分散システムの理論。
私たちは、これが唯一の2までの3つの機能を満たすことができることを知って、3人は両方を持つことはできません。一貫性:同一時点のすべてのノードは、すべてのデータが一致しています。可用性:いつでも分散システムは、常に成功した読み取りおよび書き込みすることができます。分割耐性:ネットワーク障害のいくつかのノードでは、まだサービスの一貫性と可用性を満たすことができます。
CAを選択:pは、分散システムを放棄放棄すると等価である、唯一のスタンドアロンシステムに存在する
選択CP:つまり、一時的なサービスは、極端な場合には使用できない可能、分割耐性と強い一貫性を選択してください。
APを選択:短いデータの矛盾が可能、短期のサービスデータに登録された一貫性のないシーン、サービスには影響しません。したがって、マイクロレジストリサービスのAP原理の使用は、より適切な選択です。
次いで、語彙の下部に示される塩基理論を導入し、基本的な基本的に利用可能な基地手段は、ソフトステートソフトステートは、結果整合最終整合性(状態が短い時間同期、非同期を許可しない)は、CAPの一貫利用可能ですおよびユーザビリティのトレードオフの結果は、核となるアイデアは、BASEが強い整合性を行うことができない場合でも、また、システムの特性に最終的な一貫性を達成するための適切な方法をベースとすることです。この理論的な知識に基づいて、限り、我々がそうであるように、最終的な整合性の問題は、分散システムで解決することができます。分散システムでは、最も重要なことは、むしろ抽象的、絶対的なシステム特性の追求よりも、ビジネスニーズを満たすことです。
あなたが感じたりした場合はCAPの提案参照フレームワークにこの記事を理解していない。https://www.cnblogs.com/savorboard/p/base-an-acid-alternative.html
二、シーン
百聞は一見にしかずです。
第三に、ソリューションの分析
ソリューション:
(1)剛性総務
グローバル・トランザクション(標準分散トランザクション)
長所:厳格なACID。
短所:効率が非常に低い(マイクロアーキテクチャの下ではあまり適切なサービスされています)
理由:1)グローバル・トランザクション・モードでは、グローバル・トランザクション・マネージャ(TM)は、2つのXAインタフェースステージを使用してプロトコル(2PC)とリソース層(例えば、データベースと相互作用する)をコミット。グローバル・トランザクションが終了するまで、トランザクション全体渡ってグローバル・トランザクション、データのロック時間を使用してください。
2)2PC抗スケーラブルなモデル、トランザクション処理、ビジネス状況の時に大規模化、より多くの明白な限界の2PCように参加者は、全体の分散トランザクションが終了するまで保持するためのリソースを持っている必要があります、システムの拡張性が悪くなります。
3)ローカルトランザクションと比較すると、XAプロトコルのオーバーヘッドがかなりあるので、慎重に、本当に分散トランザクションを必要とするかどうかを検討すべきです。そして唯一の分散トランザクションに参加するXAプロトコルのリソースをサポートしています。
(2)柔軟な業務
信頼できる情報源最終的な整合性(非同期そのタイプを確保)
TCC(二段型、補償型)[省略]
(校正定期的に、非信頼できる情報源)を通知するために最善の努力[省略]
我们现在知道有这么多解决分布式事务的方案,我们能否自己去实现一个分布式事务框架呢?假如我们选择柔性事务中的,可靠消息最终一致(异步确保型)这种方案来实现就不得不涉及到消息中间件的使用了,消息中间价在分布式系统中的主要作用是,异步通讯、解耦、削峰填谷等。如下图所示:
如果按照上面的图,大家可能认为它很简单呀,一个发送消息,一个接受消息。但是在分布式系统中,需要通过网络进行通信的,就引入了数据传输的不确定性,也就是CAP理论中的P(分区容错性的问题),如下图所示:
很显然,正是因为跨网络,就会产生消息发送不一致的问题,也就是说,如果我的业务操作成功,那么有这个业务操作所产生的消息一定要成功投递出去,否则就丢失消息。那么我们该怎么解决这样的问题呢?
也就是如何保障消息发送一致性?通常我们在使用消息队列来处理业务都会遇到这样的场景:
public void CompleteOrder() { //订单处理 orderService.OrderProcess(); //财务处理(发送消息) ...... }
(1)如果业务操作成功,执行消息发送前应用故障,消息发送不去去,导致消息丢失(订单系统和财务系统数据产生不一致)
(2)如果业务操作成功,应用正常,但消息系统故障或者网络故障,也会导致消息发送不出去(订单系统和财务系统数据产生不一致)。
另外一种处理方案:
public void CompleteOrder() { //财务处理(发送消息) ...... //订单处理 orderService.OrderProcess(); }
也就是,我先发送消息再处理订单,这种做法更不可控了,消息发送出去了,但是订单处理失败了(导致订单和财务系统数据的不一致),记住在处理这种场景,一定是业务数据先入库,再发送消息的。
貌似这两种方式都不能保证业务数据的一致性,当然,我们可以借助JMS标准中的XA协议方式来保证消息发送的一致性,但是这种方式引入了XA,违背了柔性事务的初衷,会带来很多局限性:
(1)要求业务操作的资源(也就是数据库)必须支持XA协议(并不是所有的数据库都支持XA)
(2)两阶段提交协议的成本
(3)持久化成本等DTP模型的局限性(全局锁、成本高、性能低)
另外一种变通的做法如下:(这种方案只是解决的业务处理成功,消息一定能发送到消息中间件中)
问题:
(1)上面的消息发送一致性方案的正向流程是可行的,但是如果遇到异常流程该怎么处理?
(2)消息发送到消息中间件能得到保障,但是消息的准确消费又如何保障呢?
(3)有没有支持这种发送一致性流程的现成消息中间件?
先来聊聊问题(1),有哪些场景会出现异常,如下图所示:
从主动应用方(生产者)来分析:
(1)预发消息失败,消息未进行存储,业务操作未执行(可能的原因:主动方应用、网络、消息中间件、消息存储等),这种场景不会出现不一致性。
(2)预发送消息后,主动方应用没有收到返回消息存储结果,可能的状态有:消息未进行存储,业务操作未执行(不会出现不一致性);如果消息已进行存储【待确认】,业务操作未执行,会出现不一致性。
(3)收到消息存储成功的返回结果,但未执行业务操作就失败,可能的状态有:消息已进行存储【待确认】,业务操作未执行,会出现不一致性的问题。
从消息中间件的角度分析:
(1)消息中间件没有收到主动方应用的业务操作处理结果,可能的状态:消息已经存储(待确认),业务操作未执行(或者业务操作出错回滚了),会出现数据的不一致性问题;如果消息已经存储(待确认),业务操作成功,也会出现数据的不一致性。
(2)消息中间件收到业务操作结果(成功/失败),但处理消息存储中的消息状态失败,可能的状态:消息已经存储(待确认),业务操作未执行(或业务操作出错回滚了),会出现数据的不一致性问题;如果消息已经存储(待确认),业务操作成功,也会出现数据的不一致性问题。
那我们该如何处理这样的异常问题呢?如下图所示:
这样就可以处理异常的流程,有人可能会说,异常处理流程也可能发生异常呀,其实大家认真看的话,异常处理基本上都是查询,如果查询出现了异常,定时补救也是可以的。
总结:关于上面异常处理总结
(1)消息未进存储,业务操作未执行,不会出现一致性问题。
(2)消息已进行存储(待确认),业务操作未执行,会出现一致性问题,异常处理手段,确认业务操作结果,处理消息【删除消息】
(3)消息已进行存储(待确认),业务操作成功,会出现一致性问题,异常处理手段,确认业务操作结果,处理消息【更新消息状态,执行消息投递】
对于问题(3)有没有现成的消息中间件支持消息发送一致性,答案是:没有。是因为常用的MQ队列消息的处理流程无法实现消息发送一致性,因此直接使用现成的MQ中间件产品无法实现可靠消息最终一致性的分布式解决方案。
对于问题(2)消息发送到消息中间件能得到保障,但是消息的准确消费又如何保障呢?
以前的流程,如下图所示:
红框圈住的就是消息的消费流程,在这个流程中,任何一个环节都有可能出问题具体到下面这张图:
那我们如何处理,这些异常呢?处理的方法有很多,这里列出常规的做法:对于未确认的消息,采用按照规则重新投递的方式进行处理。这里就不介绍了, 当然,我们需要处理极端情况:消息重发也得有次数限制,要不然就变成了死循环,对于超过重发次数的消息,进入到死信队列,等待人工干预或者延后定期处理。同时也需要处理被动方在处理业务时要实现幂等操作。
四、总结
好了,暂时分享到这里吧,虽然在分布式系统中已经有现成的框架,比如.net core 中的 CAP框架,非常的不错,我们生产环境中已经用了很长时间,框架能帮助我们解决实际场景下的问题,但是我们也要明白框架背后的原理,明白大概的原理,再去看CAP的源码,你会恍然大悟的!哈哈哈哈。
参考资料:
龙果学院 吴水成老师 《微服务架构的分布式事务解决方案》 https://www.roncoo.com/details/7ae3d7eddc4742f78b0548aa8bd9ccdb
CAP框架作者 杨老师 https://www.cnblogs.com/savorboard/p/base-an-acid-alternative.html
作者:郭峥
出处:http://www.cnblogs.com/runningsmallguo/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。