跳至主要內容
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?

4563博客

全新的繁體中文 WordPress 網站
  • 首頁
  • 关于分布式系统中的并发问题
未分類
27 4 月 2020

关于分布式系统中的并发问题

关于分布式系统中的并发问题

資深大佬 : Renco 73

问下各位,在分布式系统中,我的模块中的接口属于被调用的,用户的操作不会直接涉及我的模块,一般由其他模块调用我。这种时候我要如何考虑我模块中的并发问题。

我现在负责的会员模板有一个余额消费的功能,由订单模块,调用我会员消费,我只需要将订单模块传给我的消费金额和相关会员账号进行 扣款处理即可,项目经理让我排查一下其中出现的并发场景。但是我不太清楚分布式系统中的,并发问题是怎么产生的。

大佬有話說 (40)

  • 資深大佬 : xmh51

    别人同一个订单重复调用怎么办?

  • 資深大佬 : fxxkgw

    对于余额这种感觉说的像是幂等性 至于并发,他是不是只想说流量大的情况下,理论上并发这问题上游有负载,对业务来说压力大扩容就完事了。

  • 資深大佬 : matepi

    要你的消费模块做一致性加锁,防止多个调用者并发调你消费的时候超余额消费呗
    加锁,tcc 之类的呗

  • 資深大佬 : SpencerCJH

    分布式事务一致性、幂等性、分布式锁 了解一下 😀

  • 資深大佬 : wellsc

    流量激增,怎么平滑无痛扩容

  • 資深大佬 : xetv

    同一个订单请求用测试工具并发请求 n 次看余额会不会变成负数

  • 資深大佬 : bobuick

    单就扣款这个动作看,扣同一个账号下的款,是不是要求就是不能扣成负数?
    那就 cas 乐观锁方式处理,或者 db 直接开 select for update 锁

    你们扯上 tcc 是什么鬼,lz 只是要保障自己的模块安全就可以了.

    要 tcc 之类的,就要联动你的订单模块一起从整体上来看架构了。你们这个没个架构师来把关么,不要随便用 tcc

  • 資深大佬 : phantomzz

    4 正解,5 不知所云。

    每个订单的扣款要考虑幂等,不能重复扣款。
    模块中如果有多个消费者共享的资源,要考虑加锁或者 CAS,比如领券的场景。
    RPC 调用,账户额度和订单状态要考虑一致性。

  • 主 資深大佬 : Renco

    对于分布式系统来说 sychronize 锁是不是没有意义

  • 資深大佬 : phantomzz

    @Renco Redis、Zookeeper 是比较常见的分布式锁实现方案。如果你们有现成的 redis 集群,可以了解一下 Redisson,借助 Redis 完全依照 Java 规范实现包括分布式锁在内的各种分布式工具。

    借助其他实现了分布式一致性协议的组件也可以实现分布式锁。

  • 資深大佬 : justfly

    但是我不太清楚分布式系统中的,并发问题是怎么产生的。

    就你这个场景,两个对同一个用户的扣款请求,可能被路由到你服务的两个完全不相关的进程上,这两个进程内各自处理自己的扣款操作,比如是检查余额和扣款俩操作,二者均检查本次扣款余额充足没问题,结果可能会扣款变成负数。这时候就需要分布式锁来强制两个用户的扣款操作顺序进行。

  • 主 資深大佬 : Renco

    @justfly 明白了,感谢

  • 主 資深大佬 : Renco

    @phantomzz 好的,学习下,多谢

  • 資深大佬 : wangyzj

    tcc

  • 資深大佬 : notwaste

    好多大佬,学习了

  • 資深大佬 : index90

    跟分布式系统没多大关系吧
    即使你是单点的也会有并发问题啊
    例如,我用同一个账号同时下了两个单
    例如,我消费的同时对账号进行充值
    对共享数据(余额)进行并发读写,要注意的是脏读脏写问题

  • 資深大佬 : FrankD

    里瞎扯啥,一堆名词往上怼,人家说的是这个场景的吗

  • 資深大佬 : opengps

    关键词:分布式锁。
    多了不敢说,毕竟我经验不足

  • 資深大佬 : skypyb

    来,给你两篇分布式锁的文章,一个 Redis 的,一个 Zookeeper 的
    http://zhangtielei.com/posts/blog-redlock-reasoning.html
    http://skypyb.com/2019/08/jishu/943/

  • 資深大佬 : CoderGeek

    一般情况:
    1.redis、zk、数据库行锁
    2.是否幂等
    3.条件如 version 版本号、余额是否可为负等

  • 資深大佬 : CoderGeek

    看你描述已经流转到你内部系统了 不要跑偏了

  • 資深大佬 : CoderGeek

    对了哦我说这些是单个用户才需要考虑的哦,多个用户间不互转不存在并发问题

  • 資深大佬 : wccc

    加版本号即可,保持接口的幂等

  • 資深大佬 : wysnylc

    分布式锁性能差,做多队列单消费者
    保证一个用户任务在一个队列中
    上面要加锁的一律不看,并发的终极方案就是队列
    队列分组就 hash 取余,后期可升级一致性哈希环

  • 資深大佬 : btnokami

    所以你的模块只是作为 Proxy 来处理 request 发给 database,还是 databse 那一层呢。
    感觉把并发问题推给 database layer 然后用不同的 isolation level 来处理会比较简单

  • 資深大佬 : btnokami

    分布式计算就两个终极问题,exactly once delivery 和 consensus。。。往上套就好了

  • 資深大佬 : lewis89

    @btnokami #26 非常赞同..

  • 資深大佬 : lewis89

    @wysnylc #24 很显然 主的场景跟主公司的业务量并没有那么大的规模,如果有的话 肯定不会轮到写代码的来排查这个问题了,在架构设计上就要避免了..

  • 資深大佬 : lewis89

    @wysnylc #24 我看它的情况,会员系统应该本身应该就维护了 扣款 跟 会员权限配置 的事务操作,这本身就是一个本地事务,如果别人调你的话,你只要对外保证幂等性即可,一般分布式调用链会有 SpanId 调用 用来维护调用链的(像 SpringCloud-Seluth ),最好对 SpanId 做一个幂等性,有些中间件会在超时的时候做一些重试操作,很有可能单个订单会调用两次扣款操作

  • 資深大佬 : lewis89

    或者可以针对订单 ID 做幂等性校验 把订单 ID 本地落库跟会员扣款放到同一个本地事务 commit 进数据库,做好隔离级别校验跟订单 ID 唯一性校验,如果有重复订单 ID 落库 直接吞掉异常 正常返回即可

  • 資深大佬 : passerbytiny

    前方在极短的时间内连续调用你的接口,这个时候你的接口,可能是多节点同时执行,也可能是单节点多线程同时执行,但访问的数据库只有一个:这就是并发场景。这种场景,单节点应用和分布式应用都会出现。

    这个场景你如果不考虑,那么可能出现的问题是:一,没上事务,余额表的变动历史将乱成一锅粥;二,上了事务,但在扣余额的时候没做二次验证,余额会被口称负的。

    解决方法如下,顺序是从简单到复杂,所有方法都要先有事务(单节点事务):
    一、乐观锁,只适合单节点应用。这个太常见了,而且你也不是单节点应用,就不细说了。
    二、实时动态扣费,适合订单模块(不是你的模块)并发量不是特别高的情况。你在扣费的时候不直接扣,先去查下当前余额,如果扣完不为负,再扣费。你的接口的返回结果不是 void,也不是 true/false,而是一个对象,包含这些字段:是否扣款成功、扣费前的实际余额、扣费后的实际余额。
    三、最终一致性,适合订单模块超高并发量的情况。直接扣费,返回结果总是成功,如果扣成负的了,发事件通知,让其他模块去做补偿(或者啥也不干就允许余额为负,或者再通知订单模块去取消订单)。

    最后说一句,看见分布式事务或者分布式锁的回复,请直接忽略,这是老早就被淘汰的技术。

  • 資深大佬 : passerbytiny

    还有各种回复“幂等”的,你们在想什么。首先,这是接口调用不是事件订阅,没有重发和无序性,无需考虑幂等;其次,扣余额这种动作你做幂等? 10 天前扣 1 元跟今天扣 1 元的结果一摸一样?

  • 資深大佬 : ke1e

    最简单的就是模拟并发情况,看会出现什么问题,然后再去解决

  • 資深大佬 : xuanbg

    主你只需要考虑你的模块有多个服务实例的情况下,每个实例都在同一个时间扣同一个用户的钱的时候,如何保证扣款正确。

  • 資深大佬 : bukeshuo

    数据库乐观锁 或者 直接 分布式锁 锁账号

  • 資深大佬 : Raymon111111

    。。。

    里很多人是不是根本没有做过业务,只看过书,一堆什么分布式锁都出来了

    这是要梳理场景,不是解决方案。何况场景没有,解决方案是怎么意淫出来的

    并发问题主要考虑两点,这个接口短时间相同请求发起两次请求,这个接口被不同请求同时调用

  • 資深大佬 : leafre

    @passerbytiny 好吧 我们最近上线的项目就是使用被淘汰的分布式锁

  • 資深大佬 : peyppicp

    修改为订单模式,每笔余额扣减都有一个固定单号,需要明确一个状态机,保证状态流转正确

    做业务时,开启事务,select for update 锁住对应的单号,用户的余额,然后在本事务中做业务,完事了 commit

    这种同一单号的并发请求过来,一定会被挂起,执行代码中增加判断订单状态的逻辑就好了,如果本单状态为成功则幂等返回成功。

  • 資深大佬 : peyppicp

    这个感觉压根没必要上到分布式系统的层面,也没有必要考虑分布式锁,用 db 抗住就完事了。

    你这是有热点会员吗,同一个会员做大量余额扣减?如果是这样完全可以考虑用子会员的方法实现,也不差的

  • 資深大佬 : wc951

    扣款表里把订单号加唯一索引

文章導覽

上一篇文章
下一篇文章

AD

其他操作

  • 登入
  • 訂閱網站內容的資訊提供
  • 訂閱留言的資訊提供
  • WordPress.org 台灣繁體中文

51la

4563博客

全新的繁體中文 WordPress 網站
返回頂端
本站採用 WordPress 建置 | 佈景主題採用 GretaThemes 所設計的 Memory
4563博客
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?
在這裡新增小工具