聊的不止技术。跟着小帅写代码,还原和技术大牛一对一真实对话,剖析真实项目筑成的一砖一瓦,了解最新最及时的资讯信息,还可以学到日常撩妹小技巧哦,让我们开始探索主人公小帅的职场生涯吧!

(PS:本系列文章以幽默风趣风格为主,较真侠和杠精请绕道~)

老胡:“哟,小帅,怎样绷着个苦瓜脸似的?”
江华:“失恋了?哦…呸,单身狗哪来的失恋。”
小帅:“…”
小帅:“老胡,老大说要提高组内的学习氛围,要双周组织一次分享会,我刚好抽中一个题目《秒杀系统设计》,我都没这方面的经验,我问老大能不能换一个,他说没关系,尽你最大努力去做就行,我正头疼着呢!”(苦笑表情)

江华:“头疼那不是正好嘛,分享会的时候请病假就好。”(一脸正经表情)
老胡:“…”
小帅:“…”
老胡:“既然你老大这样说,我认为他除了希望大家能分享知识一起学习以外,更多的是考察你们的对知识整理、归纳、总结和传播能力,毕竟只是分享过去的经验,很快就到头了。”
小帅:“哦哦,原来是这样!老胡大神,你之前搞过秒杀系统不,求指点!”
老胡:“嗯…这个到饭点了,好像南塔的红烧鹅掌挺不错的。”
小帅:“在送过来的路上了。”
老胡:“哈哈,孺子可教也,我看你天资聪颖,骨骼惊奇,就是编程届的奇才啊,小小的秒杀分享不在话下。”
江华:“…”(好…贱)

容量预估

老胡:“所谓的秒杀系统,其实就是很多人同时去抢一个东西。毕竟如果只有1000个人抢100个商品,就根本不算秒杀。这时候需要产品、运营、开发一起去做容量预估,这样才能比较合适地去预估后续需要的机器、带宽、存储等等资源。真实的容量预估比较困难,影响的因素比较多,这里你可以简单点,先假设你的秒杀系统将会有50w人参加,去抢500个商品。”

小帅:“Woc,50w用户,系统会崩掉吧…”

老胡:“对啊,小帅你要做的事情就是别让系统崩了。别慌,我们从页面入口到数据落地过程模拟走一遍,去分析要做些什么措施才能应对这50w的流量。”

页面静态化

老胡:“秒杀开始前,我们需要提早准备一个秒杀首页。因为用户肯定会提前登录你的系统,等待秒杀开始。”
小帅:“可是这么多人提前访问秒杀页,秒杀活动还没开始系统可能就挂了啊!”
江华:“笨,页面静态化啊。”
老胡:“是的,整个秒杀页其实只有时间跳动的,其它部分用户信息、商品资料部分我们可以做成html静态页面,做数据拆分。做成静态页想必你们也有所了解,就是可以充分利用缓存,包括浏览器、CDN、服务端缓存。”

老胡:“浏览器缓存可以去了解下HTTP的Cache-Control等协议和304响应码,CDN加速和分发想必你们也有所耳闻,网上资料更全可以自行了解,服务端缓存也就是平时我们做的前端页面和后端代码动静分离,WEB服务器对静态资源进行缓存,请求就不用到达应用服务器。”

老胡:“至于服务器和倒计时时间校准,到点才返回秒杀链接给秒杀按钮,验证码,防重复提交这些细节就不一一展开了。”

负载均衡

老胡:“假设用户已经点击秒杀按钮,提交请求了,这时候请求都打到一台机器肯定不行的,小帅,这时候你应该怎样做呢?”
江华:“报告,小帅去挠头了,我来回答吧,要做负载均衡。”
小帅:“…”
老胡:“是的,我们需要把请求均摊多多台机器上,也就是做负载均衡。常用的负载均衡组件有Nginx、HAProxy、LVS已经土豪版F5等。负载均衡又分为请求均衡和数据均衡,这里加一层DNS分发,把请求分摊到下一层Nginx/OpenResty负载均衡层。”

江华:“老胡,Nginx/OpenResty层通过反向代理也可以做负载均衡啊,为啥还要加一层DNS轮询呢?是为了防止负载层单点吗,那也可以用Keepalive做个VIP啊。”

老胡:“没错,是可以按照你说的那样做。但是单个Nginx/OpenResty性能总会有极限的,这里加了DNS轮询除了可以避免Nginx/OpenResty单点外,还可以解决Nginx/OpenResty自身扩展性问题,例如当Nginx成为系统瓶颈的时候,无法扩容。而通过DNS一个域名设置多个IP解析,就能增加入口Nginx实例个数,起到水平扩展的作用。当然技术架构选型要取决于实际情况,这里是举个例子。”

小帅:“老胡,这里100w是不是画错了?之前我们定了50w用户,页面也做了防重复提交。”
江华:“呵呵,防重复提交只能防住你这种小白。”
老胡:“对,没错。咳咳咳…小帅先放下刀。”

再次均衡

老胡:“防重复提交防不住羊毛党等那些高级玩家,这时候我们需要对请求进行过滤。例如我们可以在Nginx层增加IP过滤,例如每分钟的每个IP的请求次数。高级点可以用Lua脚本获取到用户ID,做一层布隆过滤,过滤非法用户。”

小帅:“OpenResty,好像木有用过哈。我可以在业务代码里过滤不?”(尴尬笑)

老胡:“可以的,假如Nginx/OpenResty这里你只是简单IP的过滤,还有20w请求到达你的后端服务器,这时候你就不用能传统基于BIO/NIO的后端服务器了。你可以选择一些基于IO多路复用和Reactor模型的组件来搭建你的服务器,如Vert.x、WebFlux。”

老胡:“比如你使用WebFlux,也就是Springboot2.0框架,每个OpenResty后端挂了4个节点,每个节点能分到5w请求,这样就把100w的并发量缩减到单节点5w并发量了。”
江华:“单机5w,系统能支撑住吗?”
老胡:“按照以往的经验是可以的,不过这个不用太急下结论,你没有做过实际压测,说这些都是虚的,况且并不是5w都是有效请求,我们先看主流程能不能进行下去。”

限流

小帅:“那这里我们先判断用户合法性吗?我们可以从Redis获取用户信息,速度很快的。如果不为空,表示用户合法,如果为空则表示用户不合法。”

老胡:“不急,Redis虽然快,但为本着让最少的流量到达后端的原则,我们可以现在本机内存里过滤。”

小帅:“对哦,我们可以先用MemberId过滤一层。比如30s内只允许一个相同的MemberId的请求通过,用GuavaCahce处理一下就行,减去Redis负担,妙啊!”

老胡:“不错,其实这里可以加个开关标记,判断秒杀活动是否结束,如果秒杀活动结束,开关关闭,后来的请求就直接拒绝掉了。”

过滤

老胡:“接着才是根据MemberId限流,然后判断用户合法性和用户抢购状态。小帅,你上面提到的判断用户合法性的方法,你觉得存在什么问题?”

小帅:“好像没有啥问题呀?”(挠头表情)
江华:“…鸭掌吃多了吧你!缓存穿透啊!”

老胡:“判断用户合法性的时候,小帅说只查Redis,他的意思是把所有用户数据都放在Redis,不用查DB,严格来说不会存在缓存穿透问题。如果请求都是合法用户的请求,问题不算太大,但如果大部分请求都是非法用户的时候,这样做存在以下问题。”

1、Redis只需存MemberId等必要信息,不然可能造成浪费,尤其用户量庞大的时候。
2、Redis数据需要预热,也就是需要把用户数据预先加载到Redis。
3、空值缓存,当Redis查询结果为空需要缓存空值,减轻Redis负担。

老胡:“综上所述,更优的做法,应该是加一层布隆过滤器来过滤非法用户请求,然后使用本地缓存+Redis缓存来判断用户合法性和抢购状态,用户非法或者抢购成功返回失败或者订单页,请求结束。”

老胡:“布隆过滤器空间压缩比非常高,50w的MemberId占不多少内存,可以提前Load到本地缓存,虽然有一定的误判率,但已经非常高效了!”

令牌抢名额

老胡:“经过上面的一系列操作,到达的都是合法请求了,小帅,上次教你的令牌算法可以派上用场了,没有还给我吧?”

小帅:“交了学费的,当然还记得!”(肉痛表情)
江华:“…”(人傻钱多真好)

老胡:“啊哈哈,记得就好。这里可以利用Redis的decr指令的原子性,定义一个库存Key,初始值为500,当返回正数表示扣减成功,抢购状态置为抢购成功,请求进入后续步骤。当返回负数时候,表示已经售卖完毕,关闭秒杀开关,请求中断。”

异步

小帅:“经过令牌过滤后的请求,最极端的情况下也就500个请求,我是不是可以直接操作DB,生成订单和扣减真正库存了?”

老胡:“这里建议加一层MQ,把获得令牌成功的请求推到消息队列。”

江华:“老胡,没必要吧?这样会不会过度设计了。”

老胡:“前面说过,所有架构设计都要基于实际情况,没有最好的,只有合适的。这里加一层MQ主要出于以下考虑。”

1、解耦:秒杀模块和订单库存模块完全解耦。
2、复用:秒杀活动可以抽取出比较独立的模块,供多种商品多场次提供秒杀服务。
3、对账:可以分两个消费组,其一用来跑主流程,其二跑延时Check流程,保证获得令牌的用户都能成功创建对应的订单,放弃支付的归还令牌等等操作。
4、安全:DB是公司最珍贵也是最薄弱的环节,无论是突然意外还是人为Bug导致海量请求冲垮DB,这都是不可挽回的损失。

防止超卖

老胡:“上面提到,只要获取令牌成功,我们就认为用户秒杀成功。所以从kafka消费到的请求数据,就可以调用订单服务创建订单。”

小帅:“只创建订单,不用扣减库存吗?”

老胡:“先不用,因为用户创建了订单,不一定会支付。我们这里用预扣模式,当用户完成支付时,才需要调用库存服务去扣减库存。”

小帅:“那库存服务怎样才能正确扣减库存呢?多线程去消费MQ的时候可能会扣多了。”

江华:“说你蠢还不信,乐观锁啊,还有脸称自己为资深CRUD工程师!”

老胡:“…”

小帅:“那如果扣减库存失败了呢?”

老胡:“这个时候对账流程就起作用了,它就是用来保证最终一致性的。库存扣减失败就会重试,直到成功,当然重试的时候需要做幂等。”

小帅:“Soga,涨姿势了,小檬下班了,我去目送一下哈,告辞!”

老胡:“…”(好…猥琐)
江华:“…”(好…猥琐)

关于内推

你是否苦恼于自己技术不差但总是得不到大厂面试机会,又拉不下面子求熟人欠别人人情,社招流程慢进度不透明,苦苦等待却不知道面试结果,关注一下公众号即可获得各种大厂内推资格,各种优质岗位等着你,欢迎投递。

面试攻略系列(二)-- 秒杀系统相关推荐

  1. 前端攻略系列(二) - 前端各种面试题

    幸运且光荣的被老大安排了一个任务 - "去整理些前端面试题".年前确实不是招人的好时候,所以我们前端团队经过了超负荷的运转,终于坚持过了春节.春节以后就开始招人啦,这套题考察的目标 ...

  2. Java开发岗面试攻略(应届)

    开发岗面试系列文章目录 第一章 Java开发岗面试攻略(应届) 文章目录 开发岗面试系列文章目录 前言 一.Java技术栈 1.Java速成学习路线 二.Java面试题 1.博主自己总结的面试题(应届 ...

  3. 股票量化分析工具QTYX使用攻略系列——双底形态选股

    前言 自从股票量化分析工具QTYX新增双底形态选股功能以来,大家的反响一直很热烈.很多星球会员利用这个功能帮助自己抓到了大牛股. 确实,双底形态是由市场力量形成的,我们只需顺势而为即可,特别是大周期. ...

  4. 万字长文,小学弟熬夜肝了这份腾讯面试攻略

    本文一万字,以非腾讯在职人的身份,来聊腾讯面试的流程.攻略和建议,但愿能助有缘人. 标题涉及的范围很广,对多数面试腾讯的人而言,都有参考价值,看完本文之后,必有所得. 退一步来讲,即便是准备面试其他公 ...

  5. Java 后端开发面试总结:25 个技术专题(最全面试攻略)

    另送福利: java 面试准备 准确的说这里又分为两部分: 1.Java 刷题 2.算法刷题 Java 刷题:此份文档详细记录了千道面试题与详解:  !     私信我回复[03]即可免费获取 很多人 ...

  6. 万字长文,分享腾讯面试攻略

    本文一万字,以非腾讯在职人的身份,来聊腾讯面试的流程.攻略和建议,但愿能助有缘人. 标题涉及的范围很广,对多数面试腾讯的人而言,都有参考价值,看完本文之后,必有所得. 退一步来讲,即便是准备面试其他公 ...

  7. Spring Cloud Gateway面试攻略,微服务网关的作用以及案例

    微服务系列导航 第一篇:初学者如何快速入门微服务,面试前如何快速熟悉微服务 第二篇:微服务Spring Cloud Alibaba之Nacos篇, Nacos 就是注册中心 + 配置中心的组合 第三篇 ...

  8. 实习面试攻略(转载)

    From: http://dwz.cn/2bifx 标 题: 人品贴--实习面试攻略 发信站: 饮水思源 (2012年05月26日01:24:31 星期六) 之前向基友许诺说如果拿到爱立信的实习off ...

  9. Github获星99k的Java面试八股文,最全秋招面试攻略

    Github获星99k的Java面试八股文,最全秋招面试攻略 2020年我凭借一份<Java面试核心知识点>成功拿下了阿里.字节.小米等大厂的offer,两年的时间,为了完成我给自己立的f ...

最新文章

  1. 《head first java 》读书笔记
  2. 【C】 36_函数与指针分析
  3. 共享文件夹加密专家_文件加密软件哪家靠谱?
  4. Ubuntu18.04下安装MySQL
  5. 用java读取properties文件--转
  6. 关于进程资源限制的getrlimit和setrlimit函数(epoll、服务器经常用)
  7. nginx正向代理,反向代理概念
  8. 探秘采云间:全链路数据处理工具直击传统DW/BI痛点
  9. 2017哈尔滨ACM CCPC-final 总结
  10. 12. 表数据入口(Table Data Gateway)
  11. android ip计算,子网掩码怎么算_ipv6子网掩码计算器_掩码计算器android
  12. android原生系统裁剪
  13. Duilib的界面设计工具DuiDesigner的使用说明
  14. 微信小程序图片加载失败渲染层网络层错误
  15. 怎么桌面给计算机设密码,怎么设置电脑桌面密码
  16. js实现活动时间倒计时
  17. 不规律的生活有什么危害
  18. 服务器的GPU显示err,Nvidia GPU风扇和电源显示ERR!
  19. javascript创建对象方法总结
  20. 数据挖掘与R分析——京东某鞋类店铺售后评论

热门文章

  1. 个推消息推送Android版常见问题整理
  2. 我为什么不推荐用fmt.Sprintf
  3. vector赋值操作
  4. Qt按钮左边图片右边文字
  5. 录屏固定帧率 Android,Android 录屏时控制帧率
  6. python图形编程pdf_Python计算机视觉编程
  7. Lenovo Legion Y530-15ICH电脑 Hackintosh 黑苹果efi引导文件
  8. joseph环c语言课程设计,Joseph环课程设计.doc
  9. php ejs,EJS模板引擎实例详解
  10. 蓝桥杯 油漆面积【第八届】【省赛】【A组】线段树扫面线/求矩形相交面积/模拟