首页 文章 精选 留言 我的

精选列表

搜索[VMware替代],共10000篇文章
优秀的个人博客,低调大师

微服务--分布式事务的实现方法及替代方案

这两天正在研究微服务架构中分布式事务的处理方案, 做一个小小的总结, 作为备忘. 如有错误, 欢迎指正! 概念澄清 事务补偿机制: 在事务链中的任何一个正向事务操作, 都必须存在一个完全符合回滚规则的可逆事务. CAP理论: CAP(Consistency, Availability, Partition Tolerance), 阐述了一个分布式系统的三个主要方面, 只能同时择其二进行实现. 常见的有CP系统, AP系统. 幂等性: 简单的说, 业务操作支持重试, 不会产生不利影响. 常见的实现方式: 为消息额外增加唯一ID. BASE(Basically avaliable, soft state, eventually consistent): 是分布式事务实现的一种理论标准. 柔性事务 vs. 刚性事务 刚性事务是指严格遵循ACID原则的事务, 例如单机环境下的数据库事务. 柔性事务是指遵循BASE理论的事务, 通常用在分布式环境中, 常见的实现方式有: 两阶段提交(2PC), TCC补偿型提交, 基于消息的异步确保型, 最大努力通知型. 通常对本地事务采用刚性事务, 分布式事务使用柔性事务. 最佳实践 先上结论, 再分别介绍分布式事务的各种实现方式. 如果业务场景需要强一致性, 那么尽量避免将它们放在不同服务中, 也就是尽量使用本地事务, 避免使用强一致性的分布式事务. 如果业务场景能够接受最终一致性, 那么最好是使用基于消息的最终一致性的方案(异步确保型)来解决. 如果业务场景需要强一致性, 并且只能够进行分布式服务部署, 那么最好是使用TCC方案而不是2PC方案来解决. 注意: 以下每种方案都有不同的适用场合, 需要根据实际业务场景来选择. 两阶段提交(2PC) 两阶段提交(Two Phase Commit, 2PC), 具有强一致性, 是CP系统的一种典型实现. 两阶段提交, 常见的标准是XA, JTA等. 例如Oracle的数据库支持XA. 下图是两阶段提交的示意图: 2pc 图的上半是两阶段提交成功的演示, 下半是两阶段提交失败的演示. 关于两阶段提交网上有很多经典的讲解, 这里就不细说了, 可以参考前面的链接. 缺点 两阶段提交中的第二阶段, 协调者需要等待所有参与者发出yes请求, 或者一个参与者发出no请求后, 才能执行提交或者中断操作. 这会造成长时间同时锁住多个资源, 造成性能瓶颈, 如果参与者有一个耗时长的操作, 性能损耗会更明显. 实现复杂, 不利于系统的扩展, 不推荐. TCC (Try-Confirm-Cancle) TCC, 是基于补偿型事务的AP系统的一种实现, 具有最终一致性. TCC流程 下面以客户购买商品时的付款操作为例进行讲解: Try: 完成所有的业务检查(一致性),预留必须业务资源(准隔离性); 体现在本例中, 就是确认客户账户余额足够支付(一致性), 锁住客户账户, 商户账户(准隔离性). Confirm: 使用Try阶段预留的业务资源执行业务(业务操作必须是幂等的), 如果执行出现异常, 要进行重试. 在这里就是执行客户账户扣款, 商户账户入账操作. Cancle: 释放Try阶段预留的业务资源, 在这里就是释放客户账户和商户账户的锁; 如果任一子业务在Confirm阶段有操作无法执行成功, 会造成对业务活动管理器的响应超时, 此时要对其他业务执行补偿性事务. 如果补偿操作执行也出现异常, 必须进行重试, 若实在无法执行成功, 则事务管理器必须能够感知到失败的操作, 进行log(用于事后人工进行补偿性事务操作或者交由中间件接管在之后进行补偿性事务操作). 优点 对比与前面提到的两阶段提交法, 有两大优势: TCC能够对分布式事务中的各个资源进行分别锁定, 分别提交与释放, 例如, 假设有AB两个操作, 假设A操作耗时短, 那么A就能较快的完成自身的try-confirm-cancel流程, 释放资源. 无需等待B操作. 如果事后出现问题, 追加执行补偿性事务即可. TCC是绑定在各个子业务上的(除了cancle中的全局回滚操作), 也就是各服务之间可以在一定程度上”异步并行”执行. 注意事项 事务管理器(协调器)这个节点必须以带同步复制语义的高可用集群(HAC)方式部署. 事务管理器(协调器)还需要使用多数派算法来避免集群发生脑裂问题. 适用场景 严格一致性 执行时间短 实时性要求高 举例: 红包, 收付款业务. 异步确保型 通过将一系列同步的事务操作变为基于消息执行的异步操作, 避免了分布式事务中的同步阻塞操作的影响. 这个方案真正实现了两个服务的解耦, 解耦的关键就是异步消息和补偿性事务. 这里以一个例子作为讲解: 异步确保型 执行步骤如下: MQ发送方发送远程事务消息到MQ Server; MQ Server给予响应, 表明事务消息已成功到达MQ Server. MQ发送方Commit本地事务. 若本地事务Commit成功, 则通知MQ Server允许对应事务消息被消费; 若本地事务失败, 则通知MQ Server对应事务消息应被丢弃. 若MQ发送方超时未对MQ Server作出本地事务执行状态的反馈, 那么需要MQ Servfer向MQ发送方主动回查事务状态, 以决定事务消息是否能被消费. 当得知本地事务执行成功时, MQ Server允许MQ订阅方消费本条事务消息. 需要额外说明的一点, 就是事务消息投递到MQ订阅方后, 并不一定能够成功执行. 需要MQ订阅方主动给予消费反馈(ack) 如果MQ订阅方执行远程事务成功, 则给予消费成功的ack, 那么MQ Server可以安全将事务消息移除; 如果执行失败, MQ Server需要对消息重新投递, 直至消费成功. 注意事项 消息中间件在系统中扮演一个重要的角色, 所有的事务消息都需要通过它来传达, 所以消息中间件也需要支持 HAC 来确保事务消息不丢失. 根据业务逻辑的具体实现不同,还可能需要对消息中间件增加消息不重复, 不乱序等其它要求. 适用场景 执行周期较长 实时性要求不高 例如: 跨行转账/汇款业务(两个服务分别在不同的银行中) 退货/退款业务 财务, 账单统计业务(先发送到消息中间件, 然后进行批量记账) 最大努力通知型 这是分布式事务中要求最低的一种, 也可以通过消息中间件实现, 与前面异步确保型操作不同的一点是, 在消息由MQ Server投递到消费者之后, 允许在达到最大重试次数之后正常结束事务. 适用场景 交易结果消息的通知等. 小结 不管是同步事务中的事务管理器(协调者), 还是异步事务中使用的消息中间件,若要达到一致性保证,都需要使用带有同步复制语义的 HAC 提供的高可用和高可靠特性,这些都是以性能为代价的,无疑成为了SOA 架构中的典型性能瓶颈之一.

