当前位置:首页 > 科技  > 软件

DDD实战:应对并发挑战,五个技巧让你轻松应对

来源: 责编: 时间:2023-10-23 17:05:32 194观看
导读在业务开发中,事务一致性核心在于“原子性”,则并发管理的核心在于“隔离性”。原子性:一个业务操作被视为一个不可分割的逻辑单元,要么全部执行成功,要么全部失败回滚;隔离性:并发业务操作之间要相互隔离,不能互相干扰;1. 无

在业务开发中,事务一致性核心在于“原子性”,则并发管理的核心在于“隔离性”。5fN28资讯网——每日最新资讯28at.com

  1. 原子性:一个业务操作被视为一个不可分割的逻辑单元,要么全部执行成功,要么全部失败回滚;
  2. 隔离性:并发业务操作之间要相互隔离,不能互相干扰;

1. 无处不在的并发

并发管理是指在多个用户同时访问、修改同一数据时,如何保证数据的准确性、一致性和完整性的一系列管理措施。5fN28资讯网——每日最新资讯28at.com

并发无处不在是指在当前的业务系统和应用程序中,几乎所有的操作都是并发的。无论是网络请求、数据库操作、I/O读写操作等,都可能在同一时刻被多个线程或进程同时执行。这意味着在业务开发中,必须充分考虑并发处理问题,避免出现数据竞争、死锁等问题,同时合理利用多线程、协程等技术来提高系统的性能和处理能力。5fN28资讯网——每日最新资讯28at.com

1.1. 常见业务流程

首先看以下流程:5fN28资讯网——每日最新资讯28at.com

图片图片5fN28资讯网——每日最新资讯28at.com

这是一个聚合根更新操作,包括:5fN28资讯网——每日最新资讯28at.com

  1. 从 DB 中加载数据;
  2. 修改内存中的数据;
  3. 将变更更新到 DB;

也许还没有使用DDD,对聚合根不太熟悉,那再看一个流程:5fN28资讯网——每日最新资讯28at.com

图片图片5fN28资讯网——每日最新资讯28at.com

这是一个更为通用的数据编辑流程,包括:5fN28资讯网——每日最新资讯28at.com

  1. 打开编辑页面,从 DB 中加载数据,完成数据展示;
  2. 通过 UI 界面对数据进行编辑;
  3. 点击保存按钮,将新的变更保存到 DB;

仔细对比这两张图,其实他们都在做同样的事情:5fN28资讯网——每日最新资讯28at.com

  1. 加载数据;
  2. 修改数据;
  3. 更新数据;

在这里便存在并发问题。5fN28资讯网——每日最新资讯28at.com

1.2. 并发问题

上面所提到的流程是否存在并发问题,仔细看下图:5fN28资讯网——每日最新资讯28at.com

图片图片5fN28资讯网——每日最新资讯28at.com

同一个流程,操作同一数据,只是操作顺序不同,也会出现并发安全问题:5fN28资讯网——每日最新资讯28at.com

  1. Action2 首先加载数据 V1;
  2. Action1 其次也加载数据 V1;
  3. Action2 对数据进行修改,并成功保存变更后的数据 V2(V1 + Action2 = V2);
  4. Action1 对数据进行修改,并成功保存变更后的数据 V3 (V1 + Action1 = V3);

看起来没什么问题,但 V3 是业务期望的吗?V2 的变更又去哪里了呢?5fN28资讯网——每日最新资讯28at.com

此时,V2 被 V3 覆盖,V2 的变更丢失了。5fN28资讯网——每日最新资讯28at.com

如果还不清楚,明确业务操作为 count++,如下图所示:5fN28资讯网——每日最新资讯28at.com

图片图片5fN28资讯网——每日最新资讯28at.com

对数据库的 count 进行累加操作5fN28资讯网——每日最新资讯28at.com

  1. Action2 首先加载数据 count: 1;
  2. Action1 其次也加载数据 count: 1;
  3. Action2 对count:1进行累加,获得新值 2,并成功保存 count:2;
  4. Action1 对count:1进行累加,获得新值 2,并成功保存 count:2;

操作完成后,最终结果为2。实际期望结果为3,Action2 的修改被 Action1 覆盖,导致一次累加操作被覆盖。5fN28资讯网——每日最新资讯28at.com

当然,这仅仅是同一流程下的并发问题,多流程间也存在并发问题:5fN28资讯网——每日最新资讯28at.com

图片图片5fN28资讯网——每日最新资讯28at.com

对于同一记录,自增流程和设置流程并发执行,同样发生了写覆盖。5fN28资讯网——每日最新资讯28at.com

2. 局部串行

并发问题,只有在并发执行的情况下才会发生,对于同一数据如果不存在并发就不会出问题。5fN28资讯网——每日最新资讯28at.com

2.1. 线程方案

如下图所示:5fN28资讯网——每日最新资讯28at.com

图片图片5fN28资讯网——每日最新资讯28at.com

订单流程中的核心操作:5fN28资讯网——每日最新资讯28at.com

  1. 扣库存
  2. 下单
  3. 支付成功

由于多个订单间不存在关系,可以并发执行;但同一订单,必须保障业务执行顺序。5fN28资讯网——每日最新资讯28at.com

什么是“局部串行”:5fN28资讯网——每日最新资讯28at.com

  1. 对于同一订单,需要保障顺序性;
  2. 对于不同订单可以并行执行;

其中分发器是核心,它连接订单事件和后台线程:5fN28资讯网——每日最新资讯28at.com

  1. 收到订单事件后,从消息体中获取订单号;
  2. 通过 订单号 % 线程数量,计算出事件运行的线程;
  3. 将事件提交到对应线程的处理队列进行处理;
  4. 这样统一订单只会由同一线程进行处理;

这样,相同订单号的订单事件均由同一个线程处理,从而保证局部串行化。不同订单之间,不存在相互影响,可以在多个线程中并行执行。5fN28资讯网——每日最新资讯28at.com

2.2. MQ 方案

当然,内存操作存在数据安全问题(重启任务会丢失),不少MQ也提供了相关功能,以 RocketMQ 的顺序消息为例,如下图所示:5fN28资讯网——每日最新资讯28at.com

图片图片5fN28资讯网——每日最新资讯28at.com

  1. RocketMQ 将相同 shardingKey 的消息发送至固定的 partition;
  2. 后台处理线程从 partition 中获取消息并执行处理逻辑;
  3. 从而保证相同 shardingKey 的消息均由同一线程处理;

局部串行对性能存在一定影响,系统最大的并发量为 partition 数量。如果出现增加 Worker 节点无法提升系统吞吐时,需要扩展 partition 数量。5fN28资讯网——每日最新资讯28at.com

【备注】在系统做 rebalance 时,可能会出现短暂的消息混乱,通常情况下,业务是可接受的。如果必须保障强顺序,如 binlog 场景,只能使用一个 partition,但会极大的影响性能。5fN28资讯网——每日最新资讯28at.com

3. 最后写胜出

有些时候,写更新不依赖于之前的数据状态,只需使用最新数据进行覆盖即可,此时,并发管理也就变的非常简单。5fN28资讯网——每日最新资讯28at.com

如下图所示:5fN28资讯网——每日最新资讯28at.com

图片图片5fN28资讯网——每日最新资讯28at.com

  1. Action1 将 name 更新为 “精英英语”;
  2. Action2 将 status 更新为 Enable;
  3. 两者对不同字段进行更新,并且相互间没有交集;

此时,不会出现并发问题。但由于时序问题,数据的最终状态以“最后更新”为准。5fN28资讯网——每日最新资讯28at.com

4. 原子指令

许多存储引擎对单条记录提供了原子操作,对于简单的场景,可以将并发控制委托给存储引擎进行管理。5fN28资讯网——每日最新资讯28at.com

比如在库存扣减的场景,可以使用 Redis 或 DB 的原子指令进行操作。5fN28资讯网——每日最新资讯28at.com

4.1. Redis

使用 Redis 的 incr 指令:5fN28资讯网——每日最新资讯28at.com

图片图片5fN28资讯网——每日最新资讯28at.com

由于 redis 指令是单线程处理不存在并发问题,直接使用 incr key -1 质量对数量进行扣减。当然,这样可能会出现数量为负值情况,此时可以引入 LUA 脚本进行保障:5fN28资讯网——每日最新资讯28at.com

-- KEYS[1]: 库存键的名称,例如 stock:1001-- ARGV[1]: 要扣减的数量local stock = tonumber(redis.call('GET', KEYS[1]))-- 判断扣减的数量是否大于库存数量if stock < tonumber(ARGV[1]) then    return -1end-- 扣减库存,并返回剩余的库存数量stock = stock - tonumber(ARGV[1])redis.call('SET', KEYS[1], stock)-- 返回剩余的库存数量return stock

