这三年被分布式坑惨了,曝光十大坑

热力学仿真软件:Fluent_(8).材料属性设置 在 Fluent 中,材料属性主要包括密度、比热容、导热系数、黏度等物理性质。这些属性在不同的仿真场景中有着不同的作用,例如在流体仿真中,密度和黏度是必不可少的;在传热仿真中,导热系数和比热容是主要考虑的因素。如果所需的材料不在材料库中,或者需要对现有材料进行修改,用户可以自定义材料属性。在主菜单中选择Materials。点击打开材料编辑器。在材料编辑器中,点击Create按钮,输入新的材料名称。选择材料类型(如FluidSolid等)。在属性栏中填写所需的材料属性。 阅读详情

本篇主要内容如下:

这三年被分布式坑惨了,曝光十大坑

 

主要内容

前言

我们都在讨论分布式,特别是面试的时候,不管是招初级软件工程师还是高级,都会要求懂分布式,甚至要求用过。传得沸沸扬扬的分布式到底是什么东东,有什么优势?

借用火影忍术

这三年被分布式坑惨了,曝光十大坑

 

风遁·螺旋手里剑

看过火影的同学肯定知道漩涡鸣人的招牌忍术:多重影分身之术。

  • 这个术有一个特别厉害的地方,过程和心得:多个分身的感受和经历都是相通的。比如 A 分身去找卡卡西(鸣人的老师)请教问题,那么其他分身也会知道 A 分身问的什么问题。
  • 漩涡鸣人有另外一个超级厉害的忍术,需要由几个影分身完成:风遁·螺旋手里剑。这个忍术是靠三个鸣人一起协作完成的。

这两个忍术和分布式有什么关系?

  • 分布在不同地方的系统或服务,是彼此相互关联的。
  • 分布式系统是分工合作的。

案例:

  • 比如 Redis 的哨兵机制,可以知道集群环境下哪台 Redis 节点挂了。
  • Kafka的 Leader 选举机制,如果某个节点挂了,会从 follower 中重新选举一个 leader 出来。(leader 作为写数据的入口,follower 作为读的入口)

那多重影分身之术有什么缺点?

  • 会消耗大量的查克拉。分布式系统同样具有这个问题,需要几倍的资源来支持。

对分布式的通俗理解

  • 是一种工作方式
  • 若干独立计算机的集合,这些计算机对于用户来说就像单个相关系统
  • 将不同的业务分布在不同的地方

优势可以从两方面考虑:一个是宏观,一个是微观。

  • 宏观层面:多个功能模块糅合在一起的系统进行服务拆分,来解耦服务间的调用。
  • 微观层面:将模块提供的服务分布到不同的机器或容器里,来扩大服务力度。

任何事物有阴必有阳,那分布式又会带来哪些问题呢?

  • 需要更多优质人才懂分布式,人力成本增加
  • 架构设计变得异常复杂,学习成本高
  • 运维部署和维护成本显著增加
  • 多服务间链路变长,开发排查问题难度加大
  • 环境高可靠性问题
  • 数据幂等性问题
  • 数据的顺序问题
  • 等等

讲到分布式不得不知道 CAP 定理和 Base 理论,这里给不知道的同学做一个扫盲。

CAP 定理

在理论计算机科学中,CAP 定理指出对于一个分布式计算系统来说,不可能通是满足以下三点:

  • 一致性(Consistency)
    • 所有节点访问同一份最新的数据副本。
  • 可用性(Availability)
    • 每次请求都能获取到非错的响应,但不保证获取的数据为最新数据
  • 分区容错性(Partition tolerance)
    • 不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在 C 和 A 之间做出选择)

BASE 理论

BASE 是 Basically Available(基本可用)、Soft state(软状态)和 Eventually consistent(最终一致性)三个短语的缩写。BASE 理论是对 CAP 中 AP 的一个扩展,通过牺牲强一致性来获得可用性,当出现故障允许部分不可用但要保证核心功能可用,允许数据在一段时间内是不一致的,但最终达到一致状态。满足 BASE 理论的事务,我们称之为柔性事务。

  • 基本可用 : 分布式系统在出现故障时,允许损失部分可用功能,保证核心功能可用。如电商网址交易付款出现问题来,商品依然可以正常浏览。
  • 软状态: 由于不要求强一致性,所以BASE允许系统中存在中间状态(也叫软状态),这个状态不影响系统可用性,如订单中的“支付中”、“数据同步中”等状态,待数据最终一致后状态改为“成功”状态。
  • 最终一致性: 最终一致是指的经过一段时间后,所有节点数据都将会达到一致。如订单的“支付中”状态,最终会变为“支付成功”或者“支付失败”,使订单状态与实际交易结果达成一致,但需要一定时间的延迟、等待。

一、分布式消息队列的坑

消息队列如何做分布式?

将消息队列里面的消息分摊到多个节点(指某台机器或容器)上,所有节点的消息队列之和就包含了所有消息。

1. 消息队列的坑之非幂等

幂等性概念

所谓幂等性就是无论多少次操作和第一次的操作结果一样。如果消息被多次消费,很有可能造成数据的不一致。而如果消息不可避免地被消费多次,如果我们开发人员能通过技术手段保证数据的前后一致性,那也是可以接受的,这让我想起了 Java 并发编程中的 ABA 问题,如果出现了 [ABA问题),若能保证所有数据的前后一致性也能接受。

场景分析

RabbitMQ、RocketMQ、Kafka 消息队列中间件都有可能出现消息重复消费问题。这种问题并不是 MQ 自己保证的,而是需要开发人员来保证。

这几款消息队列中间都是是全球最牛的分布式消息队列,那肯定考虑到了消息的幂等性。我们以 Kafka 为例,看看 Kafka 是怎么保证消息队列的幂等性。

Kafka 有一个 偏移量 的概念,代表着消息的序号,每条消息写到消息队列都会有一个偏移量,消费者消费了数据之后,每过一段固定的时间,就会把消费过的消息的偏移量提交一下,表示已经消费过了,下次消费就从偏移量后面开始消费。

坑:当消费完消息后,还没来得及提交偏移量,系统就被关机了,那么未提交偏移量的消息则会再次被消费。

如下图所示,队列中的数据 A、B、C,对应的偏移量分别为 100、101、102,都被消费者消费了,但是只有数据 A 的偏移量 100 提交成功,另外 2 个偏移量因系统重启而导致未及时提交。

这三年被分布式坑惨了,曝光十大坑

 

系统重启,偏移量未提交

重启后,消费者又是拿偏移量 100 以后的数据,从偏移量 101 开始拿消息。所以数据 B 和数据 C 被重复消息。

如下图所示:

这三年被分布式坑惨了,曝光十大坑

 

重启后,重复消费消息

避坑指南

  • 微信支付结果通知场景
    • 微信官方文档上提到微信支付通知结果可能会推送多次,需要开发者自行保证幂等性。第一次我们可以直接修改订单状态(如支付中 -> 支付成功),第二次就根据订单状态来判断,如果不是支付中,则不进行订单处理逻辑。
  • 插入数据库场景
    • 每次插入数据时,先检查下数据库中是否有这条数据的主键 id,如果有,则进行更新操作。
  • 写 Redis 场景
    • Redis 的 Set 操作天然幂等性,所以不用考虑 Redis 写数据的问题。
  • 其他场景方案
    • 生产者发送每条数据时,增加一个全局唯一 id,类似订单 id。每次消费时,先去 Redis 查下是否有这个 id,如果没有,则进行正常处理消息,且将 id 存到 Redis。如果查到有这个 id,说明之前消费过,则不要进行重复处理这条消息。
    • 不同业务场景,可能会有不同的幂等性方案,大家选择合适的即可,上面的几种方案只是提供常见的解决思路。

2. 消息队列的坑之消息丢失

坑:消息丢失会带来什么问题?如果是订单下单、支付结果通知、扣费相关的消息丢失,则可能造成财务损失,如果量很大,就会给甲方带来巨大损失。

那消息队列是否能保证消息不丢失呢?答案:否。主要有三种场景会导致消息丢失。

这三年被分布式坑惨了,曝光十大坑

 

消息队列之消息丢失

(1)生产者存放消息的过程中丢失消息

这三年被分布式坑惨了,曝光十大坑

 

生产者丢失消息

解决方案

  • 事务机制(不推荐,异步方式)

对于 RabbitMQ 来说,生产者发送数据之前开启 RabbitMQ 的事务机制channel.txselect ,如果消息没有进队列,则生产者受到异常报错,并进行回滚 channel.txRollback,然后重试发送消息;如果收到了消息,则可以提交事务 channel.txCommit。但这是一个同步的操作,会影响性能。

  • confirm 机制(推荐,异步方式)

我们可以采用另外一种模式:confirm 模式来解决同步机制的性能问题。每次生产者发送的消息都会分配一个唯一的 id,如果写入到了 RabbitMQ 队列中,则 RabbitMQ 会回传一个 ack消息,说明这个消息接收成功。如果 RabbitMQ 没能处理这个消息,则回调 nack 接口。说明需要重试发送消息。

也可以自定义超时时间 + 消息 id 来实现超时等待后重试机制。但可能出现的问题是调用 ack 接口时失败了,所以会出现消息被发送两次的问题,这个时候就需要保证消费者消费消息的幂等性。

事务模式 和 confirm 模式的区别:

  • 事务机制是同步的,提交事务后悔被阻塞直到提交事务完成后。
  • confirm 模式异步接收通知,但可能接收不到通知。需要考虑接收不到通知的场景。

(2)消息队列丢失消息

这三年被分布式坑惨了,曝光十大坑

 

消息队列丢失消息

消息队列的消息可以放到内存中,或将内存中的消息转到硬盘(比如数据库)中,一般都是内存和硬盘中都存有消息。如果只是放在内存中,那么当机器重启了,消息就全部丢失了。如果是硬盘中,则可能存在一种极端情况,就是将内存中的数据转换到硬盘的期间中,消息队列出问题了,未能将消息持久化到硬盘。

解决方案

  • 创建 Queue 的时候将其设置为持久化。
  • 发送消息的时候将消息的 deliveryMode 设置为 2 。
  • 开启生产者 confirm 模式,可以重试发送消息。