优秀的个人博客,低调大师

OLTP新贵G家F1的替代者TiDB

HBase 简介 众所周知,在 SQL 方面处于顶级的有两个公司,一个是Oracle,他们已经积累了大量的经验,另一个是谷歌,谷歌 F1 在2012年发布了一篇论文,个人认为它是全球最优秀的 SQL OLTP 数据库。 1978年左右,数据库刚刚发展时出现了SQL RDBMS。2000年左右,国内开始流行互联网,互联网对 Oracle 数据库也产生较大的冲击。现在,传统的数据库大部分是集中在传统领域,互联网方面用得比较多的是 MySQL ,其次 HBase 等 NoSQL 也吸引了大量的用户。 为什么会出现 NoSQL?最开始所有人都用 SQL Database,那时比较高端有 Oracle,开源的还有 MySQL、PostgreSQL。可是随着业务的迅速发展,数据库成为了瓶颈,于是促使了 NoSQL 的诞生,NoSQL 将 Scale 放在第一位。如果业务快速发展,扩容会成为亟待解决的首要问题。这时,大多数人会选择放弃事务一致性。什么是一致性?比如使用微信时,如果我加你为好友,这是一个双向关系,对应到数据库中至少是两个操作,第一是在好友列表里把你加进来,第二个是你的好友列表里把我加进去。如果这两个列表的数据库放在不同的机器上,就需要保证一致性。否则可能会出现我是你的好友,但你的好友中却找不到我的这种情况。但这中间可能会出现多种情况,比如我把你加为好友,然后修改数据的时候 Crush 掉了,这个时候传统方案是会引入一个消息队列,有的还需要做一些补偿,这些问题在 NoSQL 里处理起来相对麻烦。 国内最大的 HBase 使用者是小米公司,有几个 HBase 的 Committer ,所以经过一些修改后可以支持分布式事务,于是能够解决之前的问题。为什么在面临诸多选择时,小米会选择 HBase 呢?就目前情况来说,主要还是技术选型和人才储备上的考虑。MongoDB大家应该不陌生,但用到一定程度后,总会出现各种问题,甚至有文章呼吁大家放弃 MongoDB 。但所有数据库都不是“十全十美”的,没有最好,选择最适合的尤为重要。 很多时候产品都有其特性,在满足其特性或者规格的情况下,使用起来可能非常顺手,否则十之八九都遇到各种麻烦。比如小米使用 HBase 就非常顺手,但其他的公司则不一定。道理很简单,如果不熟悉其使用场景,也不知道在相应场景下配什么参数,所以会出现各种各样的问题。 事实上,HBase 有非常好的特性,目前在小米公司可以每秒跑一百万 OPS ,最近 Pinterest 公布他们的 HBase 每秒可以跑三百万个 OPS ,这个数量级可以远超很多互联网公司。 HBase 在读写一致性方面非常出色,有很好的自动 Scale 的能力,通过Block Cache 和 Bloom Filters可以很好的解决查询问题,是否在磁盘上也可以通过Bloom Filters来判定。 另一方面,Oracle 把一部分逻辑会放在 CPU/硬件里,对应的 HBase 也会把一部分逻辑下推到对应的 RegionServer 上。对于一个分布系统来说,如果需要查询一个条件,可以直接把这个简单调节推到对应的 RegionServer 上执行。再比如求和运算,现在有一百亿数据,甚至一千亿条数据,分布在10个节点上,最快的求和方法是让所有节点同时运算,将这个条件下推得到所有对应数据的和,最后收集到10个数据的和即可。其实还可以继续往下推,这是比较复杂的数据库优化技术,实际情况还会更复杂。这在 HBase 里面依赖 Coprocessor 来实现。 大家应该对 MVCC 比较熟悉,也就是多版本,它的优点在于可以多次读取而不会 block。然后还有一个很好的特性,假设你用的 Database ,MVCC 在你没有做 compaction 之前可以回到任何时间的数据。现在云服务上也可以每隔半小时做一次快照,实际上如果使用 MVCC 回到任意一秒的话,可以完全不需要快照。 TiDB的优势 下面再介绍一下我们的产品 TiDB,Ti 是元素周期表里的元素。大家如果了解我们团队的程序员,就知道他们都比较 Geek,取名字要么在希腊神话里选一个神的名字,或者在数学里找一个希腊字母, 但是看了一圈,好坑都已经被占上了。于是,我们在化学元素周期表里找了一个金属作为项目名称,对于 Database 而言,它必须是高速稳定的,刚好钛金属有很强的防腐蚀性,所以选择了钛(Ti)。 因为 TiDB 的目标是谷歌 F1,所以自然会满足以上特性。首先是可以满足分布式一致,也就是说对于应用来说,不用关心后面分成多少个机器,事务的一致性是必须保证的,比如我们之前提到的 A 关注 B,两个互相加好友或者转帐,可以直接利用一条 SQL 搞定,而无需担心中间过程。另外一个特性是兼容 MySQL 协议,国内大概有70% 的互联网公司都在使用 MySQL,为了考虑大家的迁移成本,我们会兼容 MySQL 协议。同时,由于已经很多 APP 在 MySQL 上运行,为我们提供了充足的测试样本。 TiDB 的测试有五百多万个,每次提交一行代码时,后面大概有6个机器并行地跑 Test ,五百多万 Test 所需时间大约是十分钟。为了照顾各种引擎爱好者,我们还支持了 LevelDB 、RocksDB、LMDB、BoltDB 等。TiDB 主要是采用 Go 语言开发的,其代码简单、易于理解,而且性能非常高。 系统架构 任何用 MySQL 协议写的程序都可以直接使用 TiDB ,其中间是 MySQL 协议相关的内容,再往下是 SQL Layer。其次是事务 KV 层,这正是 F1 和 Spanner 构造得最为精密的地方。最底层的构造是从 KV 开始,在 KV 基础上架一个分布式的 KV 层用于支持事务,然后再让 SQL 语句直接映射到 KV 层上。 接下来,向大家介绍 现阶段 TiDB 使用的分布式事务是如何在 HBase 上实现的,早期版本中,我们参考的是 Google 的 Percolator 的模型。首先假设有一个 Client,先为其分配一个 Timestamp,在 Google 论文中叫做Time Oracle,用来分配时间戳。分配之后可以做读写操作,根据时间戳进行快照读。最后提交之前要先 Prepare ,Prepare的时候会检测是否冲突,最后提交时会得到 Commit ,如果整个过程没有任何冲突就可以提交。上图代表了一个实例,最初帐户情况是 Bob 有10美金,而 Joe 有5美金。前面的数字代表其版本,当前是第6个版本,指向的是第5个版本,为10美金,Joe 是2美金。 假设Bob要转4美金给 Joe。第一步,要先转出去4美金,10美金变成6美金,由于被扣掉4美金,然后会标注一下自己是主锁。 Joe当前是第7个版本,因为他得到了4美金,所以余额变成了6美金,同时标记自己指向另外一个主锁 Bob。 到第八个版本时,主锁会指向现在的7,这时可以把主锁删掉。如果访问的时候发现主锁被删除,那么主锁冲突已不存在,可以进行提交。同时,它会把自己的锁删掉,中间还有一些其它的清理过程。 整个事务模型中会有单点,从 Time Oracle 分配一个时间戳,单点决定了整个系统的性能。Google 论文里有一个对应描述,可以跑到两百万每秒。因为事务开始和结束的时候都需要取一个 Timestamp ,所以他们最快读写事务的速度是一百万每秒,他们已经在论文中实现。实际上,现在有更好的方式可以提高速度,如 HLC 和一些 Time Oracle的改进算法。关于 Spanner ,我们重点参考对象是谷歌 Spanner 和 F1 。由于 Spanner 高度依赖于时钟,所以谷歌有一套原子钟和 GPS 时钟,GPS 信号可以给出地理位置和时间。为什么需要原子钟呢?由于 GPS 时钟特别容易受到干扰,比如天气恶劣时 GPS 时钟就不能运行,而原子钟仍然适用。 上图是谷歌 F1 的一些信息,其中单独标记了谷歌 F1 的这篇论文,大家有兴趣的话不妨细读一番,目前整个 TiDB 所做的都是在实现这篇论文。假设有一千亿数据,你现在要给某一列加索引时,在传统数据库上应该如何操作?比如说在分布式环境下,你用MySQL 给一列添加一个索引,这几乎很难实现,而且还必须保证 index 的一致性。更多细节请参考论文。 TiDB 是如何从 SQL 迁移到 KV 上的呢?由基础知识可知,传统的 RDBMS 数据库底下一般是一个 B-Tree。对于分布式关系型数据库,站在更上层一点看,比如谷歌的F1,数据库底层都是 KV 层,都在 KV 层逻辑下操作。如果有一个 User Table,在 TiDB 里假设你的Table的结构是由 uid、name和 email 构成。在 TiDB 里有一个隐藏列叫做 RowID ,所有的操作包括行锁都是锁的 RowID 。假设 RowID 是1, uid 是XX,Name 是 Bob,Email 是 bob@Email.com,这都属于元信息。即便你的 Column name 很长,但最后在数据库里存储的是原信息。在 TiDB 中, 每一列都有唯一的UID。 假设 Table 的 ID 是1,uid 的 ID 是2,name 的ID是3,email 的 ID 是4。在数据库中存储为一个 KV 结构,然后对 TableID、RowID 、ColumnID 进行重新编码,直接将这个表的一行切成4个 KV 。这时候如果进行 select , Email 等于某一个值的话,于是可以直接取出来相应的值,速度非常快。 兼容 MySQL TiDB 对 MySQL 协议有很好的兼容性。有一些比较知名的 MySQL 应用和管理工具,比如WordPress、PhpMyAdmin, MySQL Workbench,都可以直接基于 TiDB 运行。而且数据可以无限扩展,不再是单机数据库。其次,TiDB 还兼容各种 ORM ,比如 XORM 、Beego ORM 等,能够支持很多 MySQL 的应用。每一次代码更新,这些 ORM Test 会自动运行一次,从而保证与 MySQL 的兼容性,虽然还有一些比较细微的特性暂时没有支持。现在已经支持异步的 Schema 变更,对于 DDL 操作,不会阻塞线上的业务。 关于社区 目前 TiDB 完全开源在 Github 上面。开源和开放的概念是两回事,很多大公司,所谓的开源只是把代码上传一下,国内比较知名的案例也挺多的,大家知道很多项目都已经放弃了维护。但是我们是打算完全以一个开放的心态来做整个事情,全部的代码,全部的讨论, Code Review,Bug Tracking,Roadmap 都是开源的,毕竟通用的分布式 OLTP 关系型数据库是一个非常前沿而且极端重要的领域,未来是云上的 DBaaS 的重要组成部分,但是在这块目前整个技术社区,即使全球来看都没有一个太成熟开源解决方案,TiDB也目前也处于早期,从架构上来看,我们将 SQL 层和 KV 层做了很彻底的分离,这也是我们希望更多开发者能根据自己的需要更方便的进行定制,我们也想得很清楚,依靠某一家公司,或者某几个人的力量是不够的,我们 PingCAP 只是将这一把火点起来,将框架搭好,制定好透明和公平的规则,吸引更多的合作公司和独立开发者,一起将 TiDB 做成中国第一个世界顶级的开源项目,实现共赢。 好的项目可以由社区进行推动,就比如 HBase,HBase 不属于任何一个公司,但是社区一直推动它进步。目前我们在 GitHub 状态是有 3200+的 Star,有 32个 Contributors,算是开了一个好头,非常感谢大家,希望大家都能参与进来。

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册