分布式事务实现

yang_9875 2020-07-19 03:13:09
现在有2个服务,一个订单服务(springboot后台),一个账户服务(.netcore后台),涉及到付款时扣减账户和同时修改订单状态(减还有库存)的操作,以前没做过,了解了下大概是TCC或者是2PC,但是他们的框架都是JAVA下的,好像没有.net的实现,或者还有基于MQ的实现,问下这种分布式事务如何实现,用什么技术或者框架,或者方案。
...全文
3219 16 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
现在的所谓“分布式、大数据”编程,绝大多数,还是许多分布式进程去针对关系数据库、NoSql文件数据库、共享内存数据库去“增删改查”。也就是说各个进程与数据是分离的,并且各种进程是争抢同一份数据的,而且各个进程要针对底层基础数据的不同模式(关系数据库的、NoSql数据库的、内存缓存的)分别写不同的程序。于是,各种调和一致性矛盾、沟通计算次序的所谓“大数据框架”应运而生了。以我的观察,90%都是骗人的,都是为了让传统的程序员带一些小白干苦活儿而发明的。因为90%其实都是因为沿用了传统的关系数据库的“增删改查”编程理念而一步步造成的尴尬问题。

一套分布式缓存数据管理系统,应用程序程序员不用针对关系数据库和 Cache 数据库分别编写两套代码,数据在网络上感觉永远存在、并且从不落地。并且编写的业务处理代码就跟传统关系数据库的“存储过程”似地不用再考虑什么远程增删改查,而是本地操作数据就行了。说白了,现在的所谓“大数据、分布式”里边的90%的噱头的纠结,大多都是因为将进程与数据分离而造成。
  • 打赏
  • 举报
回复
关系数据库的事务概念是个“极限”,它使用统一的、对用户端屏蔽上锁的解决方案,来保证事务的一致性、数据可恢复性。

而“分布式事务”真正要实现,没有纯粹学术化的解决方案,不可能再在“极限上走出去更远”,必须将原来的“多分布式进程--阻塞同一份数据”的模式改为真正的离散的计算模型。之所以我认可 Orlans 是因为它是 Virtual Actor 模型,并不是因为它是微软研发的。实际上我觉得使用 Redis、MemoryCache、RabittMQ、Zookeeper 之类的,其实都是糊弄小白,让刚毕业的小白干面向网络过程的苦活,而不是干更加面向网络对象设计的技术活儿。
  • 打赏
  • 举报
回复
网上有很多人画出了漂亮的框图,把有关复杂的“长”业务事务可能涉及的各种底层技术概念、每一个都单独扯出一个“xxxx子系统”来画图。实际上长业务事务根本不能用传统关系数据库的事务概念来生搬硬套,多人合作的长事务在人类中存在了几千年,而且运行的很好,为什么有人不去研究很普通的多人协同,非要以为某个刚学关系数据库不久的、BAT刚招聘的重点大学刚毕业1年的小孩子就能“研发”业务系统呢?

其实这类“终极技术”并不存在,存在都只是一些想当然的接口。没有真正理论化抽象实现,真正的既有功能又有性能的实现,都得由每一个模块的程序设计师和测试人员专门去设计实现。
luj_1768 2020-07-20
  • 打赏
  • 举报
回复
有关事务的讨论大多比较复杂,因为这不是一个统一公式化的解决方案,而是与需求分析、方案选择与设计有关的内容。所谓事务,就是任务的各个环节、整体完成或者整体取消。前面的帖子讲到的分布式事务主要就是状态管理,其实是非常专家化的理解。在实践中设计事务,关键要找出各个环节中的核心环节(其特点是:优先权高、重要性高、敏感度高、数据量大),分析事务的失效原理和失效模型,然后设计出有关的状态量和状态管理方案,最后进行实现并加以完善(分布式方案通常要考虑延迟、缓存、数据一致性、数据锁定等复杂因素)。
正怒月神 2020-07-20
  • 打赏
  • 举报
回复
首先根据CAP理论,看你的侧重点在哪里。 一致性,容错性,可用性。 然后我感觉,适合楼主的方案是通过 消息中间件 MQ来作为中介。
  • 打赏
  • 举报
回复
说得更明白的点,其实也没有什么技术,不过是各种低级的“系统”为了各自晒接口,开放了各种基础数据“增删改查”功能服务。那么所谓的“分布式事务”任务就是要让各个子系统把基础数据修改功能接口从服务总线上撤下去,大家必须使用新设计的更庞大更复杂的任务服务。
  • 打赏
  • 举报