(3)消费者丢失消息

这三年被分布式坑惨了,曝光十大坑

 

消费者丢失消息

消费者刚拿到数据,还没开始处理消息,结果进程因为异常退出了,消费者没有机会再次拿到消息。

解决方案

  • 关闭 RabbitMQ 的自动 ack,每次生产者将消息写入消息队列后,就自动回传一个 ack给生产者。
  • 消费者处理完消息再主动 ack,告诉消息队列我处理完了。

问题: 那这种主动 ack 有什么漏洞了?如果 主动 ack 的时候挂了,怎么办?

则可能会被再次消费,这个时候就需要幂等处理了。

问题: 如果这条消息一直被重复消费怎么办?

则需要有加上重试次数的监测,如果超过一定次数则将消息丢失,记录到异常表或发送异常通知给值班人员。

(4)RabbitMQ 消息丢失总结

这三年被分布式坑惨了,曝光十大坑

 

RabbitMQ 丢失消息的处理方案

(5)Kafka 消息丢失

场景:Kafka 的某个 broker(节点)宕机了,重新选举 leader (写入的节点)。如果 leader 挂了,follower 还有些数据未同步完,则 follower 成为 leader 后,消息队列会丢失一部分数据。

解决方案

  • 给 topic 设置 replication.factor 参数,值必须大于 1,要求每个 partition 必须有至少 2 个副本。
  • 给 kafka 服务端设置 min.insyc.replicas 必须大于 1,表示一个 leader 至少一个 follower 还跟自己保持联系。

3. 消息队列的坑之消息乱序

坑: 用户先下单成功,然后取消订单,如果顺序颠倒,则最后数据库里面会有一条下单成功的订单。

RabbitMQ 场景:

  • 生产者向消息队列按照顺序发送了 2 条消息,消息1:增加数据 A,消息2:删除数据 A。
  • 期望结果:数据 A 被删除。
  • 但是如果有两个消费者,消费顺序是:消息2、消息 1。则最后结果是增加了数据 A。

这三年被分布式坑惨了,曝光十大坑

 

RabbitMQ消息乱序场景

这三年被分布式坑惨了,曝光十大坑

 

RabbitMQ 消息乱序场景

RabbitMQ 解决方案:

  • 将 Queue 进行拆分,创建多个内存 Queue,消息 1 和 消息 2 进入同一个 Queue。
  • 创建多个消费者,每一个消费者对应一个 Queue。

这三年被分布式坑惨了,曝光十大坑

 

RabbitMQ 解决方案

Kafka 场景:

  • 创建了 topic,有 3 个 partition。
  • 创建一条订单记录,订单 id 作为 key,订单相关的消息都丢到同一个 partition 中,同一个生产者创建的消息,顺序是正确的。
  • 为了快速消费消息,会创建多个消费者去处理消息,而为了提高效率,每个消费者可能会创建多个线程来并行的去拿消息及处理消息,处理消息的顺序可能就乱序了。

这三年被分布式坑惨了,曝光十大坑

 

Kafka 消息丢失场景

Kafka 解决方案:

  • 解决方案和 RabbitMQ 类似,利用多个 内存 Queue,每个线程消费 1个 Queue。
  • 具有相同 key 的消息 进同一个 Queue。

这三年被分布式坑惨了,曝光十大坑

 

Kafka 消息乱序解决方案

4. 消息队列的坑之消息积压

消息积压:消息队列里面有很多消息来不及消费。

场景 1: 消费端出了问题,比如消费者都挂了,没有消费者来消费了,导致消息在队列里面不断积压。

场景 2: 消费端出了问题,比如消费者消费的速度太慢了,导致消息不断积压。

坑:比如线上正在做订单活动,下单全部走消息队列,如果消息不断积压,订单都没有下单成功,那么将会损失很多交易。

这三年被分布式坑惨了,曝光十大坑

 

消息队列之消息积压

解决方案:解铃还须系铃人

  • 修复代码层面消费者的问题,确保后续消费速度恢复或尽可能加快消费的速度。
  • 停掉现有的消费者。
  • 临时建立好原先 5 倍的 Queue 数量。
  • 临时建立好原先 5 倍数量的 消费者。
  • 将堆积的消息全部转入临时的 Queue,消费者来消费这些 Queue。

这三年被分布式坑惨了,曝光十大坑

 

消息积压解决方案

5. 消息队列的坑之消息过期失效

坑:RabbitMQ 可以设置过期时间,如果消息超过一定的时间还没有被消费,则会被 RabbitMQ 给清理掉。消息就丢失了。

这三年被分布式坑惨了,曝光十大坑

 

消息过期失效

解决方案:

  • 准备好批量重导的程序
  • 手动将消息限时批量重导

这三年被分布式坑惨了,曝光十大坑

 

消息过期失效解决方案

6. 消息队列的坑之队列写满

坑:当消息队列因消息积压导致的队列快写满,所以不能接收更多的消息了。生产者生产的消息将会被丢弃。

解决方案:

  • 判断哪些是无用的消息,RabbitMQ 可以进行 Purge Message 操作。
  • 如果是有用的消息,则需要将消息快速消费,将消息里面的内容转存到数据库。
  • 准备好程序将转存在数据库中的消息再次重导到消息队列。
  • 闲时重导消息到消息队列。

二、分布式缓存的坑

在高频访问数据库的场景中,我们会在业务层和数据层之间加入一套缓存机制,来分担数据库的访问压力,毕竟访问磁盘 I/O 的速度是很慢的。比如利用缓存来查数据,可能5ms就能搞定,而去查数据库可能需要 50 ms,差了一个数量级。而在高并发的情况下,数据库还有可能对数据进行加锁,导致访问数据库的速度更慢。

分布式缓存我们用的最多的就是 Redis了,它可以提供分布式缓存服务。

1. Redis 数据丢失的坑

哨兵机制

Redis 可以实现利用哨兵机制实现集群的高可用。那什么是哨兵机制呢?

  • 英文名:sentinel,中文名:哨兵。
  • 集群监控:负责主副进程的正常工作。
  • 消息通知:负责将故障信息报警给运维人员。
  • 故障转移:负责将主节点转移到备用节点上。
  • 配置中心:通知客户端更新主节点地址。
  • 分布式:有多个哨兵分布在每个主备节点上,互相协同工作。
  • 分布式选举:需要大部分哨兵都同意,才能进行主备切换。
  • 高可用:即使部分哨兵节点宕机了,哨兵集群还是能正常工作。

坑: 当主节点发生故障时,需要进行主备切换,可能会导致数据丢失。

异步复制数据导致的数据丢失

主节点异步同步数据给备用节点的过程中,主节点宕机了,导致有部分数据未同步到备用节点。而这个从节点又被选举为主节点,这个时候就有部分数据丢失了。

脑裂导致的数据丢失

主节点所在机器脱离了集群网络,实际上自身还是运行着的。但哨兵选举出了备用节点作为主节点,这个时候就有两个主节点都在运行,相当于两个大脑在指挥这个集群干活,但到底听谁的呢?这个就是脑裂。

那怎么脑裂怎么会导致数据丢失呢?如果发生脑裂后,客户端还没来得及切换到新的主节点,连的还是第一个主节点,那么有些数据还是写入到了第一个主节点里面,新的主节点没有这些数据。那等到第一个主节点恢复后,会被作为备用节点连到集群环境,而且自身数据会被清空,重新从新的主节点复制数据。而新的主节点因没有客户端之前写入的数据,所以导致数据丢失了一部分。

避坑指南

  • 配置 min-slaves-to-write 1,表示至少有一个备用节点。
  • 配置 min-slaves-max-lag 10,表示数据复制和同步的延迟不能超过 10 秒。最多丢失 10 秒的数据

注意:缓存雪崩、缓存穿透、缓存击穿并不是分布式所独有的,单机的时候也会出现。所以不在分布式的坑之列。

三、分库分表的坑

1.分库分表的坑之扩容

分库、分表、垂直拆分和水平拆分

  • 分库: 因一个数据库支持的最高并发访问数是有限的,可以将一个数据库的数据拆分到多个库中,来增加最高并发访问数。
  • 分表: 因一张表的数据量太大,用索引来查询数据都搞不定了,所以可以将一张表的数据拆分到多张表,查询时,只用查拆分后的某一张表,SQL 语句的查询性能得到提升。
  • 分库分表优势:分库分表后,承受的并发增加了多倍;磁盘使用率大大降低;单表数据量减少,SQL 执行效率明显提升。
  • 水平拆分: 把一个表的数据拆分到多个数据库,每个数据库中的表结构不变。用多个库抗更高的并发。比如订单表每个月有500万条数据累计,每个月都可以进行水平拆分,将上个月的数据放到另外一个数据库。
  • 垂直拆分: 把一个有很多字段的表,拆分成多张表到同一个库或多个库上面。高频访问字段放到一张表,低频访问的字段放到另外一张表。利用数据库缓存来缓存高频访问的新数据。比如将一张很多字段的订单表拆分成几张表分别存不同的字段(可以有冗余字段)。
  • 分库、分表的方式:
    • 根据租户来分库、分表。
    • 利用时间范围来分库、分表。
    • 利用 ID 取模来分库、分表。

坑:分库分表是一个运维层面需要做的事情,有时会采取凌晨宕机开始升级。可能熬夜到天亮,结果升级失败,则需要回滚,其实对技术团队都是一种煎熬。

怎么做成自动的来节省分库分表的时间?

  • 双写迁移方案:迁移时,新数据的增删改操作在新库和老库都做一遍。
  • 使用分库分表工具 Sharding-jdbc 来完成分库分表的累活。
  • 使用程序来对比两个库的数据是否一致,直到数据一致。

坑: 分库分表看似光鲜亮丽,但分库分表会引入什么新的问题呢?

垂直拆分带来的问题

  • 依然存在单表数据量过大的问题。
  • 部分表无法关联查询,只能通过接口聚合方式解决,提升了开发的复杂度。
  • 分布式事处理复杂。

水平拆分带来的问题

  • 跨库的关联查询性能差。
  • 数据多次扩容和维护量大。
  • 跨分片的事务一致性难以保证。

