Nodejs 分布式事务

事务是恢复和并发控制的基本单位,保证 ACID:原子性、一致性、隔离性、持久性。

对于全是异步的 Nodejs 而言, 并不适合做事务操作:

  1. 代码书写上:

    • try ... catch ... 是写给人看的,但是属于同步方法,局限性很大。

    • callback 简直是噩梦。

    • Promise.then(...).catch(...) 相对而言好一点。

    • ES7 的 async ... await ... 比较清爽,使用 Babel 编译,这是笔者目前找到的最人类的方式,但是和原来的 Promise 混合使用的时候有时候会出问题,因为编译之后的代码没法看,最后还得重构回 Promise

  2. 异步:

    • 异步导致有可能有意料之外的 uncaughtExceptionError 。

    • 对于 JAVA/C++ 这样语言,出错能直接转到 catch 中,但是 Node 不是,uncaughtExceptionError 将直接导致处理链断掉,你只能通过其他方式保证数据一致性。

虽然 Node 做事务相当非人类,但是考虑开发效率 / 成本,使用 Node 进行开发并不比换语言开差,毕竟事务只有核心业务需要用到。

单点

单机的事务相当容易保证,特别在依赖 MySQL 或者其他关系数据库时。

Nodejs 有 ORM (如 Sequelize ) 支持事务,也可以直接使用 PROCEDURE/FUNCTION

两者各有优势:

  • ORM 适合复杂逻辑的事务;

  • 存储过程可以有效减少 IO 次数,防止使用 ORM 时回滚失败。

实际开发过程中可以将两者结合起来一起使用,使用 ORM 完成逻辑,使用存储过程减少 IO 次数。

分布式

对于分布式系统,相信很多人都知道 CAP 理论,即任何一个分布式系统无法同时满足:

  • Consistency (一致性)

  • Availability (可用性)

  • Partition tolerance (分区容错性)

但是实际上 Consistency 是任何一个系统都不可能放弃的,分布式事务亦是为了保证数据一致性,有时候为了妥协另外两个特性,会放弃强一致性,保证最终一致性

解决方式

目前业界有很多解决分布式事务的方案,根据对数据一致性的强弱要求,可以选择不同的方案,但是解决思路大致如下:

  1. 两阶段提交

如 XA 协议(TM(事务管理器)和RM(资源管理器)之间的接口)。

假设有 A、B、C 三个操作,第一阶段,等待 A B C 均就绪,第二阶段,提交 A B C;如果第一阶段 A 失败了,则第二阶段回滚 B C。

  1. 本地事务

使用本地消息表,将远程事务拆分成一个个本地事务,写入本地表中,然后 定时 / 使用 MQ 通知事务方。

两者各有利弊,定时扫描可能大部分时候都在做无用功,而只使用 MQ 可能会有失败 / 多次消费的问题。

  1. 使用回滚接口

如 A B 两个接口,串行处理,B 失败了回滚 A ,但是回滚也可能失败,所以也需要使用本地事务表 / MQ。

使用 Node 开发,1 比较重型,不适合;2 和 3 是比较好的选择:

  1. 选择一款可靠的 MQ 服务(单次消费 / 失败重试);

  2. 拆分本地事务;

  3. 不能拆分的事务,保证回滚。

举个栗子

做一个抢购系统,用户使用虚拟币进行抢购,虚拟币是另外一套系统。为了考虑到公平,每个用户还可能要限制购买上限。

这样用户一次抢购的完整流程如下:

  1. 检查购买上限

  2. 检查总数

  3. 扣除虚拟币

  4. 写入数据库

需要事务保证的地方就是 3 和 4,3 是远程事务,4 是本地事务,此栗子中必然是串行操作,3 在前,4 在后。

0x0001

这个时候流量很少,并发不高,将 3 和 4 作为一个事务,保证一起成功,而失败一起回滚。

事务 4 即使使用 ORM 完成,也能完成功能,这个时候系统能很好的工作。

0x0010

流量上升中,抢购的商品变多,并发也变大,这个时候,考虑使用 Redis 来提高性能了(牺牲强一致性):

将 购买上限 与 总数 写入 Redis,在压力转嫁到数据库之前就挡掉,由于 Redis 的强大性能,可以假设 Redis 等同于内存操作,做好回滚就可以了。

同时可以将事务 4 重构成 PROCEDURE 防止 ORM 可能回滚失败。

0x0011

流量大到数据库扛不住了,加入 MQ 服务:

使用 Redis 抗住流量,使用 MQ 抗住压力,使用 PROCEDURE 降低 IO 。

0x0011 看起来像一个可靠的系统了,但是还有一个隐患: uncaughtExceptionError 或者 程序宕掉了,这个会影响最终一致性,导致 Redis 数据与 Database 中的数据在抢购临界结束的时候不一致。

0x0100

增加最终一致性保证。

抢购的栗子有个很特别的地方,就是 total limit ,达到总数上限之后,就只有 MQ 中的部分需要处理了,因此可以很巧妙的利用时间差,即考虑在达到上限之后,取一次数据库快照,延迟一段时间之后,再对比一次数据库,判断是数据不一致还是正常逻辑。