回复
关系数据库的“事务”其实实现起来是个非常底层的概念(这是面向现代的高并发高性能分布式系统来说的,不是面向传统的单一数据库“增删改查”来说的),传统关系数据库,一般来说,就算是你不在代码中显式起用一个事务,那么你发送的一条 sql 语句也会自动起用一个事务。而事务的方式就是把卡死相关的要读写的所有记录。所以这个概念的核心就是“卡死”!

而我们今天用的系统大多不考虑“卡死",不能给数据上锁。实际上对网络上的高速共享数据记录“上锁”的想法都会害死系统。那么传统的事务概念,就不能比较“庸俗地”移植到分布式系统上来。那种针对“基础数据”记录进行加锁的概念应该休矣了。大不了,例如上面的依据“xxxx任务”而创建的独立 Actor 对象,是唯一能改变相关各个底层基础数据的操作。底层基础数据对开发人员并不开放其它“增删改接口”,并且底层基础数据也必须是无锁的,才能保证性能。
  • 打赏
  • 举报
回复
所谓“分布式事务”并没有什么具体的抽象实现标准,你说的 TCC、2PC 已经算是最具体的东西了,需要你自己编程实现。实际上这类东西都是在开“空头支票”,假设某个具体的存储是牺牲了巨大的性能而支持某种分布式数据库(而不是分布式内存对象)事务的,那么这类东西不过是给你写个“接口”让你能把你的愿望提交给这种具体存储管理系统。但是实际上其实基本上没人能以满足性能要求的方式去实现。按照你说的2PC、TCC结合的方式去根据业务而实现就行了。

基本上不外乎就是单独设计一个“xxxx任务”原子对象,将动作抽象化为全网唯一的 Actor,它的代码能够调用不同系统发起任务,能够定时审核任务是否(预操作)成功,能够调用不同系统通知任务已经全面审核通过,或者调用各系统进行异常处理(例如冲销)。
wanghui0380 2020-07-19
  • 打赏
  • 举报
回复
为啥我们不建议一开始就各种细节,一旦细节你就忘了你要做啥了 开始俺们要弄清楚他到底要做啥,弄清楚了。其实任何方案都可用。 比如如果就是一个单机系统 Task ta Task tb alltask=await Task.WhenAll(ta,tb) alltask没有错误,不管。有错回滚。 现在分到多台机器了,那么sp会说分不分多台机器都一样olrean本来就不关心是几台机器。ta还是ta,tb还是tb。单机的task还是task,多机的task依旧还是task 不过对于混合语种开发,我们就的尽量忽略语种。我们说,还是这么几句话。只不过把状态单独抽离出来,单独放到公用系统里 比如这个上面几行代码。 任务guid xxxxxx 整体状态 子任务 guid xxxxx 子任务状态 子任务 guid yyy 子任务状态 这样来看,你只需要公用一张表,然后观察所有子任务的完成状态。 现在的问题就成了,怎么公开任务状态,怎么观察任务任务状态 所以有选mq的。提交一个子任务,让别人完成去,你等着他ack回复。超时没完成可以选择重复(考虑幂等性) 所以有选择redis的,key1,key2,当key1,key2状态都完成,那么完成。有一个没完成,回撤 所以有选etcd的,node1,node2. 还是 await node1,node2 总之我们的任务只是怎么去做一个有状态的表达,甚至我觉着如果折腾成有向图他会更有意思,那就是spark的拓扑图他自己流转去。俺们都不负责监控了
yang_9875 2020-07-19
  • 打赏
  • 举报
回复
第二种方法,就是同一服务内,多数据源的事务吧
引用 5 楼 github_36000833 的回复:
一个方法,可以把MySql等看做一个资源,把它放到一个自定义资源管理器下管理。比如自定义资源管理可以先参阅如下文章入门: 【实现资源管理器】 https://docs.microsoft.com/zh-cn/dotnet/framework/data/transactions/implementing-a-resource-manager 注:个人认为英文版比中文版容易理解。 另一个方法(如果是我,会选择这个方法),就是改写服务,使它们依赖于一个SQL服务。
yang_9875 2020-07-19
  • 打赏
  • 举报