2.分库分表的坑之唯一 ID

为什么分库分表需要唯一 ID

  • 如果要做分库分表,则必须得考虑表主键 ID 是全局唯一的,比如有一张订单表,被分到 A 库克 B 库。如果 两张订单表都是从 1 开始递增,那查询订单数据时就错乱了,很多订单 ID 都是重复的,而这些订单其实不是同一个订单。
  • 分库的一个期望结果就是将访问数据的次数分摊到其他库,有些场景是需要均匀分摊的,那么数据插入到多个数据库的时候就需要交替生成唯一的 ID 来保证请求均匀分摊到所有数据库。

坑: 唯一 ID 的生成方式有 n 种,各有各的用途,别用错了。

生成唯一 ID 的原则

  • 全局唯一性
  • 趋势递增
  • 单调递增
  • 信息安全

生成唯一 ID 的几种方式

  • 数据库自增 ID。每个数据库每增加一条记录,自己的 ID 自增 1。
    • 多个库的 ID 可能重复,这个方案可以直接否掉了,不适合分库分表后的 ID 生成。
    • 信息不安全
    • 缺点
  • 适用 UUID 唯一 ID。
    • UUID 太长、占用空间大。
    • 不具有有序性,作为主键时,在写入数据时,不能产生有顺序的 append 操作,只能进行 insert 操作,导致读取整个 B+ 树节点到内存,插入记录后将整个节点写回磁盘,当记录占用空间很大的时候,性能很差。
    • 缺点
  • 获取系统当前时间作为唯一 ID。
    • 高并发时,1 ms内可能有多个相同的 ID。
    • 信息不安全
    • 缺点
  • Twitter 的 snowflake(雪花算法):Twitter 开源的分布式 id 生成算法,64 位的 long 型的 id,分为 4 部分snowflake 算法
  • 基本原理和优缺点:
    • 1 bit:不用,统一为 0
    • 41 bits:毫秒时间戳,可以表示 69 年的时间。
    • 10 bits:5 bits 代表机房 id,5 个 bits 代表机器 id。最多代表 32 个机房,每个机房最多代表 32 台机器。
    • 12 bits:同一毫秒内的 id,最多 4096 个不同 id,自增模式。
    • 优点:
      • 毫秒数在高位,自增序列在低位,整个ID都是趋势递增的。
      • 不依赖数据库等第三方系统,以服务的方式部署,稳定性更高,生成ID的性能也是非常高的。
      • 可以根据自身业务特性分配bit位,非常灵活。
    • 缺点:
      • 强依赖机器时钟,如果机器上时钟回拨(可以搜索 2017 年闰秒 7:59:60),会导致发号重复或者服务会处于不可用状态。
  • 百度的 UIDGenerator 算法。UIDGenerator 算法
    • 基于 Snowflake 的优化算法。
    • 借用未来时间和双 Buffer 来解决时间回拨与生成性能等问题,同时结合 MySQL 进行 ID 分配。
    • 优点:解决了时间回拨和生成性能问题。
    • 缺点:依赖 MySQL 数据库。
  • 美团的 Leaf-Snowflake 算法。
  • 图片来源于美团
    • 获取 id 是通过代理服务访问数据库获取一批 id(号段)。
    • 双缓冲:当前一批的 id 使用 10%时,再访问数据库获取新的一批 id 缓存起来,等上新的 id 用完后直接用。
    • 优点:
      • Leaf服务可以很方便的线性扩展,性能完全能够支撑大多数业务场景。
      • ID号码是趋势递增的8byte的64位数字,满足上述数据库存储的主键要求。
      • 容灾性高:Leaf服务内部有号段缓存,即使DB宕机,短时间内Leaf仍能正常对外提供服务。
      • 可以自定义max_id的大小,非常方便业务从原有的ID方式上迁移过来。
      • 即使DB宕机,Leaf仍能持续发号一段时间。
      • 偶尔的网络抖动不会影响下个号段的更新。
    • 缺点:
      • ID号码不够随机,能够泄露发号数量的信息,不太安全。

怎么选择:一般自己的内部系统,雪花算法足够,如果还要更加安全可靠,可以选择百度或美团的生成唯一 ID 的方案。

四、分布式事务的坑

怎么理解事务?

  • 事务可以简单理解为要么这件事情全部做完,要么这件事情一点都没做,跟没发生一样。
  • 在分布式的世界中,存在着各个服务之间相互调用,链路可能很长,如果有任何一方执行出错,则需要回滚涉及到的其他服务的相关操作。比如订单服务下单成功,然后调用营销中心发券接口发了一张代金券,但是微信支付扣款失败,则需要退回发的那张券,且需要将订单状态改为异常订单。

坑:如何保证分布式中的事务正确执行,是个大难题。

分布式事务的几种主要方式

  • XA 方案(两阶段提交方案)
  • TCC 方案(try、confirm、cancel)
  • SAGA 方案
  • 可靠消息最终一致性方案
  • 最大努力通知方案

XA 方案原理

这三年被分布式坑惨了,曝光十大坑

 

