百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

高并发秒杀系统(高并发抢购)

mhr18 2025-05-03 15:26 16 浏览 0 评论

1.简介

秒杀能够以极小的经费撬动巨大的流量,虽然会带来一定的口碑损失,但因为极具性价比,所以经常被运营同学使用。本文介绍如何设计一款能够支撑60W QPS的秒杀系统,希望能够帮助到大家。

这套系统有着漫长的演变历史,从最初利用Nginx、PHP,到后来使用GO,团队慢慢地将系统做得更加稳定。唯一不好的地方是,当年我写的后台还在使用(写前端代码能力有限),运营配置体验上有些瑕疵,后期需要优化一版。

目前14台8+32的机器,可以支撑60W QPS,理论上还能支持得更高,不过单ELB的上限是60W,即使流量再高,在ELB层也会溢出了。

一般大家听到秒杀系统,最可能想到的是高并发,但高并发只是其中的一部分,需要其他的组件一起配合,才算是一个完整的秒杀系统。

本文从这几个方面来讲述该系统

  • 后台
  • 高并发系统设计

- 获取活动信息

- 秒杀

- 统计

不过在讲述之前,我们先看一下应用场景,让大家对秒杀有一个直观的了解。

在活动页面上会有抢购模块,会展示抢购的时间、商品图片、商品名称、秒杀价、商品价等信息。活动开始之前按钮为Coming soon。

当活动时间到了,按钮会变为Buy now,瞬间服务器压力飙升。点击Buy now时,如果秒杀成功,会跳转到购物车页,这时候只需要按照正常流程支付即可。如果不成功,按钮会变为Out of stock。当然,如果不点击Buy now按钮,该按钮文案不会变更,除非重新刷新页面。

秒杀活动完成后,会在页面上展示秒杀成功用户的id。之所以添加这个功能,是因为很多用户投诉这是假秒杀,作为商家,做活动也不容易。

2.后台

通过对场景的描述,可以分析出后台需要配置的内容。
https://www.processon.com/view/link/5fb0a1e75653bb657c335c60

1.每场活动配置:需要配置每场秒杀活动的开始时间和结束时间,以及参加秒杀的商品信息。还有一些特殊需求,如只有用户分享后才能参与秒杀等。

2.对于活动配置,需要有编辑、推送、校验、测试功能

  • 校验功能:主要用于查看推送出去的数据是否和配置的数据一致,主要用来检查系统正确性、运营操作正确性
  • 测试功能:主要用于白名单测试,使测试人员可以在活动页面真正的演练秒杀过程,同时又不影响正常用户。因为一次秒杀活动可能有多个场次(如每天一场秒杀,每场秒杀两个商品,持续7天),为了让测试同学方便配置,只需要设定好第一场的时间,根据每场活动时间间隔,其他场次的秒杀会自动配置好,商品数量只需设置一次,所有场次商品数量都为该值。

3.监控后台,必然需要监控线上情况,但是对于测试情况也需要进行监控,主要为了便利测试人员查看。监控一般关注于:中奖用户、秒杀卖出数量是否和配置数量一致、参与用户数、QPS峰值最重要的当然是中奖用户数量、秒杀卖出数量与活动配置数量是否一致,如果不一致,那肯定是出问题了,后面面临修数据、补数据。

4.黑名单管理:有些地区的用户,十分喜欢用脚本刷,对于这些用户,一部分通过程序自动抓取,一部分分析得出后,使用该管理平台,手动添加。

秒杀系统的后台给大家讲完了,下面我们进入大家感兴趣的高并发处理环节。

3.高并发系统设计

3.1获取秒杀活动信息

获取秒杀活动信息,相对比较简单,核心是通过goroutine,设置计时器,每过一段时间从Redis拉取数据,同步到本地缓存,这样能大大减小Redis的压力。

目前该接口,在8+32的机器上,qps能支持到3~4W左右,其实仍然有一定的提升空间。

  1. 可以将部分不变的数据放到CDN,库存、当前场次等动态变化的信息提供新接口,这样可以进一步减少后端冗余的逻辑和返回数据量,不过对前端要求会提高。
  2. 即使是在当前的逻辑中,有部分场次的活动,因为并不参与展现,所以可以不参与计算,同时也无需返回,一定程度上也能提高性能。

3.2秒杀接口

秒杀接口为最核心的接口,需要保证指定数量的秒杀商品不超卖,也不少卖。这个接口决定了秒杀系统的最终准确性。本来这个接口也做了流程图,不过一是里面有些内容涉及到隐私,另一方面如果给出流程图,可能大家的设计就都一样,少了很多其他的可能性。所以这里只阐述核心点:

1.使用两级限流措施,第一级为随机限流,第二级为令牌桶,限流的比例根据预估流量和商品数量来限制,尽量确保1s内所有商品售卖完成。例如,10个商品,60W请求,如果随机限流设置为千分之二,意味1s只有1200个请求能真正走到逻辑层,逻辑层压力会小很多。而令牌桶能够防止逻辑层过载。

2.黑客是需要重点考虑的对象

  • 如果提前请求则标记为黑客,进行记录
  • 如果1s内同一个用户多个请求到达逻辑层,标记为黑客,进行记

3.对于走到逻辑层的请求,需要做众多判断,确保系统准确性

  • 该用户或者IP不在黑客列表里
  • 该用户本次活动中没有秒杀成功过
  • 同一个用户不能获得两次秒杀成功的机会
  • 是否仍然有足够的库存
  • 帮用户按照秒杀价添加到购物车

本系统使用Redis来管理库存,虽然使用两级限流后,Redis负载不大,但是仍然有出错的可能性。

在库存管理上,通过一切检查后,如果符合规定,会先扣减库存。这样保证了不会超卖。

有一种情况,如先扣减库存,添加购物车失败,但是归还库存失败,这样会导致少卖。对于这种情况,目前做法为记录日志,活动结束后,如果数据不对,根据日志进行补发。

对于这种情况的优化,我能想到的办法有错误重试、错误写入队列后异步处理、分析日志自动处理错误。这几种方案,在某些极端情况下,仍然会失效,如果大家有更好的方案可以提供一下。

不过因为日志的存在,让我们有了保底的方案,而且如果在如此小流量下,Redis都无法稳定的话,可能问题就不仅仅是这一个服务了。

3.3统计

对于秒杀成功用户的统计,比较容易完成,秒杀成功后写入Redis即可。

但是对于秒杀流量的统计,就无法使用这种方案了,毕竟60W的流量,Redis可能也撑不住。

这里介绍一个比较巧的方案。

  1. 每次请求秒杀接口时,使用golang的原子操作,将统计变量statNow的值加1
  2. 起goroutine,设置定时任务,计算当前统计总数与上次统计总数的差值,写到Redis中
ticker := time.NewTicker(time.Millisecond * 100)
  go func() {
    for range ticker.C {
      orig := atomic.LoadUint64(&statOrig)
      now := atomic.LoadUint64(&statNow)
      num := int64(now - orig)
      if num > 0 {
        //将增加的数值incr到Redis中
      }
      atomic.SwapUint64(&statOrig, statNow)
    }
}()

总结

Golang是门好语言,帮我们解决了众多问题。单机使用Nginx,并发2W左右,不使用Nginx,直接用go,并发4W,在语言层面上直接解决了高并发问题。

使用两级限流策略,保证服务器压力可控。

灵活运用Go提供的功能,Goroutine、定时器、本地存储、原子操作、读写锁等。

合理使用Redis,保证服务的准确性与稳定性。

虽然还有少许的待完善点,但并不影响使用。

如果后续压力继续增加,一个可行方案是CDN边缘计算。当然,如果有钱,不必这么扣扣索索的,堆机器也是可以的。

相关推荐

SpringBoot 各种分页查询方式详解(全网最全)

一、分页查询基础概念与原理1.1什么是分页查询分页查询是指将大量数据分割成多个小块(页)进行展示的技术,它是现代Web应用中必不可少的功能。想象一下你去图书馆找书,如果所有书都堆在一张桌子上,你很难...

《战场兄弟》全事件攻略 一般事件合同事件红装及隐藏职业攻略

