云原生(Cloud-Native)到底是什么?这个问题一直很难定义。CNCF 技术监督委员会最近通过投票确定了其官方定义。如何使其弹性可扩展、稳定高可用、敏捷易维护等特性应用到现有创新场景?
蚂蚁金服在 7 月 6 日与 AS 深圳合作举办云原生架构探讨晚场技术交流活动,邀请微服务、中间件、应用开发架构、分布式事务解决方案等技术专家,共同讨论云原生、容器、微服务、海量数据访问等话题,SOFA 的各个技术专家们很兴奋能与大家面对面交流
现场针对六个话题进行了深入探讨,气氛热烈,来自各个规模各个行业的架构师们踊跃表达着自己的实践方案和技术见解,我们特地挑选了具有代表性的话题与大家分享
1. 讨论关键词:娱乐行业,100 人技术团队,数据不一致
某互联网娱乐企业技术总监表达了自己实际遇到的问题:目前带领了 100 人左右的团队,产品用户规模 1000 万左右,并在快速增长中。
于是出现了一些“甜蜜”的负担:
公司用户规模越来越大,故已经对底层数据库进行拆分,将原来的单库水平拆分成多个数据库。
数据库水平拆分之后,原来在单个数据库上便能完成的操作,现在需要跨多个数据库,目前未采用任何分布式事务方案来保证跨库操作的数据一致性,故经常出现业务数据不一致的情况。
他谈到,最近调研了一些分布式事务方面的资料,正在考虑 TCC 方案,想咨询一下设计和实现 TCC 服务有哪些注意事项?TCC 方案能否解决其数据一致性的需求?
《海量数据访问和数据一致性挑战》话题小组长张森:
在讨论之前,先简单介绍一下 TCC
TCC 是一种比较成熟的分布式事务解决方案,可用于解决跨库操作的数据一致性问题。
TCC 是服务化的两阶段编程模型,其 Try、Confirm、Cancel 3 个方法均由业务编码实现。
Try 操作作为一阶段,负责资源的检查和预留,Confirm 操作作为二阶段提交操作,执行真正的业务,Cancel 是预留资源的取消。
如下图所示,业务实现 TCC 服务之后,该 TCC 服务将作为分布式事务的其中一个资源,参与到整个分布式事务中;事务管理器分 2 阶段协调 TCC 服务,在第一阶段调用所有 TCC 服务的 Try 方法,在第二阶段执行所有 TCC 服务的 Confirm 或者 Cancel 方法。
再来说说实现 TCC 服务时候,要重点注意的事项:
1、业务操作分两阶段完成:
如下图所示,接入 TCC 前,业务操作只需要一步就能完成,但是在接入 TCC 之后,需要考虑如何将其分成 2 阶段完成,把资源的检查和预留放在一阶段的 Try 操作中进行,把真正的业务操作的执行放在二阶段的 Confirm 操作中进行。
TCC 服务要保证第一阶段 Try 操作成功之后,二阶段 Confirm 操作一定能成功。
2、允许空回滚:
如下图所示,事务协调器在调用 TCC 服务的一阶段 Try 操作时,可能会出现因为丢包而导致的网络超时,此时事务协调器会触发二阶段回滚,调用 TCC 服务的 Cancel 操作。
TCC 服务在未收到 Try 请求的情况下收到 Cancel 请求,这种场景被称为空回滚,TCC 服务在实现时应当允许空回滚的执行。
3、防悬挂控制;
如下图所示,事务协调器在调用 TCC 服务的一阶段 Try 操作时,可能会出现因网络拥堵而导致的超时,此时事务协调器会触发二阶段回滚,调用 TCC 服务的 Cancel 操作;在此之后,拥堵在网络上的一阶段 Try 数据包被 TCC 服务收到,出现了二阶段 Cancel 请求比一阶段 Try 请求先执行的情况。
用户在实现 TCC 服务时,应当允许空回滚,但是要拒绝执行空回滚之后到来的一阶段 Try 请求。
4、幂等控制:
无论是网络数据包重传,还是异常事务的补偿执行,都会导致 TCC 服务的 Try、Confirm 或者 Cancel 操作被重复执行;用户在实现 TCC 服务时,需要考虑幂等控制,即 Try、Confirm、Cancel 执行一次和执行多次的业务结果是一样的。
5、业务数据可见性控制:
TCC 服务的一阶段 Try 操作会做资源的预留,在二阶段操作执行之前,如果其他事务需要读取被预留的资源数据,那么处于中间状态的业务数据该如何向用户展示,需要业务在实现时考虑清楚;通常的设计原则是“宁可不展示、少展示,也不多展示、错展示”。
6、业务数据并发访问控制:
TCC 服务的一阶段 Try 操作预留资源之后,在二阶段操作执行之前,预留的资源都不会被释放。如果此时其他分布式事务修改这些业务资源,会出现分布式事务的并发问题。
用户在实现 TCC 服务时,需要考虑业务数据的并发控制,尽量将逻辑锁粒度降到最低,以最大限度的提高分布式事务的并发性。
再谈谈蚂蚁金服在 TCC 方面应用
蚂蚁金服使用 TCC 有 10 年历史,在 TCC 应用方面积累了大量实践经验。除了上述 TCC 服务的设计注意事项外,在设计 TCC 服务时还要遵循大量设计规范,这无疑对用户提了非常高的要求。
为了简化用户接入分布式事务的门槛,蚂蚁金服的分布式事务框架(SOFA-DTX)推出了 FMT(Framework-managed transactions)模式和 XA 模式,这两种模式均不需要用户实现 TCC 服务,用户只需要关注自身业务 SQL 便可。SOFA -DTX 的三种模式:TCC、FMT 和 XA 相互之间是功能互补,相辅相成的,形成了蚂蚁金服完善的分布式事务解决方案。
SOFA-DTX 全面覆盖金融场景,金融级容灾保障、提供丰富的接入模式并且使用简洁易于接入,目前已经应用在支付宝、网上银行、蚂蚁财富、芝麻信用、南京银行等项目中。
SOFA-DTX 现已开放公测,可点击申请:
https://www.cloud.alipay.com/products/DTX
2. 讨论关键词:异地容灾,财务系统
某知名音乐软件的总架构师提了一个他们面临的问题:
账务的主备库分别部署在两个机房,为了保证主库高性能,主备之间采取异步复制。当机房故障时(比如断电、光缆被挖断、网络持续抖动等),或者主库 crash 起不来,备库的数据不敢直接拉起来提供服务,因为不清楚是否有数据丢失,这时候整个账务系统也不能提供服务。
蚂蚁的容灾是如何做的,可以让系统快速恢复又不丢数据?
《海量数据访问和数据一致性挑战》讨论组司空曙:
蚂蚁也经历过 IBM+ORACLE+EMC 的时代,早期也未能完全解决跨机房容灾的问题。后来通过在应用层实现数据的 Failover 方案,才逐渐将 IBM 以及 EMC 逐渐下线掉,换成相对低成本的 PC 服务器+本地 PCIE 卡/SSD 盘的方案,再往后进一步升级为 OceanBase 数据库来保证多机房的数据一致性。
本质上,这个问题的痛点在于,需要保证数据一致性,同时要让业务迅速恢复。
细想下,这种情况下,主备不一致的数据量是很少的,我们为了保护很少的这部分数据,而牺牲了整个 DB 的服务、应用的服务,实在是比较可惜。基于这样的情况,是不是有一种方案,只要保证用户访问不了未同步完成的数据,那整个 DB 、应用其实是可以快速拉起来提供服务的。
基于上面的思考,落地成一个方案大体就如下:
正常情况:
修改账务操作,在事务内同步发送一致性消息(事务同步器内触发二阶段的消息发送),将账务信息发送到消息中心
异机房的黑名单系统订阅并消费这些消息,缓存到本机房的 cache,cache 的超时时间要保证大于主备的延时;这里的 cache 也可以换成其他任意一种存储。正常情况,消息不出现积压,cache 跟主库数据应该是一致的
异常情况( DB 主库故障):
从消息中心查询积压的账务用户,把这些归类为黑名单用户,因为他们没有被正常消费掉,意味着业务主库事务并没有结束,或者 DB 提交了,但是还没来得及发送二阶段消息,系统就 crash 了。不管哪种情况,黑名单用户量一定是大于等于 DB 未同步的用户数据,这就保证了通过黑名单屏蔽是安全的。消息中心的位置也很关键,如果要实现跨机房容灾,需要将消息投递到异机房,或者消息中心自己保障数据强同步。
未被黑名单拦截的用户,从 cache 获取用户最新数据,可能也会查询备库进一步组装用户信息,因为缓存是过期时间的。
根据查询的数据,进一步在空库里面进行落地并继续记账处理。空库指的是 DB 的 user/schema/table/sequence 等结构信息都是在的,只是数据为空。
上述方案,再结合异常时将业务快速从正常状态切换到容灾状态,就可以实现业务的快速恢复,同时保障数据的一致性;如果如果结合金融云的微服务产品 MS 实现动态配置推送,就可以将这个时间控制到秒级。
等 DB 恢复了,系统从容灾状态再切回正常状态,期间的数据处理也是很复杂的。
这套基于黑名单的容灾方案在蚂蚁一直运行了好几年,效果还不错,缺点就是比较复杂,这是账务类业务本身的特点决定的。
后来蚂蚁自研了基于数据访问代理的容灾方案,将上述 Failover + 黑名单的方案下沉到数据访问层产品 DBP ,让容灾方案更为通用、便捷,应用几乎不用再感知上述方案的细节。DBP 能够支持多种常用的数据库,包括蚂蚁自研的 OceanBase。
再往后,自研数据库 OceanBase 诞生。OceanBase 是基于 Paxos 协议的分布式强一致数据库,对于单节点故障,它提供 RPO=0,RTO<30 秒的容灾能力,致力于从数据库层屏蔽容灾细节,为应用层提供简单的使用方式。
本文转载自技术琐话公众号。
原文链接:https://mp.weixin.qq.com/s/DJC2xTlVQjCFb8oiqaFkrg
评论