XA 方案

  • 事务管理器负责协调多个数据库的事务,先问问各个数据库准备好了吗?如果准备好了,则在数据库执行操作,如果任一数据库没有准备,则回滚事务。
  • 适合单体应用,不适合微服务架构。因为每个服务只能访问自己的数据库,不允许交叉访问其他微服务的数据库。

TCC 方案

  • Try 阶段:对各个服务的资源做检测以及对资源进行锁定或者预留。
  • Confirm 阶段:各个服务中执行实际的操作。
  • Cancel 阶段:如果任何一个服务的业务方法执行出错,需要将之前操作成功的步骤进行回滚。

应用场景:

  • 跟支付、交易打交道,必须保证资金正确的场景。
  • 对于一致性要求高。

缺点:

  • 但因为要写很多补偿逻辑的代码,且不易维护,所以其他场景建议不要这么做。

Sega 方案

基本原理:

  • 业务流程中的每个步骤若有一个失败了,则补偿前面操作成功的步骤。

适用场景:

  • 业务流程长、业务流程多。
  • 参与者包含其他公司或遗留系统服务。

优势:

  • 第一个阶段提交本地事务、无锁、高性能。
  • 参与者可异步执行、高吞吐。
  • 补偿服务易于实现。

缺点:

  • 不保证事务的隔离性。

可靠消息一致性方案

这三年被分布式坑惨了,曝光十大坑

 

可靠消息一致性方案

基本原理:

  • 利用消息中间件 RocketMQ 来实现消息事务。
  • 第一步:A 系统发送一个消息到 MQ,MQ将消息状态标记为 prepared(预备状态,半消息),该消息无法被订阅。
  • 第二步:MQ 响应 A 系统,告诉 A 系统已经接收到消息了。
  • 第三步:A 系统执行本地事务。
  • 第四步:若 A 系统执行本地事务成功,将 prepared 消息改为 commit(提交事务消息),B 系统就可以订阅到消息了。
  • 第五步:MQ 也会定时轮询所有 prepared的消息,回调 A 系统,让 A 系统告诉 MQ 本地事务处理得怎么样了,是继续等待还是回滚。
  • 第六步:A 系统检查本地事务的执行结果。
  • 第七步:若 A 系统执行本地事务失败,则 MQ 收到 Rollback 信号,丢弃消息。若执行本地事务成功,则 MQ 收到 Commit 信号。
  • B 系统收到消息后,开始执行本地事务,如果执行失败,则自动不断重试直到成功。或 B 系统采取回滚的方式,同时要通过其他方式通知 A 系统也进行回滚。
  • B 系统需要保证幂等性。

最大努力通知方案

基本原理:

  • 系统 A 本地事务执行完之后,发送消息到 MQ。
  • MQ 将消息持久化。
  • 系统 B 如果执行本地事务失败,则最大努力服务会定时尝试重新调用系统 B,尽自己最大的努力让系统 B 重试,重试多次后,还是不行就只能放弃了。转到开发人员去排查以及后续人工补偿。

几种方案如何选择

  • 跟支付、交易打交道,优先 TCC。
  • 大型系统,但要求不那么严格,考虑 消息事务或 SAGA 方案。
  • 单体应用,建议 XA 两阶段提交就可以了。
  • 最大努力通知方案建议都加上,毕竟不可能一出问题就交给开发排查,先重试几次看能不能成功。

写在最后

分布式还有很多坑,这篇只是一个小小的总结,从这些坑中,我们也知道分布式有它的优势也有它的劣势,那到底该不该用分布式,完全取决于业务、时间、成本以及开发团队的综合实力。后续我会继续分享分布式中的一些底层原理,当然也少不了分享一些避坑指南。

参考资料:

基于Python的新闻聚合与推荐系统:抓取多新闻网站内容并根据用户兴趣进行个性化推荐 本文介绍了如何使用Python构建一个新闻聚合与推荐系统,涵盖了从新闻数据抓取、用户兴趣建模到推荐算法实现的全过程。通过爬虫技术抓取新闻网站内容,使用TF-IDF、Word2Vec等算法进行内容分析,并通过推荐算法向用户推送个性化的新闻,最终帮助用户快速获取自己感兴趣的信息。你可以根据具体需求,进一步扩展和优化系统。例如,加入更多的推荐算法、优化爬虫的抓取效率、增强前端展示的互动性等。通过本文的指导,您应该能够构建一个完整的新闻聚合与推荐系统,并为用户提供个性化的新闻推荐服务。 阅读详情

相关推荐

【Python脚本】Python自动大麦网抢票,准点原价秒杀演唱会门票,拒绝黄牛交易!从我做起!!!1

你是否错过了周杰伦的票,最近又没抢到五月天的票,不要太难过,今晚有张学友的票,后天还有张杰的票,加油哦!

weixin_45841831的博客 6万+

为什么不建议使用分布式事务

这样,系统的可用性就相当于参加分布式事务的各实例的可用性之积,实例越多,可用性下降越明显。响应时间增加:从性能和可伸缩性角度看,分布式事务的总持续时间通常是各实例操作时间之和,因为一个事务中的各个操作通常是顺序执行的。复杂性:分布式事务要求事务的参与方提供事务的存储方式,并且需要在理解原理的基础上进行配置,比如配置当前参与者事务的存储位置等。并发冲突:由于事务持续时间延长,事务对相关资源的锁定时间也相应增加,从而可能严重增加并发冲突,影响到系统吞吐率和可伸缩性。

怀揣梦想,一颗执着于技术的心从未磨灭,内心住着一颗顽强的小强时刻提醒自己层层突破自我,同时也成就他人 720

金蝶ERP元数据解析:字段属性与表结构映射实战

本文深入解析金蝶ERP元数据的核心价值与应用实践,详细介绍了字段属性与表结构映射的关键技术。通过缓存获取与工具类直连两种方案对比,结合实际案例展示元数据在数据库校验、动态表单生成等场景的应用,帮助开发者高效解决二次开发中的常见问题。

weixin_33738555的博客 435

分布式系统的常见问题

不好意思最近实在是有点太忙了,将近一个月没更新博客,其实前几天我是有发表一篇关于HSF框架的源码解析,后来由于一些原因不得不删除。其实HSF也跟Dubbo类似,解决了分布式系统中的一系列问题。分布式带来的优势就是能够将复杂业务拆分成多个服务的组合,就如同controller-service-dao中的service接口部署在不同的机器上,service不就是服务的抽象么。让不同的团队维护不同的ser

超威半导体 5854

保姆级教程:在阿里云ECS上用Docker一键部署EMQX MQTT服务器(Ubuntu 20.04)

本文提供在阿里云ECS上使用Docker一键部署EMQX MQTT服务器的详细教程,涵盖从实例创建、Docker环境配置到EMQX部署与优化的全流程。适合物联网开发者快速搭建高效、安全的MQTT消息服务器,适用于智能家居、工业物联网等场景。

weixin_28739079的博客 309

基于STM32的蓝牙智能药盒设计

本研究设计了一种基于STM32F103C8T6单片机的蓝牙智能药盒系统,针对老年人用药管理需求,集成了定时提醒、药量检测、环境监测等功能。系统通过LCD1602显示屏实时显示时间与用药信息,支持每日3次定时提醒及3种药物用量设置,采用DHT11温湿度传感器、HX711药量检测模块和红外传感器实现环境监控,并通过蓝牙模块实现远程用药提醒。测试结果表明,系统定时误差≤30秒,温湿度监测精度±2℃,药量检测误差<1g,各项功能运行稳定。该设计为解决老年人用药依从性问题提供了智能化解决方案,具有实用价值和应用前景。

3254968421的博客 544

分布式事务解决方案优缺点对比

背景 分布式事务是企业集成中的一个技术难点,也是每一个分布式系统架构中都会涉及到的一个东西,特别是在微服务架构中,几乎可以说是无法避免。 ACID 指数据库事务正确执行的四个基本要素: 原子性(Atomicity) 一致性(Consistency) 隔离性(Isolation) 持久性(Durability) CAP CAP原则又称CAP定理,指的是在一个分布式系统中,一致性(Consistency)、可用性(Availability)、分区容忍性(Partition tolerance)。

HelloWorld搬运工 777

6万字嵌入式最全八股文面试题大全及参考答案(持续更新)

进程上下文定义:进程上下文包含了进程执行时所需的所有信息,包括 CPU 寄存器的值、内核栈、任务控制块(TCB)等。作用:当进程被切换时,需要保存当前进程的上下文,并恢复下一个将要运行进程的上下文。中断上下文定义:中断上下文是指处理中断时 CPU 所处的状态,包括中断发生时的寄存器值等。作用:当中断发生时,CPU 会自动保存当前的上下文信息,并跳转到相应的中断处理程序。示例表格上下文描述进程上下文包含进程执行时的所有相关信息中断上下文处理中断时 CPU 所处的状态线程同步定义。

大模型大数据攻城狮的专栏 7936

<转>为什么不建议你用分布式事务?

转自:为什么不建议你用分布式事务? (baidu.com) 「来源: |51CTO技术栈 ID:blog51cto」 关注51CTO技术栈,悦享技术,成就 CTO 梦想 “ 伴随着业务的快速的发展、越来越高的业务复杂度,几乎每个公司的系统都会从单体走向分布式,特别是转向微服务架构。 图片来自 Pexels 随之而来就必然遇到分布式事务这个难题。而我的这篇文章总结了分布式事务的解决方案,希望给大家带来帮助。 分布式事务基础 ①到底什么是事务呢? 什么是事务?举个生活中的例子:你去小卖铺.

sunshingheavy的专栏 1505

UG\NX二次开发 替换部件引用集UF_ASSEM_replace_refset

替换部件引用集UF_ASSEM_replace_refset,需要替换成“完整部件(Entire Part)”需要第三个参数传入空指针或者空字符串。

王牌飞行员_里海的博客 255

第十四节《OpenCascade集成Qt》

将 OpenCascade 与 Qt 集成是开发图形界面应用的常见需求。通过将 OpenCascade 的几何建模与 Qt 的图形用户界面(GUI)功能结合,可以创建强大而灵活的 CAD 或建模工具。OpenCascade 提供了与 Qt 的集成接口,允许你在 Qt 应用程序中嵌入 OpenCascade 的视图,执行几何操作,并与用户进行交互。以下是 OpenCascade 与 Qt 集成的详细步骤:首先,确保已安装 OpenCascade 和 Qt。你可以从 OpenCascade 官方网站或通过包管理

yumeiguo的博客 597

为什么说分布式事务不再适用于微服务架构

http://www.toutiao.im 传统应用使用本地事务和分布式事务保证数据一致性,但是在微服务架构中数据都是服务私有的,需要通过服务提供的API来访问,所以分布式事务不再适用微服务架构。那么微服务架构又该如何保证数据一致性呢?本文就来谈谈这个话题。 传统分布式事务不是微服务中数据一致性的最佳选择 微服务架构中应满足数据最终一致性原则 微服务架构实现

武汉红喜 3万+

快速入门必看!RT-DETR手把手训练自己的数据集去跑实验,基于 ultralytics 仓库源码改进,配置虚拟环境,准备数据集、训练、验证、推理测试 ,实现0到1的完整教学过程。

本文介绍了使用Ultralytics框架训练RT-DETR模型的全流程。首先需要创建Python 3.10虚拟环境,安装指定版本的PyTorch和相关依赖包。然后准备数据集,修改配置文件,并详细介绍训练、验证和推理三个核心步骤的代码实现。训练阶段使用RTDETR类加载模型配置,设置训练参数;验证阶段评估模型性能;推理阶段可对图片、视频等进行预测。文中还提供了清华大学镜像源加速下载,以及详细的参数配置说明,帮助用户快速搭建RT-DETR目标检测模型。

Ai缝合怪、助力小伙伴高效发论文 5566

不是知道,就能写文章

我工作十几年来,接触过太多程序员了,其中不乏技术出色的程序员。不过我发现这些出色的程序员里,很多人很难把技术讲明白。肚子里有货说不出来。自从我写了公众号后,我发现我也有这个问题:自己明明懂...

艾小仙的专栏 419

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

诸葛亮 VS 庞统,拿下 Paxos 共识算法

前言 分布式确实是一个有趣的话题,只要你留心观察,分布式在生活中无处不在。 悟空哥最开始学习分布式是从一篇非常用心写的技术征文开始的,而且这篇文章获得了征文第一名,在此感谢掘金社区提供的平台。想学习的同学可以点这个文章链接:《这三年被分布式坑惨了,曝光十大坑》 前两讲主要是讲解分布式理论,涉及到了分布式的四大理论。 拜占庭将军问题:《用三国杀讲分布式算法,舒适了吧?》 BASE、CAP、ACID:《用太极拳讲分布式理论,舒服!》 从这篇开始,将会讲解分布式的八大协议/算法。本篇主要讲解 Paxos 共识算法

悟空聊架构的专栏 725

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

诸葛 VS 庞统,拿下 Paxos 共识算法

前言 分布式确实是一个有趣的话题,只要你留心观察,分布式在生活中无处不在。 悟空哥最开始学习分布式是从一篇非常用心写的技术征文开始的,而且这篇文章获得了征文第一名,在此感谢掘金社区提供的平台。想学习的同学可以点这个文章链接:《这三年被分布式坑惨了,曝光十大坑》 前两讲主要是讲解分布式理论,涉及到了分布式的四大理论。 拜占庭将军问题:《用三国杀讲分布式算法,舒适了吧?》 BASE、CAP、ACID...

悟空聊架构的专栏 176

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

如果把 4 个消息队列都拉到一个群里,他们会聊些什么?

本篇的灵感来自我超级喜欢的一篇文章:《如果把中国 442 位皇帝都放在一个群里面,他们会聊些什么》。 其实我的第一篇文章就是用这种方式写的《悟空聊无事务》,这也是我的公众号名字的来源,叫做:「悟空聊架构」 。 本篇也会以 「群聊、单聊、朋友圈」 的方式来讲解计算机世界中消息队列的一些奇闻趣事。 从事软件开发的同学,一定都听过或用过消息队列,比如 RabbitMQ,Kafka。消息队列简单来说就是生产者将很多消息放到一个队列结构中,由其他消费者来消费。想了解更多队列的知识,看下我之前写的 18 个 Queue

悟空聊架构的专栏 6031

单篇文章被转100次,她到底牛在哪?

前言众所周知,技术型公众号遍地开花。但如果一篇文章能被转载100次,是什么概念?假设,转载一次产生1000阅读,那100次的转载就代表着10万的阅读量。这证明了什么?文章好-->作者...

田维常 478

BAT大佬齐了

前言最近有些读者私信给我说,我之前写得文章挺实用的,看了之后有很多收获,希望我多写几篇分布式相关的文章。说实话我有很多东西想写,但是最近太忙了,没法给小伙伴们快速交稿。所以先推荐一些好朋友...

dabaoshiwode的博客 252
上一篇: 惊艳!阿里出产的MyCat性能笔记,带你领略什么叫细节爆炸
下一篇: 简直不可思议,竟然还有人不会查看GC垃圾回收日志?
爱玛士
博客等级 码龄7年 720粉丝 253原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值