怅然|消息队列之事务消息,RocketMQ 和 Kafka是如何做的?


怅然|消息队列之事务消息,RocketMQ 和 Kafka是如何做的?作者 | 是Yes呀
【怅然|消息队列之事务消息,RocketMQ 和 Kafka是如何做的?】责编 | 郑丽媛
来源 | yes的练级攻略(ID:yes_java)
每个时代 , 都不会亏待会学习的人 。
大家好 , 我是 yes 。
今天我们来谈一谈消息队列的事务消息 , 一说起事务相信大家都不陌生 , 脑海里蹦出来的就是 ACID 。
通常我们理解的事务就是为了一些更新操作要么都成功 , 要么都失败 , 不会有中间状态的产生 , 而 ACID 是一个严格的事务实现的定义 , 不过在单体系统时候一般都不会严格的遵循 ACID 的约束来实现事务 , 更别说分布式系统了 。
分布式系统往往只能妥协到最终一致性 , 保证数据最终的完整性和一致性 , 主要原因就是实力不允许...因为可用性为王 。
而且要保证完全版的事务实现代价很大 , 你想想要维护这么多系统的数据 , 不允许有中间状态数据可以被读取 , 所有的操作必须不可分割 , 这意味着一个事务的执行是阻塞的 , 资源是被长时间锁定的 。
在高并发情况下资源被长时间的占用 , 就是致命的伤害 , 举一个有味道的例子 , 如厕高峰期 , 好了懂得都懂 。
怅然|消息队列之事务消息,RocketMQ 和 Kafka是如何做的?对了 ,ACID是什么还不太清楚的同学 , 赶紧去查一查 , 这里我就不展开说了 。
怅然|消息队列之事务消息,RocketMQ 和 Kafka是如何做的?分布式事务那说到分布式事务 , 常见的有 2PC、TCC 和事务消息 , 这篇文章重点就是事务消息 , 不过 2PC 和 TCC 我稍微提一下 。
怅然|消息队列之事务消息,RocketMQ 和 Kafka是如何做的?2PC2PC就是二阶段提交 , 分别有协调者和参与者两个角色 , 二阶段分别是准备阶段和提交阶段 。
准备阶段就是协调者向各参与者发送准备命令 , 这个阶段参与者除了事务的提交啥都做了 , 而提交阶段就是协调者看看各个参与者准备阶段都 o 不 ok , 如果有ok那么就向各个参与者发送提交命令 , 如果有一个不ok那么就发送回滚命令 。
这里的重点就是 2PC 只适用于数据库层面的事务 , 什么意思呢?就是你想在数据库里面写一条数据同时又要上传一张图片 , 这两个操作 2PC 无法保证两个操作满足事务的约束 。
而且 2PC 是一种强一致性的分布式事务 , 它是同步阻塞的 , 即在接收到提交或回滚命令之前 , 所有参与者都是互相等待 , 特别是执行完准备阶段的时候 , 此时的资源都是锁定的状态 , 假如有一个参与者卡了很久 , 其他参与者都得等它 , 产生长时间资源锁定状态下的阻塞 。
总体而言效率低 , 并且存在单点故障问题 , 协调者是就是那个单点 , 并且在极端条件下存在数据不一致的风险 , 例如某个参与者未收到提交命令 , 此时宕机了 , 恢复之后数据是回滚的 , 而其他参与者其实都已经执行了提交事务的命令了 。
怅然|消息队列之事务消息,RocketMQ 和 Kafka是如何做的?TCCTCC能保证业务层面的事务 , 也就是说它不仅仅是数据库层面 , 上面的上传图片这种操作它也能做 。
TCC 分为三个阶段 try - confirm - cancel , 简单的说就是每个业务都需要有这三个方法 , 先都执行try方法 , 这一阶段不会做真正的业务操作 , 只是先占个坑 , 什么意思呢?比如打算加10个积分 , 那先在预添加字段加上这10积分 , 这个时候用户账上的积分其实是没有增加的 。


推荐阅读