这是一个投机取巧的处理方式,一定程度上可以保证最终一致性。当然,还是人最靠谱了,程序搞不定,人工修复嘛,ORZ~。

终语

分布式事务是一个很大的话题,依据业务量大小可以给出很多实现。

Nodejs 做分布式事务勉勉强强,异步里面的雷很多,不过依赖良好的设计和逻辑一样可以实现。

Nodejs 分布式事务相关推荐

  1. node.js - Nodejs 分布式事务_个人文章 - SegmentFault 思否

    事务是恢复和并发控制的基本单位,保证 ACID:原子性.一致性.隔离性.持久性. 对于全是异步的 Nodejs 而言, 并不适合做事务操作: 代码书写上: try ... catch ... 是写给人 ...

  2. 分布式事务,再说说解决方案

    Savorboard 『代码如诗』 ┈这是我们为世界写的诗歌. 博客园 首页 联系 订阅 管理 随笔 - 94  文章 - 0  评论 - 1702 聊聊分布式事务,再说说解决方案 前言 最近很久没有 ...

  3. rabbitmq 查询版本_基于rabbitmq解决分布式事务

    分布式事务要解决的问题是保证二个数据库数据的一致性,本地事务ACID属于刚性事务,基于CAP理论,分布式事务的核心要点柔性事务,最终一致性. 基于rabbitmq解决分布式事务要点如下 生产者采用发送 ...

  4. TCC分布式事务的实现原理

    目录 一.写在前面 二.业务场景介绍 三.进一步思考 四.落地实现TCC分布式事务 (1)TCC实现阶段一:Try (2)TCC实现阶段二:Confirm (3)TCC实现阶段三:Cancel 五.总 ...

  5. 分布式事务中间件 Fescar—RM 模块源码解读

    2019独角兽企业重金招聘Python工程师标准>>> 前言 在SOA.微服务架构流行的年代,许多复杂业务上需要支持多资源占用场景,而在分布式系统中因为某个资源不足而导致其它资源占用 ...

  6. sql server分布式事务解决方案[新事务不能登记到指定的事务处理器中错误]

    < DOCTYPE html PUBLIC -WCDTD XHTML StrictEN httpwwwworgTRxhtmlDTDxhtml-strictdtd> 适用环境 操作系统:wi ...

  7. 常用的分布式事务解决方案介绍有多少种?

    关于分布式事务,工程领域主要讨论的是强一致性和最终一致性的解决方案.典型方案包括: 两阶段提交(2PC, Two-phase Commit)方案 eBay 事件队列方案 TCC 补偿模式 缓存数据最终 ...

  8. cap理论与分布式事务的解决方案

    现在很火的微服务架构所设计的系统是分布式系统.分布式系统有一个著名的CAP理论,即一个分布式系统要同时满足一致性(Consistency).可用性(Availablility)和分区容错(Partit ...

  9. zookeeper入门系列 : 分布式事务

    上一章我们了解了zookeeper到底是什么,这一章重点来看zookeeper当初到底面临什么问题?而zookeeper又是如何解决这些问题的? 实际上zookeeper主要就是解决分布式环境下的一致 ...

最新文章

  1. weblogic创建域后启动不了_WebLogic的Azure虚拟机主要版本发布
  2. 实习随记-不定时更新
  3. c++快速排序(附完整源码)
  4. [Android] DownloadManager下载管理类2.3新增API介绍
  5. 深入Java集合系列之五:PriorityQueue
  6. 为数据计算提供强力引擎,阿里云文件存储HDFS v1.0公测发布
  7. 诺基亚2亿欧元建越南新工场
  8. 嵩天python爬虫_我自己爬-python爬虫快速入门(一)
  9. 2020 科大讯飞全球开发者大会节目单来了!
  10. java类型转换_Java类型转换
  11. c 取数组 最大值 算法_拜托,面试别再问我最大值最小值了!!!
  12. 计算机菜单界面无法缩小怎么办,如何解决Win10个性化设置最小化任务栏后不能弹出的问题?...
  13. Windows内核面试题(持续更新,目前完成度30%约1.8万字)
  14. bzoj4568-幸运数字
  15. 案例学习——创建你的第一个Substance Designer材质球
  16. 使用python内置函数进行常规API接口调用
  17. 推荐12个免费查找文献的学术网站,建议点赞、收藏!
  18. 文件系统源码分析之buffer.c
  19. 海思平台ISP调试经验
  20. 操作系统、输入法和编码的理解

热门文章

  1. Win7系统忘记登入密码的解决方法
  2. iATKOSv7+硬盘安装助手+变色龙
  3. Linux Shell高级技巧(二)
  4. PHP中功能强大却少使用的函数 -- 为你提供更多的思路
  5. TCP连接三次握手和四次挥手
  6. mysql 中文乱码解决办法
  7. 【设计模式】设计模式C++编程实现之策略模式(Strategy Pattern)
  8. ArrayList 有序集合 c#
  9. 接口 java 1614953826
  10. 章二测试 1613999388