场景描述

对于预算扣减/库存扣减类场景,我们需要根据业务对已有预算/库存做减法,拿发券的场景来举例:

需要满足不同的发券需求,运营可配置预算扣减业务

每次请求扣减一定数量的金额,比如发10元券给用户

需要保持强一致,计划中的预算金额尽可能全部发出去,但不能多发,多发会有资金损失,所以需要有强一致的保证

本文介绍的方案还可以作为秒杀类业务中的一部分

概述

对于预算的扣减需求,可以用2条简单的sql来理解:

第一条SQL,记录流水,流水有幂等的作用,还可用于做对账,SQL简化如下:

insert into budget_log (biz_no, budget_code) values (#{bizNo}, #{budget_code})

其中biz_no表示一次扣减的唯一标识,budget_code是一个预算计划的唯一标识

第二条SQL用于做真正的扣减:

update budget set amount = amount - #{amt} where budget_code = #{budgetCode} and amount >= #{amt}

但是如果对并发的要求是百级别,仅仅依靠这两条sql或许可以满足需求,但是想要达到数十万以上的并发支撑,这样是远远不够的。

我曾经使用的库(全库能支持6k的tps)能支持到300次扣减,数据库资源发挥不出来。为什么会出现这种情况呢?6k的tps只能发挥出600tps的能力(300次流水插入+300次预算扣减),因为数据库在执行扣减sql时,会加上行锁,所有的扣减都会在此排队

有何方案

很多人会使用缓存解决问题,使用缓存后,并发往往能达到要求,但是缓存的另一个问题在于无法保持强一致,且缓存有宕机的风险,宕机后相关数据丢失,对于有强一致需求的场景,使用缓存并不合适,需要考虑基于数据库的方案,

前面说过,扣减sql有行锁导致并发量无法提高,那么我们可以将数据进行拆分,将一行数据拆分成多行,分布在不同的表上,可更进一步使用分库分表的方式提高并发量。

基于分库分表的方案

分表方案

按照我使用的DB的能力,DB能支持6k的tps,一次预算扣减需要一次写流水和一次扣减操作,那么可以算出,DB每秒可支持3000次预算扣减业务,而在单行上只能支持300次扣减业务,我们可以分10个表,将单行转变为10行

假如有100万预算,分10个表,每个表10万,扣减方案如下图:

分表扣减

使用单个流水表,多个数据表的方式,因为流水表不是瓶颈,瓶颈在数据表的行锁上,所以流水表不需要分表

表路由组件可通过biz_no做hash,分配到不同的分表上做扣减

通过分表的方案后,能支撑秒级3000次的扣减业务,但是这样还不够,如果想要支撑数十万,依然远远不够。

分表+分库方案

通过前面的计算,我们知道,分表后,可将单个数据库的性能发挥到极限,想要再进一步提高支持的并发量,可以再加上分库的方式,使用分库分表的方案,单库秒级只能支撑3000次扣减业务,那么如果分100库,则秒级可支撑30万次扣减业务,如下图:

分库分表方案

还是假设有100万预算,当我们使用100库1000表后,单行转变成了1000行,处理能力可扩大1000倍,每个表1000预算

需要注意的是:

在分库分表的方案下,流水表也需要分表,但是每个库一个分表即可,假如是100库,则流水表使用百库百表即可

同一次扣减业务,记流水表必须要和执行扣减发生在同一个分库中,需要通过事务保证一致性

问题与风险分析

通过分库分表的方式,我们确实可以达到非常高的并发量的支持,但是如果结合实际情况,我们会发现以下问题:

解决流量不均的问题

如果流量不均,那么每容易出现某些表很快就扣完了,有些表扣的比较慢,这样导致系统整体容量降低

我们可以通过按需分配的方式解决这个问题,我们将每个表上的一行数据称为一个分桶,我们增加总桶的概念,初始时,预算都在总桶中,然后依次给每个分桶分配少量的预算,比如100(具体的分配金额可根据实际场景确定),那么初始分配后,每个分桶100,1000个分桶一共10万,总桶中还有90万,当一个分桶扣完后,立即向总桶申请一定的预算,这样可以保证分桶中的预算大体上是按流量分配的,方案如下图:

预算申请

解决库被打挂的风险

当总桶无预算时,预算申请都会失败,而当预算申请失败后,某些库可能会出现无预算可扣的情况,在这种场景下,如果换到有预算的库做预算的扣减,那么就可能会出现库被打挂的风险,举个例子:

假设业务上有10万的tps,100库平均每个库1000,当总桶无预算可申请,其中的99个库慢慢的扣完后,10万的tps会打到剩下的一个有预算的库上,这个库肯定无法承受秒级10万的扣减业务

如何解决这个问题呢?在前面描述的按需申请预算的基础上做一个限制,分库路由规则中,如果业务被分到了无预算可扣减的库上,则返回扣减失败,给调用方返回预算已扣完,因为流量大体上是均衡的,所以这样做的问题并不大

分库分表的作用

本文介绍的方案是基于分库分表的,脱离我们这个方法,最后聊一聊分库分表的作用,根据经验,我认为分库分表可解决以下问题:

数据量大导致单表/单库效率低,通过分库分表可解决数据量大的问题

单库/单表能力不足,支撑不了业务量,使用分库分表的方式提高系统能力(本文介绍的方案属于这一种)

容错,降低数据库故障给业务带来的影响,比如分100库,当其中一个库不可用时(软硬件升级导致的故障等因素),只影响1%

所以,在数据量并不大的情况下,也是有分库分表的场景和必要性的

高并发 统计对账Java_高并发场景下强一致预算/库存扣减方案相关推荐

  1. 分布式锁和mysql事物扣库存_这个是真的厉害,高并发场景下的订单和库存处理方案,讲的很详细了!...

    前言 之前一直有小伙伴私信我问我高并发场景下的订单和库存处理方案,我最近也是因为加班的原因比较忙,就一直没来得及回复.今天好不容易闲了下来想了想不如写篇文章把这些都列出来的,让大家都能学习到,说一千道 ...

  2. 高并发写场景:秒杀系统库存扣减

    前言 本文中的伪代码示例均以 PHP 作为编程语言 在设计秒杀系统的库存扣减逻辑时,可能一开始想到的代码是: /*** 商品库存扣减** @param int $skuId 商品ID* @param ...

  3. 大厂面试题,高并发库存扣减超卖问题解决,多种sql 适合场景

    ⾼并发库存扣减超卖问题,很多⼈加了乐观锁版本号去解决,那下⾯三种有什么区别,分别适合哪些场景使用 1)update product set stock=stock-1 where id =1 and ...

  4. java分布式库存系统_这个是真的厉害,高并发场景下的订单和库存处理方案,讲的很详细了!...

    前言 之前一直有小伙伴私信我问我高并发场景下的订单和库存处理方案,我最近也是因为加班的原因比较忙,就一直没来得及回复.今天好不容易闲了下来想了想不如写篇文章把这些都列出来的,让大家都能学习到,说一千道 ...

  5. 【万级并发】电商库存扣减如何设计?不超卖!

    随着中国消费认知的不断升级,网购走近千家万户,越来越被人们所接受.淘宝.唯品会.考拉.京东.拼多多等逐渐成为我们生活的重要组成部分. 除了常规的购物下单外,这些电商平台还经常搞一些双十一活动,秒杀.大 ...

  6. 【高并发】Redis如何助力高并发秒杀系统?看完这篇我彻底懂了!!

    秒杀业务 在电商领域,存在着典型的秒杀业务场景,那何谓秒杀场景呢.简单的来说就是一件商品的购买人数远远大于这件商品的库存,而且这件商品在很短的时间内就会被抢购一空.比如每年的618.双11大促,小米新 ...

  7. 每秒上千订单场景下的分布式锁高并发优化实践!

    本文授权转自石杉的架构笔记 背景引入 首先,我们一起来看看这个问题的背景? 前段时间有个朋友在外面面试,然后有一天找我聊说:有一个国内不错的电商公司,面试官给他出了一个场景题: 假如下单时,用分布式锁 ...

  8. Java架构-每秒上千订单场景下的分布式锁高并发优化实践!

    "上一篇文章我们聊了聊Redisson这个开源框架对Redis分布式锁的实现原理,如果有不了解的兄弟可以看一下:<拜托,面试请不要再问我Redis分布式锁实现原理>. 今天就给大 ...

  9. 面试官让我设计一个基于分布式锁的库存超卖方案,并发量很高的那种

    今天给大家聊一个有意思的话题:每秒上千订单场景下,如何对分布式锁的并发能力进行优化? 背景引入 首先,我们一起来看看这个问题的背景? 前段时间有个朋友在外面面试,然后有一天找我聊说:有一个国内不错的电 ...

最新文章

  1. Android Studio Emulator 提示 “/dev/kvm is not found” 解决办法
  2. 5分钟学会开发浏览器扩展
  3. 如何实现手游app瘦身?
  4. vue 自定义属性判断点击每个item 显示隐藏
  5. 中小企业的软件需求问题
  6. 鸿蒙王者荣耀想要转区吗,王者荣耀:跨系统角色转移功能终于上线,想要成功转区,这九点常识必须要知道!...
  7. legend2---开发日志4(常用的链接传值方式有哪些)
  8. js 打印组件的使用
  9. 简单的UDP监听需要打开w网路岗才能接收到数据的原因和解决办法
  10. 十款移动APP开发框架
  11. 成长 工作 游戏 英语 阅读
  12. ARM-linux开发板网线连接电脑访问外网
  13. vnc远程控制软件安装,超实用的windows下安装vnc远程控制软件教程
  14. #AI边缘计算单元-想搞开发,买树莓派还是Nano?
  15. UI设计初学者教程:色彩基础知识
  16. POJ 1682 DP
  17. Pyramid Vision Transformer: A Versatile Backbone for Dense Prediction without Convolutions
  18. 【数据结构】【cfs_rq】【task_struct】【sched_domain】
  19. Java知识点的总结(一)
  20. 如何制作好看的菜单c语言,一种漂亮的自绘菜单

热门文章

  1. Linux实操篇 - 查看tomcat日志
  2. P4101 人人尽说江南好
  3. 博德之门2增强版存档_博德|博德之门2:增强版存档修改方法_234游戏网
  4. java 获取前/后一秒时间
  5. iPad应用的十大用户体验设计准则
  6. 如何更改电脑桌面图标大小
  7. 《大话数据结构》5一文学会数据结构中的静态链表存储结构(概念,实例,代码)
  8. const与define相比优点_相关const和define优缺点信息大全_美瞳网
  9. UE4 动画插件Advanced Locomotion System V4分析
  10. 自从见了身价上亿的同学,我再也不羡慕有钱人了