从单机到多机:多机一定比单机快吗?秒杀到底有没有必要用分布式锁?

一、单机场景

单机能承受的 TPS

  • tomcat 500~1000
  • mysql 200~800

在单机状态下,tomcat 能接受的请求肯定比 mysql 更多,此时数据库成为系统瓶颈。为了解决这个问题,可以将自增的累加器(例如请求次数、商品剩余等等)等“公共值”缓存起来,放在 JVM 里面,仅让有效请求到达数据库,让 DB 的 TPS 有最大利用价值。

Tomcat 是多线程的,会产生并发问题。我们考虑不同商品数量的情况:

  • 最小,只有一件商品供秒杀,此时多线程在扣减商品的时候,要排队串行,串行放进队列里,不需要加锁了
  • 最大,很多件商品的时候,由于商品与商品之间是无关的,不同商品可以看做是并行的,同一个商品在同一个队列里,也不用加锁了

思考,如果第一件商品10件,第二件商品9999件,第三件商品500件,都在数据库里,如果没有前置判断的话,夹杂着的请求很快会让1件的商品卖光,后续还有很多对卖光商品的请求,白白占用了数据库的性能。所以我们需要前置的拦截,让最终进来的请求都是还有库存的商品。

目前来看,是不是不用锁了?是的,但是我们大多数人很少在开发的时候去做线程的资源隔离,而是直接把请求打出去,当所有请求是并发达到数据库的时候,我们控制不了请求的顺序性,所以才会有锁的概念。

二、多机场景

场景:单机 1 个 tomcat -> 多机 2 个 tomcat

多机情况下,只有一件商品的时候,也需要加锁,防止超卖。锁是一个参照物,用来参照哪个线程取到了、哪个线程没取到。锁自身要具备排他性,即只能有一个线程取到。那么如何实现排他性?

  • redis worker 线程是串行的

  • zk 两阶段提交,主从,主是串行的

1、在分布式场景下,有了分布式锁,还需要单机锁吗?

首先要理解的是,我们在数据库上目的是做有效请求的过滤,让没有意义的操作不去消耗它的资源和网络带宽。在微服务当中,在任何一个节点上,我们都要关注请求的有效性。虽然微服务是“不主动、不拒绝、不负责”,即使打过去的是无效请求,也会正确返回,但 调用方必须考虑请求的“有效性”,不随便去浪费服务方的资源,这是调用方个人价值的体现。这是面试的时候你要强调的,可以区别于其他人的。

回到这个问题,在分布式场景下,有了分布式锁,还需要单机锁吗?

  • 举一个例子,如果有两台机器一共10个线程去抢锁,在只有1件商品的情况下,最终只有1个线程能拿到锁,而服务方承受的I/O的负载是O(10)。

  • 同样的情况,如果你对每个单机加锁,服务方承受的I/O的负载就只有O(2),在整体的性能上会有提高。另外,如果不想用本地锁,也想达到O(2)的效率的话,你也可以在每个单机上用逻辑做资源隔离,通过队列实现串行。

2、多件商品情况下,商品之间其实是无关的

商品之间无关,所以多件商品和一件商品的情况类似。在用户下单后,n 件商品经过过滤,最终每件商品只有有效请求到达数据库,大大减少了数据库的压力。


比如,限制每个用户只能买 3 种商品,每个商品限购 2 件,系统应该怎么设计?

根据“只能有效请求到达数据库”原则,多余秒杀的商品不应该到达数据库浪费I/O资源,因此应该做前置过滤。解决方法是将 redis 集群前移。在 redis 里面将售卖规则创建成 key,后续用业务逻辑判断此次用户请求是否能够生成订单。

比如,一个用户请求到达之后,去 redis 取商品种类、商品单品数量、用户 id,带着想要秒杀的商品的 itemid 一起返回到 tomcat,由业务逻辑判断这个用户能不能下单,从而识别“有效请求”。你也可以用 redis 事务来处理一个用户的多个减库存,防止超出限购数量。识别了有效请求(防止超卖)后,生成订单即可,因为第三方支付是异步的,后续订单可以走队列了,无需再加锁。队列的迁移到后续的分库分表,是后续调优要考虑的问题。

另外,商品数量足够大的话,不同商品可能放在 redis 不同的节点中,稍显复杂,这个是开发人员要考虑的逻辑。redis 分区后,就不能使用 LUA 脚本和事务实现上述多个判断逻辑了,需要自己写逻辑实现了。

3、服务的无状态性:多机一定比单机快吗?都说秒杀场景一定要用分布式锁,真的是这样吗?

首先要理解一个概念,就是 服务的状态性。累加器、公共值,属于状态数据。为了维护多机的状态,要保持数据的同步,去做事件传递,去做分布式协调。zk 是主从架构,性能并不高,仅应该用来维护核心且不经常发生变化的那些数据的一致性,并不是一个很好的用于数据同步的技术方案。正确的方式是做服务状态的迁出,而不是去多台机器上做数据的同步。

单机情况下,没有到达瓶颈的时候,单笔业务处理速度是最快的。加机器并不能提升速度,反而由于网络开销,让单笔请求变慢。而且单机是不需要外部锁的,而多机要做一致性、同步问题,反而加机器会让整个系统变慢。

那为什么常说多机会变快?这样说的前提是:不只有一件商品。如果只有一件商品,最终都要成为串行去扣这一件商品的库存,多机一定不会带来速度的提升。而在多件商品的情况下,多机可以让无关的商品之间并行,不同商品的减库存进入不同的机器并同时执行,而受制于一台机器的性能问题,虽然可能会排队,但最终的表现是,多机能够“让无关请求并行起来”,因此才会有所谓的“快”。

最后,无论你怎么变,(考虑到多机存在的数据同步问题和单机存在的CPU调度问题),在“没有资源瓶颈”的时候,并行总是会比串行慢。串行才是效率最高的方式。

4、升华:从商家的角度,秒杀的目的是什么?

从商家的角度,不是每个人都能拿到秒杀的便宜。秒杀是为了引流,应该用更低的成本获得更多的用户使用这个平台,完成秒杀。在秒杀的同时,也应该做限购,即一个用户只能拿走一件商品。加了限购的秒杀才是完善的秒杀系统。

秒杀场景下,会有很多人刷单,因此才更应该仅让有效请求到达数据库。根据上面的方案,无效请求都让 redis +业务逻辑 挡住了,保护了mysql。

那如果用户下单之后不付款,交易失败怎么办?你仍然要从商家的角度考虑,实际上,卖少了没关系,但不能超卖。况且,如果秒杀没有结束,你可以把库存加回去。这就是产品经理和程序员要换位思考。

5、秒杀系统还需要分布式锁吗?

不需要了。redis 所有的操作是串行的,每一个操作拥有了原子性和排他性。分布式锁成本是很高的,上述解决方案将 redis 集群前移来做请求有效性识别、减库存这些事情,就不需要做分布式锁了。

所以,对于任何系统设计,不要上来就推导“多机”的架构模式。

6、redis 宕机了怎么办?

程序员代码不能解决所有问题,要在其他地方做补偿,例如你还是要靠运维、靠linux内核调优、靠监控系统、靠服务器硬件的冗余能力,在秒杀这样的特殊场景,你还是需要对服务器细心照顾、特殊对待。不要因为技术而技术,要从企业的角度其实追求可用性。

如果不断的追求某个问题的解决方案,很可能会引入其他的问题。也不要把平时的解决方案放进特殊场景中使用,可能会引起蝴蝶效应,风险很大。美团发布过一篇实战文章,在大量并发情况下关闭健康检查,避免一些节点被剔除。必要的时候,让一些用户的请求失效。虽然可能会让用户体验上稍微慢一些,但保证整个服务的可用性才是最重要的。站在产品经理的角度来看,这个方案可以了。

7、那分布式锁岂不是没用了?什么场景需要分布式锁呢?

分布式锁其实是在解决并发问题。未来很多公司采用响应式编程、流式编程模型(而且已经有公司落地了),无状态、无锁化将是趋势。

如果你学过大数据的话会更好理解,map reduce 计算框架,map 处理数据初始状态进行加工,同一数据做 reduce 的时候会有分区概念,最后分治汇总。

所以,在开发的时候,我们应该尽量去规避分布式锁,去采用无锁化的方式解决问题。

从单机到多机:多机一定比单机快吗?秒杀系统到底有没有必要用分布式锁?相关推荐

  1. pytorch-多GPU训练(单机多卡、多机多卡)

    pytorch-多GPU训练(单机多卡.多机多卡) pytorch 单机多卡训练 首先是数据集的分布处理 需要用到的包: torch.utils.data.distributed.Distribute ...

  2. 运维堡垒机(跳板机)系统 python

    相信各位对堡垒机(跳板机)不陌生,为了保证服务器安全,前面加个堡垒机,所有ssh连接都通过堡垒机来完成,堡垒机也需要有 身份认证,授权,访问控制,审计等功能,笔者用Python基本实现了上述功能. A ...

  3. S700K转辙机多机牵引道岔故障处理【转自微信公众号高速铁路信号技术交流】

    S700K转辙机道岔故障处理原则 一停用.二汇报.三处理.四确认 一.故障处理携带仪表.工具.器材 室内 1.工具:通信工具.应急工具.设备钥匙.便携式工作灯.电烙铁. 2.仪表:万用表.钳形表. 3 ...

  4. WIN10锁屏久了宕机(死机)解决方案

    电脑:dell 灵越整机 一年多以来,教研室电脑在锁屏时间久了之后总会自动宕机:屏幕亮着,但是鼠标键盘不顶用.通常这个时候只能强制按电源键重启,很伤而且感觉很逗比. 第一阶段(重装系统) 之前的系统是 ...

  5. 物联网云平台DTU Modbus协议 上位机 下位机 源码 源代码 程序

    物联网云平台DTU Modbus协议 上位机 下位机 源码 源代码 程序 一.源码的使用基本说明: 1.1 编译语言: 下位机使用C语言:上位机使用C#语言 标准Modbus Slave通信下位机源码 ...

  6. 安卓玩机搞机技巧综合资源-----修改rom 制作rom 解包rom的一些问题解析【二十一】

    接上篇 安卓玩机搞机技巧综合资源------如何提取手机分区 小米机型代码分享等等 [一] 安卓玩机搞机技巧综合资源------开机英文提示解决dm-verity corruption your de ...

  7. 安卓玩机搞机技巧综合资源---MIUI14全机型首版下载链接 刷机方法 获取root步骤【十二】

    接上篇 安卓玩机搞机技巧综合资源------如何提取手机分区 小米机型代码分享等等 [一] 安卓玩机搞机技巧综合资源------开机英文提示解决dm-verity corruption your de ...

  8. SecureCRT自动登录跳板机/堡垒机直连linux

    1.连接堡垒机/跳板机如果是ip地址即跳过此步骤,如果是网址先获取网址ip 2.设置登陆堡垒机/跳板机条件 3.设置登录账号密码及登录后默认选择的机器序号 an IP Address 首次登录不确定机 ...

  9. 跳板机/堡垒机并不安全

    各位读者好,今天我很闲,就来分享一下,为何 堡垒机并不安全: 不知道什么是跳板机和堡垒机的可以去百度先普及下: 堡垒机和跳板机的安全性只体现到了对登陆者登录服务器时的权限和控制上,不管是阿里云还是华为 ...

最新文章

  1. 打印合同_批量打印合同用印申请单
  2. 禁止程序接收鼠标事件的工具_报表工具html事件--鼠标悬停出现提示信息
  3. ant 安装及基础教程 !
  4. LiveVideoStack线上分享第三季(二):对话机器人与儿童电子消费品
  5. (学习日记)关于a1,a2,a3,...,an共n个元素依次入栈其可能出栈的排列数的计算(catalan数)...
  6. WPF 自定义命令 以及 命令的启用与禁用
  7. xml模块、项目开发过程
  8. c++byte数组和文件的相互转换_5分钟系列之Java类文件结构(三、字节码指令简介)...
  9. 实验三:分别用for、while和do-while循环语句以及递归方法计算n!,并输出算式...
  10. 想对可以使用的adblock插件感谢!!
  11. 乘业绩创新高的东风,董明珠续任格力董事长几无悬念
  12. 小白学Oracle基础知识(一)
  13. 【python + FFmpeg】对视频进行分辨率改变,(带音频)
  14. 顺序结构(C语言基本结构)
  15. [题目解析]乐乐的数字
  16. Lambda 表达式详解
  17. 函数参数缺省值/默认值
  18. Oracle 设置 密码可以重复使用 the password cannot be reused
  19. 支付宝被罚18万元;金立副总裁回应60亿广告费;苹果再遭专利诉讼丨价值早报
  20. 记录自己折腾不止的人生,留住时光的一抹轨迹

热门文章

  1. VSCODE + 搜狗输入法,两次文字突然变成繁体?
  2. 【Linux】内核驱动篇九--设备模型
  3. linux设备模型详解
  4. 【微信公众号开发】四、公众号按钮设置及自己的微信按钮编辑器
  5. tree | 分类回归树模型
  6. 代码管理工具—GitLab
  7. mac解决mysql忘记密码的问题(亲测有效)
  8. 电脑显示屏只显示中间部分其他地方不显示问题
  9. C#datagridview中双缓存Dgv
  10. [Excel]rank函数实现自动排序