《战场兄弟》全事件攻略,一般事件合同事件红装及隐藏职业攻略。《战场兄弟》事件奖励,事件条件。《战场兄弟》是OverhypeStudios制作发行的一款由xcom和桌游为灵感来源,以中世纪、低魔奇幻为...

LoadRunner(loadrunner录制不到脚本)

一、核心组件与工作流程LoadRunner性能测试工具-并发测试-正版软件下载-使用教程-价格-官方代理商的架构围绕三大核心组件构建,形成完整测试闭环:VirtualUserGenerator(...

Redis数据类型介绍(redis 数据类型)

介绍Redis支持五种数据类型:String(字符串),Hash(哈希),List(列表),Set(集合)及Zset(sortedset:有序集合)。1、字符串类型概述1.1、数据类型Redis支持...

RMAN备份监控及优化总结(rman备份原理)

今天主要介绍一下如何对RMAN备份监控及优化,这里就不讲rman备份的一些原理了,仅供参考。一、监控RMAN备份1、确定备份源与备份设备的最大速度从磁盘读的速度和磁带写的带度、备份的速度不可能超出这两...

备份软件调用rman接口备份报错RMAN-06820 ORA-17629 ORA-17627

一、报错描述:备份归档报错无法连接主库进行归档,监听问题12541RMAN-06820:WARNING:failedtoarchivecurrentlogatprimarydatab...

增量备份修复物理备库gap(增量备份恢复数据库步骤)

适用场景:主备不同步,主库归档日志已删除且无备份.解决方案:主库增量备份修复dg备库中的gap.具体步骤:1、停止同步>alterdatabaserecovermanagedstand...

一分钟看懂,如何白嫖sql工具(白嫖数据库)

如何白嫖sql工具?1分钟看懂。今天分享一个免费的sql工具,毕竟现在比较火的NavicatDbeaverDatagrip都需要付费才能使用完整功能。幸亏今天有了这款SQLynx,它不仅支持国内外...

「开源资讯」数据管理与可视化分析平台,DataGear 1.6.1 发布

前言数据齿轮(DataGear)是一款数据库管理系统,使用Java语言开发,采用浏览器/服务器架构,以数据管理为核心功能,支持多种数据库。它的数据模型并不是原始的数据库表,而是融合了数据库表及表间关系...

您还在手工打造增删改查代码么,该神器带你脱离苦海

作为Java开发程序,日常开发中,都会使用Spring框架,完成日常的功能开发;在相关业务系统中,难免存在各种增删改查的接口需求开发。通常来说,实现增删改查有如下几个方式:纯手工打造,编写各种Cont...

Linux基础知识(linux基础知识点及答案)

系统目录结构/bin:命令和应用程序。/boot:这里存放的是启动Linux时使用的一些核心文件,包括一些连接文件以及镜像文件。/dev:dev是Device(设备)的缩写,该目录...

PL/SQL 杂谈(二)(pl/sql developer使用)

承接(一)部分。我们从结构和功能这两个方面展示PL/SQL的关键要素。可以看看PL/SQL的优雅的代码。写出一个好的代码,就和文科生写出一篇优秀的作文一样,那么赏心悦目。1、与SQL的集成PL/S...

电商ERP系统哪个好用?(电商erp哪个好一点)

电商ERP系统哪个好用?做电商的,谁还没被ERP折腾过?有老板说:“我们早就上了ERP,订单、库存、财务全搞定,系统用得飞起。”也有运营吐槽:“系统是上了,可库存老不准,订单漏单错单天天有,财务对账还...

汽车检测线系统实例,看集中控制与PLC分布控制

PLC可编程控制器,上个世纪70年代初,为取代早期继电器控制线路,开始采取存储指令方式,完成顺序控制而设计的。开始仅有逻辑运算、计时、计数等简单功能。随着微处理的发展,PLC可编程能力日益提高,已经能...

苹果五件套成公司年会奖品主角,几大小技巧教你玩转苹果新品

钱江晚报·小时新闻记者张云山随着春节的临近,各家大公司的年会又将陆续上演。上周,各大游戏公司的年会大奖,苹果五件套又成了标配。在上海的游戏公司中,莉莉丝奖品列表拉得相当长,从特等奖到九等奖还包含了特...

取消回复欢迎 发表评论: