如果你第一次接触秒杀,可能还不太理解,库存100件就卖100件,在数据库里减到0就好了,这有什么麻烦的?理论上是这样,但是具体到业务场景中就没那么简单了。今天就聊聊减库存的设计,之后以高可用方案来结束秒杀设计的全部内容。
减库存操作一般有如下几个方式:
1.下单减库存:下单后,在商品的总库存中减去购买数量,下单减库存是最简单的减库存方式,也是控制最精确的一种,下单时直接通过数据库的事务机制控制商品库存,这样一定不会出现超卖的情况。
2.付款减库存:下单后,并不立即减库存,而是等到付款后才真正减库存,否则库存一直保留给其他买家,但因为付款时才减库存,如果并发比较高,有可能出现买家下单后付不了款的情况,可能商品已经被其他人买走了。
3.预扣库存:下单后,库存为其保留一定的时间, 超过这个时间,库存将会自动释放,释放后其他买家就可以继续购买,在买家付款前,系统会校验该库存是否还有保留,如果没有保留,则再次尝试预扣;如果库存不足则不允许继续付款;如果预扣成功,则完成付款并实际地减去库存,这种方式相对复杂一些。
以上这几种减库存的方式都会存在一些问题。 假如我们采用“下单减库存”的方式,正常情况下,买家下单后付款的概率会很高,所以不会有太大问题,但是有一种场景例外,就是当卖家参加某个活动时,此时活动的有效时间是商品的黄金售卖时间,通过恶意下单的方式将该卖家的商品全部下单,那么这款商品就不能正常售卖了。要知道,这些恶意下单的人是不会真正付款的。
既然“下单减库存”可能导致恶意下单,从而影响卖家的商品销售,那么有没有办法解决呢?你可能会想,采用“付款减库存”的方式是不是就可以了?的确可以,但是 “付款减库存”又会 导致另外一个问题:库存超卖。假如有10件商品,因为下单时不会减库存,就可能出现100人下单成功的情况,这样一 来,就会导致很多买家下单成功但是付不了款,购物体验自然比较差。
既然“下单减库存”和“付款减库存”都有缺点,我们能否采用“预扣库存”这种方式呢? 这种方案确实可以在一定程度上缓解上面的问题,但是否就彻底解决了呢?针对恶意 下单这种情况,虽然把有效的付款时间设置为10分钟,但是恶意买家完全可以在10分钟后再次下单。
针对这种情况,解决办法还是要结合反作弊的措施来制止, 例如,设置最大购买件数,对重复下单不付款的操作进行次数限制等。针对“库存超卖”这种情况,在10分钟时间内下单的数量仍然有可能超过库存数量,遇到这种情况只能区别对待:对普通的商品下单数量超过库存数量的情况,可以通过补货来解决;但是有些卖家完全不允许库存为负数的情况,那只能在买家付款时提示库存不足。
由于参加秒杀的商品成功下单后却不付款的情况比较少,再加上卖家对秒杀商品的库存有严格限制,所以秒杀商品采用“下单减库存”更加合理。一般我们有多种解决方案:一种是在应用程序中通过事务来判断,即保证减后库存不能为负数,否则就回滚;另一种办法是直接设置数据库的字段数据为 无符号整数, 这样减后库存字段值小于零时会直接执行SQL语句来报错。
高可用涉及架构阶段、编码阶段、测试阶段、运行阶段。
1.架构阶段:架构阶段主要考虑系统的可扩展性和容错性,要避免系统出现单点问题,例如多机房部署,即使某个机房出现整体故障,仍然不会影响整体网站的运转。
2.编码阶段:编码最重要的是保证代码的健壮性,例如涉及远程调用问题时,要设置合理的超时退出机制,防止被其他系统拖垮。
3.测试阶段:测试主要是保证测试用例的覆盖度,保证最坏情况发生时,我们也有相应的处理流 程。
4.运行阶段:系统大部分时间都会处于运行态,运行态最重要的是对系统的监控要准确及时,发现问题能够准确报警并且报警数据要准确详细,以便于排查问题。
为什么系统的高可用建设要放到整个生命周期中全面考虑?因为我们在每个环节中都可能犯错, 而有些环节犯的错是无法弥补的。例如在架构阶段,没有消除单点问题,那么系统 上线后,遇到突发流量把单点给挂了,加机器都加不进去。
那么针对秒杀系统,我们重点介绍在遇到大流量时,应该从哪些方面来保障系统的稳定运行,所 以更多的是看如何针对运行阶段进行处理,这就引出了接下来的内容:降级、限流。
降级:就是当系统的容量达到一定程度时,限制或者关闭系统的某些非核心功能,从而把有限的资源保留给更核心的业务。降级方案可以这样设计:当秒杀流量达到5w/s时,把成交记录的获取从展示20条降级到只展示5条。
执行降级无疑是在系统性能和用户体验之间选择了前者,降级后肯定会影响一部分用户的体验,。 所以降级的核心目标是牺牲次要的功能和用户体验来保证核心业务流程的稳定,是一个不得已而 为之的举措。
限流: 如果说降级是牺牲了一部分次要的功能和用户的体验效果,那么限流就是更极端的一种保护措施 了。限流就是当系统容量达到瓶颈时,我们需要通过限制一部分流量来保护系统,并做到既可以人工执行开关,也支持自动化保护的措施。
首先,来分别说下客户端限流和服务端限流的优缺点。 客户端限流,好处可以限制请求的发出,通过减少发出无用请求从而减少对系统的消耗,缺点 就是当客户端比较分散时,没法设置合理的限流阈值。如果阈值设的太小,会导致服务端没有 达到瓶颈时客户端已经被限制;而如果设的太大,则起不到限制的作用。 服务端限流,好处是可以根据服务端的性能设置合理的阈值,而缺点就是被限制的请求都是无效的请求,处理这些无效的请求本身也会消耗服务器资源。
以上的内容就是我所介绍的秒杀系统设计中的难点和一些解决思路,不是每个方案都完美,选择一个适合自己的才重要。
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数
电脑0x0000001A蓝屏错误怎么U盘重装系统教学分享。有用户电脑开机之后遇到了系统蓝屏的情况。系统蓝屏问题很多时候都是系统bug,只有通过重装系统来进行解决。那么蓝屏问题如何通过U盘重装新系统来解决呢?来看看以下的详细操作方法教学吧。 准备工作: 1、U盘一个(尽量使用8G以上的U盘)。 2、一台正常联网可使用的电脑。 3、ghost或ISO系统镜像文件(Win10系统下载_Win10专业版_windows10正式版下载-系统之家)。 4、在本页面下载U盘启动盘制作工具:系统之家U盘启动工具。 U盘启动盘制作步骤: 注意:制作期间,U盘会被格式化,因此U盘中的重要文件请注
在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList()Obt
目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称
项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU
需求:要创建虚拟机,就需要给他提供一个虚拟的磁盘,我们就在/opt目录下创建一个10G大小的raw格式的虚拟磁盘CentOS-7-x86_64.raw命令格式:qemu-imgcreate-f磁盘格式磁盘名称磁盘大小qemu-imgcreate-f磁盘格式-o?1.创建磁盘qemu-imgcreate-fraw/opt/CentOS-7-x86_64.raw10G执行效果#ls/opt/CentOS-7-x86_64.raw2.安装虚拟机使用virt-install命令,基于我们提供的系统镜像和虚拟磁盘来创建一个虚拟机,另外在创建虚拟机之前,提前打开vnc客户端,在创建虚拟机的时候,通过vnc
我在我的项目中有一个用户和一个管理员角色。我使用Devise创建了身份验证。在我的管理员角色中,我没有任何确认。在我的用户模型中,我有以下内容:devise:database_authenticatable,:confirmable,:recoverable,:rememberable,:trackable,:validatable,:timeoutable,:registerable#Setupaccessible(orprotected)attributesforyourmodelattr_accessible:email,:username,:prename,:surname,:
因为我现在正在做一些时间测量,我想知道是否可以在不使用Benchmark类或命令行实用程序time的情况下测量用户时间或系统时间。使用Time类只显示挂钟时间,而不显示系统和用户时间,但是我正在寻找具有相同灵active的解决方案,例如time=TimeUtility.now#somecodeuser,system,real=TimeUtility.now-time原因是我有点不喜欢Benchmark,因为它不能只返回数字(编辑:我错了-它可以。请参阅下面的答案。)。当然,我可以解析输出,但感觉不对。*NIX系统的time实用程序也应该可以解决我的问题,但我想知道是否已经在Ruby中实
在Ruby中,以毫秒为单位获取自纪元(1970)以来的当前系统时间的正确方法是什么?我试过了Time.now.to_i,好像不是我想要的结果。我需要结果显示毫秒并且使用long类型,而不是float或double。 最佳答案 (Time.now.to_f*1000).to_iTime.now.to_f显示包含十进制数字的时间。要获得毫秒数,只需将时间乘以1000。 关于ruby-以毫秒为单位获取当前系统时间,我们在StackOverflow上找到一个类似的问题: