建材秒知道
登录
建材号 > 设计 > 正文

Redis 秒杀系统的设计与实现

矮小的仙人掌
等待的棒棒糖
2022-12-31 21:55:39

Redis 秒杀系统的设计与实现

最佳答案
知性的小兔子
顺利的抽屉
2025-06-21 18:57:45

还记得刚工作那会,每每听到大牛们聊技术,各种专业术语,巴拉巴拉的,简直像是在听天书,比如什么中间件、分布式、SOA、无状态、热更新、懒加载、ACID、LVS、LDAP、VIP、CDN、负载均衡、鲁棒性、POJO、DSL、DI、IOC,太多太多了。一转眼快 10 年过去了,当很多新人再问到我这些名词的时候,我就在想,能不能用通俗易懂的大白话,就能聊明白这些专业的技术知识呢?

最近,给几个公司做技术咨询,经常会聊到秒杀系统。所以,借这次机会,尝试用大白话和大家聊聊 Redis 秒杀系统的设计与实现,。

说起 “秒杀”,我相信大家肯定都耳熟能详了,双十一零点抢购、手机整点抢购、抢火车票、1 元秒杀、抢红包等等,都可以说是秒杀的各种应用场景了。

秒杀系统的设计 ,难就难在,在极短的时间内,应对瞬时涌入平时成百上千倍的巨大流量,还包括各种攻击刷量作弊等未知流量,最终我们要保证在用户体验顺畅良好的情况下,不能多卖或者少卖。

而当我们公司决定要做秒杀系统的时候,我就去找业务,到时大概会有多少 UV,不知道 10 倍或者 100 倍?然后去找老板,给技术多少预算,最多平时的 10 倍不能再多了,当然越少越好,呵呵,也就是说让我们用平时最多 10 倍的预算去解决不可预估的用户流量,怎么做?要是有钱直接扔 1 万台服务器跑去吧,钱能解决的事就不是事,但问题是现在还没那么多钱,还要把事情搞定。

在聊秒杀系统设计之前,让我们先回到现实生活中,聊聊常见的“秒杀”场景和秒杀场景的独有特点,以及它们都是怎么应对的,在应对过程中都需要注意什么。

日常生活中,其实也有很多秒杀场景,比如,早上 9 点超市开门,老大爷老大妈抢购蔬菜水果,是不是? 还有,新楼盘开盘抢购,是不是? 股市开盘、交易所现场,是不是?

对的,生活中其实有太多类似场景了, 你有没有发现“秒杀”的独有特点呢?

记住了上面三个特点,我们就可以区分和确定秒杀的业务场景了。 这里我举一个特别的例子, 你说挤公交车,算不算秒杀场景呢?

下面,我再和大家聊一个关于抢猪肉的故事。

在保安部门充分讨论之后,保安大队长决定通过以下安排,在保证人员安全的前提下,还要做到相对公平。

后来,活动井然有序的开始了,但是由于猪肉销售场地太远,销售窗口又少,老大爷和老大妈们买肉又精挑细选,导致整个过程很漫长,而且外面等候的人们都开始骚动起来,这个时候保安大队长赶紧找到经理:

故事讲完了,如果我们把上面的故事,理解为秒杀业务场景,我们就可以总结出一个 秒杀系统的设计原则 了:

最新回答
搞怪的滑板
忐忑的紫菜
2025-06-21 18:57:45

