我的秒杀总结

秒杀系统设计(学习):从 “稳准快” 到落地的全流程方案 秒杀系统设计的核心在于应对瞬时高并发请求,保证"稳、准、快"三大目标。通过分层优化策略:1)前端静态资源CDN缓存+动态数据本地暂存;2)接入层限流+应用层本地缓存;3)Redis预扣库存+消息队列削峰;4)数据库最终一致性校验。关键要解决超卖问题(Redis预扣+MySQL双重校验)和热点隔离(业务/系统/数据三层隔离)。兜底方案包括限流、熔断、降级和事后核对,确保系统高可用。整体设计遵循"层层过滤、抓大放小"原则,用简单方案解决核心问题。 阅读详情

title: 我的秒杀总结
date: 2016-11-24 19:50:35
categories:

  • 技术
    tags:
  • 实习

近期 接到一个十万数量的秒杀任务,后台完全由我写。因为之前对秒杀的处理所知甚少,故趁此机会学习了一下。当然,这里 秒杀 只涉及到 “抢” 的环节,没有下单、支付等,故对性能要求不是那么高。最终,“跌跌撞撞”地还是让系统上线了,目前运行良好。

项目环境

两台业务的服务器,还有一台缓存服务器和一台数据库服务器。
在整个项目 的 前端部分 自然离不开 负载均衡。故 这里 还是采用 Nginx 来实现。具体方式采用默认的配置,即轮询的方式。

关于“抢”的环节

intro:一天分为几个时段开抢,每个时段有几分钟的时间抢(该时段的奖品抢完了或者时间到了,该时段抢购就结束了),对于没有抢完的奖品,要求自动“滚到”下一轮。

为了满足如上要求,自然得从数据库开始设计。在系统运行前,将十万奖品 批量输入 至数据库。我给 所有奖品 设计了一个生效时间 和一个 是否被抢 的标志。

这里我采用的技巧是(解决方案):
每个奖品 都有一个生效时间,这个生效时间是每个时间段的开始时间,只有当前时间大于生 效时间该奖品才可以抢(具体可以用sql控制,这里时间采用ms,时间越往后时间越大)。

再 声明 一下抢奖品的策略:只有当前时间大于奖品的生效时间,该奖品才可以抢。这样设计解决了对于后面的几轮秒杀可以秒杀到之前没抢完的奖品(因为后面几轮的当前时间大于前面奖品的生效时间)的要求。同时 ,又可以避免 前一时段的秒杀环节 抢到 后面时段的奖品。原因自然是 当前时间比后面几轮的生效时间小。

性能方面:为了避免每一次都要去数据库查取符合条件的奖品(生效时间和是否被抢),++我自然需要将奖品一次性地多拿几个放到内存里++。这里 我使用 队列 来存放 符合条件的奖品,每来一个用户,抢走(弹出)队列头部的奖品。后面的用户来了 再弹出一个。从而避免 用户“同时”拿到同一个奖品,从而避免“超卖”现象。

那么队列我具体采用什么样的数据结构呢?如下
基于链接节点的无界线程安全队列(这个名字很霸气~~)

    private static volatile Queue<Coupon> couponQueue;
    static{
        if (null == couponQueue) {
            LOG.info("QueueServiceImpl init!!");
            couponQueue = new ConcurrentLinkedQueue<Coupon>(); 
            }
    }

具体弹出采用什么代码呢?

@Override
public  Coupon getPoll(String uid) {
    Coupon coupon = null;
    synchronized(this){
        coupon = couponQueue.poll();
        if (coupon == null) {
            setQueue();//从数据库里取奖品放入队列的方法
            coupon = couponQueue.poll();
        }
        if (coupon!=null){
            int row =  couponDao.allocateCoupon(coupon.getId(),uid,CouponConst.Status.USED,System.currentTimeMillis());

            if (row!=1){
                coupon = null;
            }
        }
    }
    //打日志
    if (coupon!=null) {
        LOG.info(
                "getPoll uid:{},couponId:{}",
                new Object[]{uid, coupon.getId()});
    }
    return coupon;
}

这里有个synchronized,是为了线程安全,避免多个人访问同一段代码产生冲突。
那么为什么把“弹出”(如果内存队列里没有了,还会去数据库里一次性取100奖品来放入内存)和update奖品是否被抢状态的代码同时锁住呢?

