事务与消息语义

一、什么是事务

1.1 概念

事务是一个程序执行单元,里面的所有操作要么全部执行成功,要么全部执行失败。也就是我们常说的(ACID)。

  • Atomicity(原子性):事务是一个不可分割的整体,事务内所有操作要么全做成功,要么全失败。
  • Consistency(一致性):事务执行前后,数据从一个状态到另一个状态必须是一致的(A向B转账,不能出现A扣了钱,B却没收到)。
  • Isolation(隔离性):多个并发事务之间相互隔离,不能互相干扰。
  • Durablity(持久性):事务完成后,对数据的更改是永久保存的,不能回滚。

1.2 分布式事务

分布式事务是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。分布式事务通常用于在分布式系统中保证不同节点之间的数据一致性。

分布式事务的解决方案一般有以下几种:XA(2PC/3PC)、TCC

1.2.1 XA(2PC/3PC)

最具有代表性的是由Oracle Tuxedo系统提出的XA分布式事务协议。XA中大致分为两部分:事务管理器和本地资源管理器。其中本地资源管理器往往由数据库实现,比如Oracle、DB2这些商业数据库都实现了XA接口,而事务管理器作为全局的调度者,负责各个本地资源的提交和回滚。XA协议通常包含两阶段提交(2PC)三阶段提交(3PC)两种实现。两阶段提交顾名思义就是要进行两个阶段的提交:第一阶段,准备阶段(投票阶段);第二阶段,提交阶段(执行阶段)。实现过程如下所示:

二阶段提交看似能够提供原子性的操作,但它存在着一些缺陷,三段提交(3PC)是对两段提交(2PC)的一种升级优化,有兴趣的可以深入了解一下,这里不再赘述。

1.2.2 TCC

TCC(Try-Confirm-Cancel)是Try、Commit、Cancel三种指令的缩写,又被称补偿事务,其逻辑模式类似于XA两阶段提交,事务处理流程也很相似,但2PC是应用于在DB层面,TCC则可以理解为在应用层面的2PC,是需要我们编写业务逻辑来实现。

TCC它的核心思想是:“针对每个操作都要注册一个与其对应的确认(Try)和补偿(Cancel)”。

1.3 消息事务

所谓的消息事务就是基于消息队列的两阶段提交,本质上是对消息队列的一种特殊利用,它是将本地事务和发消息放在了一个分布式事务里,保证要么本地操作成功成功并且对外发消息成功,要么两者都失败。

基于消息队列的两阶段提交往往用在高并发场景下,将一个分布式事务拆成一个消息事务(A系统的本地操作+发消息)+B系统的本地操作,其中B系统的操作由消息驱动,只要消息事务成功,那么A操作一定成功,消息也一定发出来了,这时候B会收到消息去执行本地操作,如果本地操作失败,消息会重投,直到B操作成功,这样就变相地实现了A与B的分布式事务。原理如下:

虽然上面的方案能够完成A和B的操作,但是A和B并不是强一致的,而是最终一致(Eventually consistent)的。而这也是满足BASE理论的要求的。这里引申一下,BASE是Basically Available(基本可用)、Soft state(软状态)和Eventually consistent(最终一致性)三个短语的缩写。BASE理论是对CAP中AP(CAP已经被证实一个分布式系统最多只能同时满足CAP三项中的两项)的一个扩展,通过牺牲强一致性来获得可用性,当出现故障允许部分不可用但要保证核心功能可用,允许数据在一段时间内是不一致的,但最终达到一致状态。满足BASE理论的事务,我们称之为“柔性事务”。

二、消息语义

在分布式系统中,任何节点都有可能出现异常甚至宕机。在消息队列中也一样,当Producer在生产消息时,可能会发生Broker宕机不可用,或者网络突然中断等异常情况。根据在发生异常时Producer处理消息的方式,系统可以具备以下三种消息语义:

2.1 At-least-once(至少一次)

Producer通过接收Broker的ACK(消息确认)通知来确保消息成功写入Topic。然而,当Producer接收ACK通知超时,或者收到Broker出错信息时,会尝试重新发送消息。如果Broker正好在成功把消息写入到Topic,但还没有给Producer发送ACK时宕机,Producer重新发送的消息会被再次写入到Topic,最终导致消息被重复分发至Consumer。即:消息不会丢失,但有可能被重复发送

2.2 At-most-once(最多一次)

当Producer在接收ACK超时,或者收到Broker出错信息时不重发消息,那就有可能导致这条消息丢失,没有写入到Topic中,也不会被Consumer消费到。在某些场景下,为了避免发生重复消费,我们可以容许消息丢失的发生。即:消息可能会丢失,但绝不会被重复发送

2.3 Exactly-once(精确一次)

Exactly-once语义保证了即使Producer多次发送同一条消息到服务端,服务端也仅仅会记录一次。Exactly-once语义是最可靠的,同时也是最难理解的。Exactly-once语义需要消息队列服务端,消息生产端和消费端应用三者的协同才能实现。比如,当消费端应用成功消费并且ACK了一条消息之后,又把消费位点回滚到之前的一个消息ID,那么从那个消息ID往后的所有消息都会被消费端应用重新消费到。即:消息不会丢失,也不会被重复发送

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值