(纯分析一波,如果有什么方面没考虑到,希望各位大咖见谅,并且给我提点哦~ 可以继续完善)首先, 在购票方面, 最主要的一点是要防止黄牛囤积大量票, 第二步在防止黄牛用自己的账号随便买票, 第三步才考虑完全杜绝黄牛为其他人代购票。首先说图片验证码, 图片验证码的作用就是用在最后一步的, 至于为什么不是用于防止黄牛大量囤积或者用于防止黄牛用自己的账号买票, 因为图片验证码总有一个概率通过,根据现在的验证码规则, 在8个图中选择1~3个图,那么随机选一个选中的概率就是1/(8C1+8C2+8C3)=1/92≈1.086% (应用一下中学排列组合知识,C 表示组合数),也就是说, 黄牛买100次票就会有一次抢到票, 这对于一般用户来说这是没用的, 一般的用户就算有这个软件, 100次才有一次那需要的次数也太多了,但对于大量囤积票来说,这就足够了,一个机器人100趟车只能抢到一次,开几十几百个机器人抢就是了,有钱想囤积多少都可以。而防止黄牛拿自己的账号买票也是不行的,黄牛人工操作,你总没办法吧,手工买票,就像以前的黄牛都是到火车站排队去买票一样。那么对于这三点来说,我们应该怎么样设计才能防止呢,一点一点来说:一、 如何防止黄牛大量囤积票这就是还是要从概率的方面考虑。任何验证策略总是有一个成功概率的,那么只要有大量的基数,那就总是能达到预期的成功数量。那么最直接的应对方式就出现了,就是单客户端单账号单个手机号在一定的时间段。(如一个小时或者一天内查询的次数不能超过一个限制,这个限制可以考虑根据时间段的长度来决定限额大小,一般的应用这么做是没必要的,但是对于12306绝对是非常有用的功能)限额,这是最不容易被用户感知到的功能,也是我最推荐的方案,最好能润物细无声的让大量刷票的用户做出一定的限制,让普通用户有一个好好买票的机会。二、 如何防止黄牛用自己的账号买票囤着这一方面来说,验证码也是毫无用处的。因为,人工买票也是一个很好地囤机票手段。在农村招一批年轻的小伙子,找一个黑网吧,经过半天的培训,做抢票的工作肯定毫无问题了。那就一整天人工刷飘来囤积,然后有客户没票着急买的时候,加价20%~40%卖给他,找个人少的时间(以前可以凌晨),一个账户退票,客户账户再买,这就完成了票的转移。那么这个防御的方法就是实名买票,这还不够,还要做:一个账户不能购买的来回去见过多(比如限制15个始发站、终点站组合),或者可以要设置家乡地和工作地,买去这两地或从这里出发的车票会比一定客户容易(春运期间回家肯定是头等大事,别的那就放放再说吧,总不可能你出去旅游玩比人家回家看望父母要重要吧)卖了的票退票不是立马就可以买,而是所有退票都统一时间处理,比如3天前退的票都在发车3天前的某一个时刻放出,3天内的票就当日或次日12:00放出,这样黄牛就没法偷偷地把票转移到客户手里三、如何防止黄牛为其他人买票好吧,这是最麻烦的一步,换句话说,也就是如何让多个用户能比较公平的抢票,不会因为有了什么工具就比人家容易抢票,甚至不会因为手比较慢就不容易有票(当然这个很难)到了这里,黄牛囤积的概率应该已经大大减小了,如果能把这一步页=也禁止了,那么黄牛应该就只能回到最原始的方案(也就是带着乘客从出口往里跑,硬生生摸进去)。到这里图片验证码才开始登场,这也是秒杀方案要考虑的地方。图片验证码的作用就是,防止机器能在开抢0.1s 之内就买到票了,而普通用户要2~4s,如果机器不能快速识别图片验证码,那么所有人的反应速度都在4~10s 左右,这就公平了。那么我们有没有什么代替验证码的方案,也能让机器出局,大家都比较公平呢?接下来就是脑洞大开的时候:既然要公平,那么可不可以这样考虑,一批车票不一次性放出来,而是考虑在一个小时内分15次放出来,每次都是一个小的"抽售",在这 4min 内,只要申请一下,在放票的时候就可以参与抽奖,抽中了就获得了票,就有 45min 的时间锁定着票。在一个小时放票时间没抢的票就继续按照现有逻辑呗~大量买票的用户可能就是那么几个,有少数是经常出去玩的用户,那剩下的呢?有一些是黄牛,还有一些是去哪儿等等之类的网站吧(因为很多时候12306没票,在去哪儿就有),那么审查一些这样的用户,对其中黄牛可以采用严格的验证策略(这是一个烟雾弹,这些采用了严格的策略又不提示,这样可以让他们以为整个网站都很严格,可以为等多优化争取到时间)开放第三方接口,允许其他平台登录了查询(而不是抓取),允许登陆后预约票,这样可以减轻很多开发压力和舆论压力,现在这么多购票软件和购票浏览器,一下都给弄死了,这得引起多大的反弹,既然这样,那就给个接口引导这些 app 浏览器什么的转型呗,给个生路,大小都好过年。

飘逸的悟空
犹豫的麦片
2025-06-21 18:57:45

在惯有思维中,楼梯往往被建筑设计划到一起。但其实许多可以秒杀你想象力的楼梯设计,是都是室内设计师的杰作。

楼梯设计对建筑内部的装饰功能,

在欧洲古典时期已经可以找到明显的痕迹。无论是注重宏大结构的巴洛克风格设计,还是更加追求细节精致的洛可可设计风格,都在楼梯装饰上进行了华丽的处理。

现在,设计风格已经呈现百花齐放的格局,楼梯设计同样花样翻新,持续突破我们想象力的天际线。下面,我们就一起来看一组想象力报表的楼梯设计吧!

虽然楼梯口装点着带有东南亚风格的佛像,但整个楼梯造型更倾向于欧式风格。盘旋而上形成的柔美曲线,螺旋造型的楼梯扶手,都有古典欧式的奢华风范。但复杂的造型并非这个楼梯的最大亮点,作为半吊子的文化人,视觉上捕捉到的楼梯造型像一本本堆积起来的书籍,让楼梯华丽之外,带上文化底蕴。

这是一组造型上中规中矩的楼梯,但却具有浓厚的美式风情。从楼梯的颜色组合到线条运用,都与室内家具摆设和整体色彩形成呼应,在室内设计的风格营造中起到了重要的桥梁作用。

这组楼梯是典型的与建筑融合在一起的楼梯,但对楼梯口扶手的设计进行了细致的处理,从而强化了其室内装饰功能。在这里,强调的不仅仅是楼梯的使用特性,还充分利用了其造景功能。

这组楼梯打破了传统楼梯一步一台阶的固定思维。在较深的楼梯中嵌入了另一层,并使用了不同的材质。这种新的楼梯思路在丰富室内设计材质构成的同时,也让造型更加多样化。

这是一组概念化的楼梯,

对曲线的运用更加的彻底。和带有古典色彩的楼梯不同,它具有更加复杂的造型,且在色彩使用上更加大胆。虽然也运用了木质材料的天然纹理,但整体材料使用更加具有现代的金属感。

楼梯造景的方式如此之多,在常规曲线上的变形就不再让人感觉意外。这组楼梯的第一个亮点是曲线变形方面更加大胆,而这个变形的结果也别有深意,即一个欧洲古典时期的拱门形状。这让楼梯曲线有限的延伸,变得和室内的整体风格形成照应,维持了设计的完整性。

这组楼梯极富童趣而又大胆的造型让其具有明确的现代色彩。楼梯为我们打开一道通往未知世界的通道,这组不太长的楼梯可能带我们去到哪里?或许是种满绿植的天台,或许是一个温馨的阁楼,或许是一个充满趣味的儿童房。

在单层空间之中进行楼梯造型有很多局限性,一般认为木材和玻璃是最好的选择。木材质感温和,色彩天然,很容易和室内其他元素融合。玻璃材质透明,不会因为楼梯的设置而导致整个室内空间拘紧。

楼梯和阳台由于缺乏整体的支撑,可能会造成使用者心理上缺乏安全感。所以常规的思路是尽量让楼梯显得结实而又有安全感。玻璃楼梯虽然可以最大程度消除对室内空间的挤压,但也是一种比较有挑战的选择。

正如不同的人会对毕加索的绘画产生不同的感觉一样,不同的人也会对楼梯有不同的偏好。古典式楼梯一统天下的时代已经一去不复返,对于楼梯来说,设计多样化的大环境正在开启一个新时代。

这组楼梯的第一个亮点是曲线变形方面更加大胆,而这个变形的结果也别有深意,即一个欧洲古典时期的拱门形状。这让楼梯曲线有限的延伸,变得和室内的整体风格形成照应,维持了设计的完整性。

这组楼梯极富童趣而又大胆的造型让其具有明确的现代色彩。楼梯为我们打开一道通往未知世界的通道,这组不太长的楼梯可能带我们去到哪里?或许是种满绿植的天台,或许是一个温馨的阁楼,或许是一个充满趣味的儿童房。

在单层空间之中进行楼梯造型有很多局限性,一般认为木材和玻璃是最好的选择。木材质感温和,色彩天然,很容易和室内其他元素融合。玻璃材质透明,不会因为楼梯的设置而导致整个室内空间拘紧。

楼梯和阳台由于缺乏整体的支撑,可能会造成使用者心理上缺乏安全感。所以常规的思路是尽量让楼梯显得结实而又有安全感。玻璃楼梯虽然可以最大程度消除对室内空间的挤压,但也是一种比较有挑战的选择。

正如不同的人会对毕加索的绘画产生不同的感觉一样,不同的人也会对楼梯有不同的偏好。古典式楼梯一统天下的时代已经一去不复返,对于楼梯来说,设计多样化的大环境正在开启一个新时代。

繁荣的裙子
朴实的诺言
2025-06-21 18:57:45

大概思路吧:

秒杀系统的架构设计

秒杀系统,是典型的短时大量突发访问类问题。对这类问题,有三种优化性能的思路: 

写入内存而不是写入硬盘 

异步处理而不是同步处理 

分布式处理 

用上这三招,不论秒杀时负载多大,都能轻松应对。更好的是,Redis能够满足上述三点。因此,用Redis就能轻松实现秒杀系统。 

用我这个方案,无论是电商平台特价秒杀,12306火车票秒杀,都不是事:)

下面介绍一下为什么上述三种性能优化思路能够解决秒杀系统的性能问题:

写入内存而不是写入硬盘 

传统硬盘的读写性能是相当差的。SSD硬盘比传统硬盘快100倍。而内存又比SSD硬盘快10倍以上。因此,写入内存而不是写入硬盘,就能使系统的能力提升上千倍。也就是说,原来你的秒杀系统可能需要1000台服务器支撑,现在1台服务器就可以扛住了。 

你可能会有这样的疑问:写入内存而不是持久化,那么如果此时计算机宕机了,那么写入的数据不就全部丢失了吗?如果你就这么倒霉碰到服务器宕机,那你就没秒到了,有什么大不了? 

最后,后面真正处理秒杀订单时,我们会把信息持久化到硬盘中。因此不会丢失关键数据。 

Redis是一个缓存系统,数据写入内存后就返回给客户端了,能够支持这个特性。

异步处理而不是同步处理 

像秒杀这样短时大并发的系统,在性能负载上有一个明显的波峰和长期的波谷。为了应对相当短时间的大并发而准备大量服务器来应对,在经济上是相当不合算的。 

因此,对付秒杀类需求,就应该化同步为异步。用户请求写入内存后立刻返回。后台启动多个线程从内存池中异步读取数据,进行处理。如用户请求可能是1秒钟内进入的,系统实际处理完成可能花30分钟。那么一台服务器在异步情况下其处理能力大于同步情况下1800多倍! 

异步处理,通常用MQ(消息队列)来实现。Redis可以看作是一个高性能的MQ。因为它的数据读写都发生在内存中。

分布式处理 

好吧。也许你的客户很多,秒杀系统即使用了上面两招,还是捉襟见肘。没关系,我们还有大招:分布式处理。如果一台服务器撑不住秒杀系统,那么就多用几台服务器。10台不行,就上100台。分布式处理,就是把海量用户的请求分散到多个服务器上。一般使用hash实现均匀分布。 

这类系统在大数据云计算时代的今天已经有很多了。无非是用Paxos算法和Hash Ring实现的。 

Redis Cluster正是这样一个分布式的产品。

使用Redis实现描述系统

Redis和Redis Cluster(分布式版本),是一个分布式缓存系统。其支持多种数据结构,也支持MQ。Redis在性能上做了大量优化。因此使用Redis或者Redis Cluster就可以轻松实现一个强大的秒杀系统。 

基本上,你用Redis的这些命令就可以了。 

RPUSH key value 

插入秒杀请求

当插入的秒杀请求数达到上限时,停止所有后续插入。 

后台启动多个工作线程,使用 

LPOP key 

读取秒杀成功者的用户id,进行后续处理。 

或者使用LRANGE key start end命令读取秒杀成功者的用户id,进行后续处理。 

每完成一条秒杀记录的处理,就执行INCR key_num。一旦所有库存处理完毕,就结束该商品的本次秒杀,关闭工作线程,也不再接收秒杀请求。

要是还撑不住,该怎么办

也许你会说,我们的客户很多。即使部署了Redis Cluster,仍然撑不住。那该怎么办呢? 

记得某个伟人曾经说过:办法总比困难多!

下面,我们具体分析下,还有哪些情况会压垮我们架构在Redis(Cluster)上的秒杀系统。

脚本攻击

如现在有很多抢火车票的软件。它们会自动发起http请求。一个客户端一秒会发起很多次请求。如果有很多用户使用了这样的软件,就可能会直接把我们的交换机给压垮了。

这个问题其实属于网络问题的范畴,和我们的秒杀系统不在一个层面上。因此不应该由我们来解决。很多交换机都有防止一个源IP发起过多请求的功能。开源软件也有不少能实现这点。如linux上的TC可以控制。流行的Web服务器Nginx(它也可以看做是一个七层软交换机)也可以通过配置做到这一点。一个IP,一秒钟我就允许你访问我2次,其他软件包直接给你丢了,你还能压垮我吗?

交换机撑不住了

可能你们的客户并发访问量实在太大了,交换机都撑不住了。 

这也有办法。我们可以用多个交换机为我们的秒杀系统服务。 

原理就是DNS可以对一个域名返回多个IP,并且对不同的源IP,同一个域名返回不同的IP。如网通用户访问,就返回一个网通机房的IP;电信用户访问,就返回一个电信机房的IP。也就是用CDN了! 

我们可以部署多台交换机为不同的用户服务。 用户通过这些交换机访问后面数据中心的Redis Cluster进行秒杀作业。

总结

有了Redis Cluster的帮助,做个支持海量用户的秒杀系统其实So Easy! 

这里介绍的方案虽然是针对秒杀系统的,但其背后的原理对其他高并发系统一样有效。 

最后,我们再重温一下高性能系统的优化原则: 

写入内存而不是写入硬盘 

异步处理而不是同步处理 

分布式处理

迷路的大雁
高兴的大米
2025-06-21 18:57:45
首先罗列一些常见的功能和业务,这些通常会作为软件测试常见的用例设计考题。

① 注册、登陆;

② 搜索商品、店铺;

③ 商品列表浏览;

④ 商品详情浏览;

⑤ 加入购物车;

⑥ 支付功能;

⑦ 评价功能。

以上仅是基本的功能,用例的设计要遵从基本功能的目的,结合软件测试的方法,逐一设计。

下面举个注册的例子讲解。

对于注册的动作,测试的观点应该包含以下内容:

· 注册时不同注册数据的组合,特殊字符,用户名规则等的确认;

· 注册按钮点下后,是否可以成功跳转到成功或失败页面;

· 注册信息发出后,服务器的响应时间,即性能指标的测试;

· 注册动作完成后,使用相同数据再次注册时,是否会提示失败;

· 另外还要注意注册页面上的一些页面元素是否符合需求说明书的要求。

以上仅是建议,还有很多角度可以思考,可以设计。希望对你有所帮助。

我本身也是做软件行业的,测试环节必不可少,若有不明,欢迎探讨。