回复
技术化才好,我得实现啊,但大的思路也得学习
引用 6 楼 wanghui0380 的回复:
讨论太技术化了 说白了,分布式事务依赖于有状态服务。所以任何一种有状态服务的技术都可以。 so,不管他是资源也好,不是资源也罢。全局能一致性状态就可。至于那临外的讨论都是一致性和高可用的讨论。过于具体技巧 只要把握住有状态,一致性就能解决问题,至于高可用只是另外的讨论 如果说有状态,一致性,就是啥不讨论什么mysql,sqlserver都一样。比如如果等会sp上来,他会说Orleans,对这个也一样能做。因为他本身就是分布式有状态提供的。 我没说这个,只是因为这个是纯微软的架子,混合开发就算了。那边的人不太会可能选择和你这样对接 在有状态和一致性,高可用3个要求下,MQ/zookeeper1/etcd/redis其实都可用,我们的任务只是把执行状态公有,至于一致性和高可用实际不太考虑(因为上面说的那些自己会保证一致性和高可用)
wanghui0380 2020-07-19
  • 打赏
  • 举报
回复
讨论太技术化了 说白了,分布式事务依赖于有状态服务。所以任何一种有状态服务的技术都可以。 so,不管他是资源也好,不是资源也罢。全局能一致性状态就可。至于那临外的讨论都是一致性和高可用的讨论。过于具体技巧 只要把握住有状态,一致性就能解决问题,至于高可用只是另外的讨论 如果说有状态,一致性,就是啥不讨论什么mysql,sqlserver都一样。比如如果等会sp上来,他会说Orleans,对这个也一样能做。因为他本身就是分布式有状态提供的。 我没说这个,只是因为这个是纯微软的架子,混合开发就算了。那边的人不太会可能选择和你这样对接 在有状态和一致性,高可用3个要求下,MQ/zookeeper1/etcd/redis其实都可用,我们的任务只是把执行状态公有,至于一致性和高可用实际不太考虑(因为上面说的那些自己会保证一致性和高可用)
github_36000833 2020-07-19
  • 打赏
  • 举报
回复
一个方法,可以把MySql等看做一个资源,把它放到一个自定义资源管理器下管理。比如自定义资源管理可以先参阅如下文章入门: 【实现资源管理器】 https://docs.microsoft.com/zh-cn/dotnet/framework/data/transactions/implementing-a-resource-manager 注:个人认为英文版比中文版容易理解。 另一个方法(如果是我,会选择这个方法),就是改写服务,使它们依赖于一个SQL服务。
yang_9875 2020-07-19
  • 打赏
  • 举报
回复
谢谢回复,现在是两个服务,每个服务的库也不同,一个mysql,一个sqlserver的
引用 2 楼 github_36000833 的回复:
你的需求,从字面上看没有分布式事务的直接需求。如果有一个核心的处理机制可以支持事务,而多个服务依赖于核心来进行业务处理,实际上并不需要分布式事务。一个具体例子就是,订单服务和账户服务使用SQL服务,并依赖于它的事务支持,这里实际上并不需要用到分布式事务。 只有当资源分布在不同节点上,才有需要用到布式事务。一个具体例子比如是用到两台SQL服务器的系统。 分布式事务也不是什么情况都能处理。比如2PC(Two Phase Commit两阶段提交)需要如下的假定: 一、所有节点不会永久性损坏 二、所有节点能预写式日志,且存储必须可靠 三、任意两个节点都能互相通讯 第二和第三比较宽松,但第一点要求就比较难(就是说可以允许一台机器垮掉,但必须保证垮掉后能够重新启动和参与恢复)。
github_36000833 2020-07-19
  • 打赏
  • 举报
回复
你的需求,从字面上看没有分布式事务的直接需求。如果有一个核心的处理机制可以支持事务,而多个服务依赖于核心来进行业务处理,实际上并不需要分布式事务。一个具体例子就是,订单服务和账户服务使用SQL服务,并依赖于它的事务支持,这里实际上并不需要用到分布式事务。 只有当资源分布在不同节点上,才有需要用到布式事务。一个具体例子比如是用到两台SQL服务器的系统。 分布式事务也不是什么情况都能处理。比如2PC(Two Phase Commit两阶段提交)需要如下的假定: 一、所有节点不会永久性损坏 二、所有节点能预写式日志,且存储必须可靠 三、任意两个节点都能互相通讯 第二和第三比较宽松,但第一点要求就比较难(就是说可以允许一台机器垮掉,但必须保证垮掉后能够重新启动和参与恢复)。
wanghui0380 2020-07-19
  • 打赏
  • 举报
回复
既然你选择混合语言开发,自然是选择和语言无关的公共环境做支撑。 所以你可以选择MQ做支撑

13,190

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 分析与设计
社区管理员
  • 分析与设计社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