4.2. MySQL

同样的操作也可以在 MySQL 中操作,如下图所示:5fN28资讯网——每日最新资讯28at.com

图片图片5fN28资讯网——每日最新资讯28at.com

也可避免扣减为 负值的情况,如下图所示:5fN28资讯网——每日最新资讯28at.com

图片图片5fN28资讯网——每日最新资讯28at.com

新增对 count 的条件判断,通过操作结果控制不同的流程:5fN28资讯网——每日最新资讯28at.com

  1. 影响行数为1,代表操作成功;
  2. 影响函数为0,代表操作失败;

5. 乐观锁

当一个事务(线程)修改一个数据时,先记录下该数据的版本号,其他事务(线程)修改该数据时必须先检查版本号,只有版本号相同的事务(线程)才能修改数据。乐观锁通常使用CAS(Compare and Swap)操作实现,对并发性能影响较小,但是需要开发人员在代码中增加版本号检查的代码。5fN28资讯网——每日最新资讯28at.com

业务中使用最多的场景仍旧是 读-改-写,此时最佳处理方案便是乐观锁。5fN28资讯网——每日最新资讯28at.com

图片图片5fN28资讯网——每日最新资讯28at.com

相对于数据更新,乐观锁方案只是增加了 version 判断,并未引入其他复杂性,对性能影响非常小。5fN28资讯网——每日最新资讯28at.com

  1. 在加载数据时获取当前的数据版本 vsn1;
  2. 操作完成后,将数据更新到DB时,指定更新的数据版本为 vsn1,并将最新的 vsn 更新为 vsn1+1;
  3. 根据操作结果进行判断:
  1. 更新成功,数据库数据未发生变化,不存在并发问题;
  2. 更新失败,数据库数据已经发生变化,此时可以告知用户对数据进行重新加载,并进行修改;

对于聚合根来说,这是数据更新最常见的并发保障机制。5fN28资讯网——每日最新资讯28at.com

6. 悲观锁

当一个事务(线程)正在使用某个数据时,其他事务(线程)就不能访问该数据,必须等待锁释放后才能访问。悲观锁能够保证数据的一致性,但是对并发性能影响比较大。5fN28资讯网——每日最新资讯28at.com

悲观锁是最后的办法,由于其对性能冲击较大,不到万不得已不要随便使用。5fN28资讯网——每日最新资讯28at.com

6.1. 数据库悲观锁

MySQL 提供 for update 指令,可以在查询数据时获取写锁,从而保证数据不会被破坏。5fN28资讯网——每日最新资讯28at.com

使用 for update 加载数据,操作如下:5fN28资讯网——每日最新资讯28at.com

图片图片5fN28资讯网——每日最新资讯28at.com

for update 语句将对数据进行强制加锁,只有在事务提交后,锁才会释放。如图所示,for update 会对操作进行强制排序,最终使单条操作变成串行化,从而影响并发度最终影响系统性能。5fN28资讯网——每日最新资讯28at.com

6.2. 分布式锁

通常情况下分布式锁是一种特殊的悲观锁,在一些数据添加场景非常重要。5fN28资讯网——每日最新资讯28at.com

比如,在订单系统中,对于特价商品一个用户只能购买一次,如下图所示:5fN28资讯网——每日最新资讯28at.com

图片图片5fN28资讯网——每日最新资讯28at.com

该流程存在并发问题,可能导致一个用户下单多次:5fN28资讯网——每日最新资讯28at.com

  1. 两个线程都成功加载用户的历史订单;
  2. 进行重复性校验,发现都没有购买该商品,从而进入生单流程;
  3. 两个线程完成订单对象构建,将数据保存到数据库;
  4. 最终,同一用户生成了两个订单,与业务预期不符;

由于是新增场景,没有什么资源可锁定,所以乐观锁方案无法落地,此时就需要引入分布式锁,如下图所示:5fN28资讯网——每日最新资讯28at.com

图片图片5fN28资讯网——每日最新资讯28at.com

以 user 为单位申请分布式锁,保证同一用户只有一个线程能进行被保护流程,从而保证同一用户不会购买多次。5fN28资讯网——每日最新资讯28at.com

4. 小结

并发管理是一个高级话题,也是设计中的难点,一不小心就会出问题。让每个开发人员都成为并发高手又是一件不太现实的事,但,好在存在很多并发管理的成熟方案,业务开发者按照场景进行落地即可:5fN28资讯网——每日最新资讯28at.com

  1. 局部串行:适用于同一数据的修改需要串行处理;不同数据间可并行处理的场景;
  2. 最后写胜出:适用于不依赖于前值状态的更新操作,对数据进行全量覆盖的场景;
  3. 原子指令:适用于通过原子指令能完成业务场景,并且存储引擎也提供了对应支持;
  4. 乐观锁:适用于聚合根的更新场景,对性能影响极小,可以作为框架默认配置;
  5. 悲观锁:适用于最为严格的场景,需要强制串行,对性能影响极大,需谨慎选择;


5fN28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-14597-0.htmlDDD实战:应对并发挑战,五个技巧让你轻松应对

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 当年很流行,现在已经淘汰的前端技术,请不要再继续学了!

下一篇: 一文掌握在PyCharm中正确设置Python项目

标签:
  • 热门焦点
  • 7月安卓手机好评榜:三星S23Ultra好评率第一

    7月安卓手机好评榜:三星S23Ultra好评率第一

    性能榜和性价比榜之后,我们来看最后的安卓手机好评榜,数据来源安兔兔评测,收集时间2023年7月1日至7月31日,仅限国内市场。第一名:三星Galaxy S23 Ultra好评率:95.71%在即将迎来新
  • 六大权益!华为8月服务日开启:手机免费贴膜、维修免人工费

    六大权益!华为8月服务日开启:手机免费贴膜、维修免人工费

    8月5日消息,一年一度的华为开发者大会2023(Together)日前在松山湖拉开帷幕,与此同时,华为8月服务日也式开启,到店可享六大专属权益。华为用户可在华为商城Ap
  • K8S | Service服务发现

    K8S | Service服务发现

    一、背景在微服务架构中,这里以开发环境「Dev」为基础来描述,在K8S集群中通常会开放:路由网关、注册中心、配置中心等相关服务,可以被集群外部访问;图片对于测试「Tes」环境或者
  • 如何使用JavaScript创建一只图像放大镜?

    如何使用JavaScript创建一只图像放大镜?

    译者 | 布加迪审校 | 重楼如果您曾经浏览过购物网站,可能遇到过图像放大功能。它可以让您放大图像的特定区域,以便浏览。结合这个小小的重要功能可以大大改善您网站的用户体验
  • 阿里大调整

    阿里大调整

    来源:产品刘有媒体报道称,近期淘宝天猫集团启动了近年来最大的人力制度改革,涉及员工绩效、层级体系等多个核心事项,目前已形成一个初步的&ldquo;征求意见版&rdquo;:1、取消P序列
  • 冯提莫签约抖音公会 前“斗鱼一姐”消失在直播间

    冯提莫签约抖音公会 前“斗鱼一姐”消失在直播间

    来源:直播观察提起&ldquo;冯提莫&rdquo;这个名字,很多网友或许听过,但应该不记得她是哪位主播了。其实,作为曾经的&ldquo;斗鱼一姐&rdquo;,冯提莫在游戏直播的年代影响力不输于现
  • iQOO 11S屏幕细节公布:首发三星2K E6全感屏 安卓最好的直屏手机

    iQOO 11S屏幕细节公布:首发三星2K E6全感屏 安卓最好的直屏手机

    日前iQOO手机官方宣布,新一代电竞旗舰iQOO 11S将会在7月4日19:00正式与大家见面。随着发布时间的日益临近,官方关于该机的预热也更加密集,截至目前已
  • OPPO K11搭载长寿版100W超级闪充:26分钟充满100%

    OPPO K11搭载长寿版100W超级闪充:26分钟充满100%

    据此前官方宣布,OPPO将于7月25日也就是今天下午14:30举办新品发布会,届时全新的OPPO K11将正式与大家见面,将主打旗舰影像,和同档位竞品相比,其最大的卖
  • 滴滴违法违规被罚80.26亿 共存在16项违法事实

    滴滴违法违规被罚80.26亿 共存在16项违法事实

    滴滴违法违规被罚80.26亿 存在16项违法事实开始于2121年7月,历经一年时间,网络安全审查办公室对“滴滴出行”网络安全审查终于有了一个暂时的结束。据“网信
Top