试想这样一种场景:内存里原本放100个奖品的队列,经过一段时间后还剩下两个奖品。此时,甲、乙两个用户过来弹出了最后的两个奖品,还未来的及修改奖品状态。此时此刻,丙冲了过来,结果发现队列里没有了,coupon==null,就去setQueue()从数据库里拿符合条件的100个奖品放入内存队列。然而!,甲乙还没来得及将其抢到的奖品修改状态,就是说这两个奖品还没有被标记已经抢过。所以 这两个奖品又会被丙放入内存队列,接着弹出!由后来者再去抢。从而造成一种现象,最后的奖品被多个用户抢到,从而形成冲突。解决方案:加锁!

是不是这样就可以了呢??

回答是No!因为我在学校 一般都写的是 一个业务服务器,这里是两个!亲,两个和一个有着巨大差别,这是放在内存里,不是缓存服务器里。所以A服务器取了100个符合条件的奖品,B服务器也取了100个符合条件的奖品,然而!,A和B可能取得都是前100个奖品,就是说,这俩服务器取得是相同的奖品,然后进行发放!怎么办呢??

解决方案:我首先想到的是将奖品队列放入缓存服务器(1台)里?这样就避免冲突。可是 缓存 用的是 xmemcached,不是redis!没法支持那么多数据结构,而且xmemcached的CAS用起来并不舒服,,,
那么,该怎么处理呢~上代码:

    int flag = -1 ;//因为 线上有两台服务器, 所以 为避免两台服务器 取 相同的 coupon 放入自己的内存;故采用 id%2==flag 分开。

​

    int ip = LocalIPGetter.getLocalServerIpTail(); //获取当前服务器ip
    if (ip == 223) { //如果是A服务器 取id为奇数的奖品放入内存队列
        flag = 1;
    }else {         //如果是B服务器 取id为偶数的奖品放入内存队列
        flag = 0;
    }
    List<Coupon> couponList = couponDao.selectByStatusValidate(CouponConst.Status.INIT,current,100,flag); //两台服务器根据奇偶数进行分类去数据库取奖品。

上述代码就是我的解决思路,是不是太简单了点,把数据库表分成两块,两个服务器互不干扰。

还有缓存服务器,我将获奖者名单放在里面,减少对数据库的访问。

关于“抢”的环节 多次点击问题

我遇到这样一个问题(一位用户只能秒杀成功一次):

试想这样一个场景,对于某用户甲,点击了“秒杀”按钮。但是由于网速、性能等原因,用户甲比较着急,连续点了好几次。

当第一次请求发来时:数据库里没有该用户的记录,资格认证,发现没有秒杀记录,将要添加用户,想进入秒杀流程。注意:这里是将要,还没有添加用户。此刻!!!
该用户的第二次点击请求发了过来,资格认证,发现没有秒杀记录,将要添加用户。然而!!!第一次请求添加用户成功,第二次请求又来添加,数据库主键冲突!500!

解决方案:
每次点击,收到请求检查缓存没有该账户信息,第一件事放入 缓存(key值为其账户主键)中,同时设置2s后失效。
如果 缓存中 有该账户信息,说明 2s 内该用户 访问过,返回411,访问过于频繁。
OK

疏忽!

在活动开始的前一天,QA正在火急火燎地测试。自然,线上测试用的是测试数据,奖品的中奖码都是模拟的。注意,我说的是线上测试。
晚上,22:00测试完毕。我把数据库里的数据库变成真实数据,就屁颠屁颠地回家了。

我想说的是,然而!!!两台业务服务器里的两个奖品队列还是测试的模拟数据,然后我就,,,这个坑,,,
切记
切记,清空缓存,清空内存
重要事情说三遍,清空缓存,清空内存。
情空缓存,清空内存

后续的想法

我能不能将抽取、改变状态的 流程 写在数据库里,作为存储过程来调用会不会更快??
然后我就开始写存储过程,,,,

然而!!!后来DBA告诉我:

存储过程 与 触发器 都不允许。
计算尽量不要放在数据库来,
数据库主要完成数据存取的功能。

如果我这么做,有可能会导致数据库死锁,,,,

待续

我想我如果再写秒杀系统的话 自然会做的更好,以上都是我自己的摸索。后续我会尝试 消息队列(Notify?MetaQ?),用redis?什么有损服务?什么熔断机制?

继续探索吧~

【Python秒杀脚本】淘宝或京东等秒杀抢购 我们的目标是秒杀淘宝或京东等的订单,这里面有几个关键点,首先需要登录淘宝或京东,其次你需要准备好订单,最后要在指定时间快速提交订单。这里就要用到一个爬虫利器Selenium,Selenium是一个用于Web应用程序测试的工具,Selenium可以直接运行在浏览器中,通过后台控制操作浏览器,完成购买操作,利用它我们可以驱动浏览器执行特定的动作,抢购脚本就是通过Selenium来完成自动登录和自动购买的操作的。httpshttpshttpshttpshttps。... 阅读详情

相关推荐

秒杀业务

1. 秒杀业务分析 1.1 需求分析 所谓“秒杀”,就是网络卖家发布一些超低价格的商品,所有买家在同一时间网上抢购的一种销售方式。通俗一点讲就是网络商家为促销等目的组织的网上限时抢购活动。由于商品价格低廉,往往一上架就被抢购一空,有时只用一秒钟。 秒杀商品通常有两种限制:库存限制、时间限制。 需求: (1)商家提交秒杀商品申请,录入秒杀商品数据,主要包括:商品标题、原价、秒杀价、商品图片、...

qq_42806915的博客 3561

秒杀的大概流程

秒杀场景: 大量用户在同一时间同时进行抢购 怎么去做 1、秒杀相关的活动页面相关的接口,所有查询能加缓存的,全部添加 redis 的缓存; 2、活动相关真实库存、锁定库存、限购、下单处理状态等全放 redis; 3、当有请求进来时,进入活动 ID 为粒度的分布式锁,第一步进行用户购买 的重复性校验,满足条件进入下一步,否则返回已下单的提示; 4、第二步,判断当前可锁定的库存是否大于购买的数量,满足条件进入下 一步,否则返回已售罄的提示; 5、第三步,锁定当前请求的购买库存,从锁定库存中减除,并将下单的请 求

java_kuangjia的博客 2616

Chrome浏览器高效抢购秒杀插件:秒杀助手改进版

在电子商务风靡的今天,商品秒杀成了消费者获取热门商品的一种方式。然而,手动参与秒杀常常因为网络延迟或操作不及时而失败。为了解决这一问题,Chrome浏览器的秒杀插件应运而生,它们能在瞬间帮助用户自动完成繁琐的操作过程。本文将详细分析Chrome浏览器秒杀插件的工作原理,如何自定义秒杀定时任务,以及插件在提高用户秒杀成功率方面的作用。接下来,我们将深入探讨插件内部的定时任务功能,并说明如何实现可视化选择秒杀按钮,乃至如何通过自定义DOM选择器来精确控制秒杀过程。

weixin_34064233的博客 1529

系统设计——秒杀系统设计

秒杀大家都不陌生。自2011年首次出现以来,无论是双十一购物还是 12306 抢票,秒杀场景已随处可见。简单来说,秒杀就是在同一时刻大量请求争抢购买同一商品并完成交易的过程。从架构视角来看,秒杀系统本质是一个高性能、高一致、高可用的三高系统。而打造并维护一个超大流量的秒杀系统需要进行哪些关注。博文主要介绍的有关于秒杀系统的设计和底层实现原理。

庄小焱 1万+

WGCNA样本量不够怎么办?5种替代方案帮你解决小样本基因共表达分析难题

本文针对WGCNA样本量不足的问题,提供了5种科学替代方案,包括CEMiTool、参数调整、多组学数据整合、机器学习特征提取和公共数据利用。这些方法帮助研究者在小样本条件下仍能进行可靠的基因共表达分析,特别适用于罕见病和珍贵临床样本研究。

weixin_42554042的博客 301

VoLTE吞字断续优化方案

网络侧通过各节点探针的数据采集,能够进行RTP和RTCP包的分析,确定各节点的上行或下行丢包情况。1.基于测试语音分析,每2秒中大约8个字,每个字约10个RTP语音包。通话过程中,语音有短暂停顿,收音段听语音中会出现“吞字/断续现象”2.连续丢3~5个RTP以上就可能会出现吞字断续的感觉。下行评价的丢包问题,很难有效指导定界定位分析,无从下手。2.部分终端可能存在RTCP不反馈,导致无法获取丢包。1.语音包为UDP包,无反馈,终端无法判定是否丢包。终端可依据自身的调度反馈或弃包进行上行丢包判决。

m0_73503557的博客 1510

秒杀活动总结(秒杀之一)

秒杀活动总结(秒杀之一)

荣山的博客 1379

QT的温湿度显示系统

大家好,这里是石侃侃的博客,欢迎前来讨论这篇文章介绍的是DHT11在2440上的基于Qt5.6的应用基于单片机系统的温湿度监测系统构成框图如图2-1所示。图2-1 系统构成框图该系统采用单片机s3c2440作为了本设计的核心元件。利用LCD作为了显示器件,利用触摸屏作为用户界面输入设备,第一行显示当前实时的温度,湿度,第二行依次显示历史时刻最高的温度值,最高的湿度值。第三行是一个文本框,记录了程...

zxpcus的博客 1万+

秒杀系统学习总结

秒杀系统是高并发的经典场景。 秒杀系统的挑战 对现有正常业务的冲击:解决方法是对秒杀单独部署。 应用服务器和数据库负载压力 1)秒杀开始前:如果所有查看秒杀商品页面的请求(如刷新页面看秒杀是否开始),都到达后端应用服务和数据库,那么将产生极大负载压力。 解决方法是,秒杀页面静态化:将商品描述、商品参数、成交记录、用户评价等全部写入一个静态页面,而不用动态加载。这样用户浏览该秒杀页面时,...

胜天半子 1474

1、JMP脚本编程全面指南:从基础到高级应用

本博客全面介绍了JMP脚本编程的各个方面,从JMP基础和JSL入门,到数据类型、数据结构、编程方法、数据表操作、图形与三维场景脚本,再到应用程序创建与扩展功能。内容涵盖脚本工具使用、常见任务实现、兼容性说明及未来发展趋势,旨在帮助用户掌握JMP脚本语言的强大功能,提升数据分析的自动化与定制化能力。适合从初学者到高级用户的深入学习与实践参考。

flink9streamer的博客 266

OpenCode + Oh My OpenCode:打造你的终极AI编程团队(OpenCode新手入门指南)

本文详细介绍了开源终端AI编程助手 OpenCode 的完整配置教程 🖥️,从安装、AI模型配置到增强插件 Oh My OpenCode 的部署一应俱全。支持 Claude、ChatGPT、Gemini 多模型切换 🤖,还能实现多AI智能体协作开发。步骤清晰适合新手 📝,想在终端用AI写代码的开发者不要错过 ✨

XiaoqiangClub的博客 1万+

【高并发】高并发秒杀系统架构解密,不是所有的秒杀都是秒杀!

网上很多的文章和帖子中在介绍秒杀系统时,说是在下单时使用异步削峰来进行一些限流操作,那都是在扯淡! 因为下单操作在整个秒杀系统的流程中属于比较靠后的操作了,限流操作一定要前置处理,在秒杀业务后面的流程中做限流操作是没啥卵用的。

冰河的专栏 6164

基于YOLOv8的表面裂痕等缺陷检测:深度学习与UI界面的实践

本文详细介绍了如何使用YOLOv8进行表面裂痕等缺陷检测,并结合图形用户界面展示检测结果。通过YOLOv8的强大能力,我们可以实现高效、准确的表面缺陷检测,提升工业产品的质量控制水平。未来,随着深度学习技术和数据集的不断发展,表面缺陷检测的精度和速度将不断提升,应用领域也将进一步拓展。希望本文的实践能够为深度学习在工业检测领域的应用提供一些启示。

YOLO 549

电商秒杀项目-秒杀模块

秒杀

qq_40916110的博客 2309

EPLAN中2D安装板的绘制方法示例

EPLAN中2D安装板的绘制方法示例

Robot_PLC_HMI_Automation 3212

javascript 酷炫时钟

javascript 酷炫时钟

liuhao9999的博客 631

秒杀流程

秒杀活动开始之前有个活动倒计时,时间到了则会放开秒杀的权限,并生成一个验证码展示在前面页面,并把验证结果存在redis中,这里利用redis有过期时间的特性,也给验证码的缓存加了个过期时间。这里的redis缓存用的是redis的string类型。 在秒杀之前先要填一个验证码verifyCode,点击秒杀按钮时,先发送ajax请求到后台获取真实的秒杀地址path,这里秒杀地址是隐藏的,目的是防止有...

weixin_39590058的博客 3659

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

秒杀设计方案(一篇文章秒杀面试官)

秒杀设计详细过程:(关于后端我就详细讲解一下) 前端操作 1、秒杀开始前,秒杀按钮灰掉为“未开始”,不可点击。 2、URL在活动开始前不可露出或者生效,否则容易被使用工具绕过浏览器提前下单。导致活动还未开始,已经开始下单这个大黑洞。我们的做法是在活动开始前,通过更新JS文件露出下单的URL。 3、在秒杀进行中,秒杀按钮才可以点击下单。 4、秒杀产品的介绍,详情,参数等等,全部静态化,将秒杀...

小杰爱吃蛋的博客 5542

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Chrome浏览器 抢购、秒杀插件,秒杀助手

秒杀插件(seckill)Chrome浏览器 抢购、秒杀插件(秒杀助手) 可自定义 秒杀辅助插件(减少人肉失误) 任意网站,自定义添加秒杀定时任务 支持可视化选择“秒杀”按钮+自定义选择dom元素 自定义秒杀频率,秒杀次数 秒杀前2分钟提醒 北京时间自动校对,准时秒杀 注意事项 请求提前登陆,选择商品的规格型号 暂不支持秒杀时输入验证码验证和其他复杂的(多步骤)抢购秒杀 秒杀助手只是辅助,不保证10

GJH 6万+

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

【SpringBoot商城秒杀系统项目实战14】秒杀功能的实现(秒杀业务逻辑处理)

先去设置数据库里面的秒杀时间 假设当前时间是2019-05-28 19:30:12 1.已经开始 2.秒杀结束 3.秒杀倒计时 所以我们去秒杀第一个商品: 在之前的goods_detail.html里面的秒杀按钮点击之后提交/miaosha/do_miaosha,以POST类型提交,带有数据是秒杀商品的goodsId 新建一个MiaoshaController,定义接收该秒杀请求的接口方法d...

pitt1997的博客 6836

京东秒杀之秒杀实现

秒杀功能实现

_山月见光的博客 1921

设计一个秒杀系统-秒杀方案分析

学习使用,老鸟很过,欢迎交流 秒杀系统应该考虑哪些因素 高可用:秒杀系统最大的特点就是并发高,在极短的时间内, 瞬间用户量大。试想一下双11的时候可能会有几十万的用户去访问同一个商品详情页面秒杀同一个商品,那么我们的系统如何能在这么大的并发请求下不被击垮?万一系统被击垮或者错了一些不可控的意外我们需要设置要一个兜底方案 高性能:一个秒杀系统还要考虑如何在大并发请求下拥有好的性能,让用户拥有更好的体验,如果用户需要等待十几秒甚至几十秒才能得到结果那这个体验是很差的。 一致性:最后还要考虑超卖问题,大并发请求下

墨家巨子@俏如来 3519

秒杀优化+秒杀安全

Data;/*** Description: 秒杀消息/*** Description: 限流注解*/ @Retention(RetentionPolicy . RUNTIME) // 运行时生效 @Target(ElementType . METHOD) // 作用在方法上 public @interface AccessLimit {// 时间范围 int maxCount();

Sun的个人博客 1460

抢购、秒杀插件,秒杀助手

Chrome浏览器 抢购、秒杀插件(秒杀助手) 可自定义 秒杀辅助插件(减少人肉失误) 源码地址:http://www.lx138.com 功能 1、北京时间自动校对,手动校对、准时秒杀 2、自动检测是否登录 3、服务器进行云加速,提前比别人快1秒显示验证 4、支持答题杀、抢购杀 安装 chrome浏览器,更多设置 –&gt; 扩展程序,勾选开发者模式 详细操作步骤,参考:http://www.z...

qq_42879514的博客 3万+

Java秒杀系统实战系列~商品秒杀代码实战

摘要: 本篇博文是“Java秒杀系统实战系列文章”的第六篇,本篇博文我们将进入整个秒杀系统核心功能模块的代码开发,即“商品秒杀”功能模块的代码实战。 内容: “商品秒杀”功能模块是建立在“商品详情”功能模块的基础之上,对于这一功能模块而言,其主要的核心流程在于:前端发起抢购请求,该请求将携带着一些请求数据:待秒杀Id跟当前用户Id等数据;后端接口在接收到请求之后,将执行一系列的判断与秒杀处理...

青松之竹_Java博客 7107

秒杀项目总结

秒杀项目总结

qq_44855338的博客 3574
上一篇: 浅谈软件工程学习心得
下一篇: 服务能力输出小结
chengshuo678
博客等级 码龄14年 5粉丝 17原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值