第一百三十五期:如何模拟一次阿里双11秒杀场景的实现?程序员必看

秒杀活动可以说在互联网上随处可见,从12306抢票,到聚划算抢购,我们生活的方方面面都可以看到秒杀的身影。

作者:IT技术管理那些事儿

秒杀活动可以说在互联网上随处可见,从12306抢票,到聚划算抢购,我们生活的方方面面都可以看到秒杀的身影。

秒杀的架构设计也是对于一个架构师架构设计能力的一次考验。本文的目的并不在于提供一个可以直接落地的设计方案,而是意在提供一个简单的方法,一个思路,使大家能够对于秒杀背后的一些设计有更感性的认识, 并且可以自己亲自动手实践一下。

所有的配置及源码都在本文最后的GitHub repository中可以找到。

首先,先简单介绍下本文中会涉及到的一些组件,如下图所示:

如何模拟一次阿里双11秒杀场景的实现?程序员必看

JMeter:用JMeter来模拟秒杀活动中大量并发的用户请求

Seckill Service:基于Nodejs使用Express实现的秒杀service,图中的步骤2,3,4都是在这个service中处理的

Redis:一个Redis的docker container,在其中保存一个名为counter的数据来表示当前剩余的库存大小

Kafka: 一个Kafka的docker container,其实这里还有一个zookeeper的docker container,Kafka用zookeeper来存放一些元数据,在程序中并没有涉及到,所以也就不单独列出来说了。Seckill service在更新完Redis之后,会发送一条消息给Kafka表示一次成功的秒杀

Seckill Kafka Consumer: 基于Nodejs的Kafka consumer,会从Kafka中去获取秒杀成功的消息,处理并且存储到MySQL中

MySQL:一个MySQL的docker container,最终秒杀成功的请求都会对应着数据库表中的一条记录

环境搭建

1 . 安装JMeter

从官网下载一个JMeter的binary包,执行bin目录下的jmeter即可启动,启动后如下图新建一个名为Seckill的Thread Group,并且设置在5s内发起2000次并发请求。

如何模拟一次阿里双11秒杀场景的实现?程序员必看

在这个Thread Group下新建一个Http Request的Sampler并命名为Seckill,按下图配置host name,port number,http request method以及request path

如何模拟一次阿里双11秒杀场景的实现?程序员必看

2 . 安装Redis,Kafka, Zookeeper和MySQL

为了方便搭建环境,这几个组件会以docker container的形式启动。在此之前需要去Docker官网下载并安装Docker Engine,Docker Machine和Docker Compose。如果是在Windows或者Mac上,Docker官网提供Docker For Windows/Docker For Mac安装程序,可以很方便的把这3个组件安装好。

3 . 编写Docker Compose文件

创建一个Seckill项目文件夹,新建一个docker-compose.yml文件,内容如下:

如何模拟一次阿里双11秒杀场景的实现?程序员必看

配置文件中一共配置了4个services对应4个docker container,分别是zookeeper,kafka,redis以及mysql。这里有两个地方需要设置成你实际环境的值,一个是kafka配置下面的KAFKA_ADVERTISED_HOST_NAME字段,这个需要设置成本地机器的IP。另一个是MYSQL配置下面的MYSQL_ROOT_PASSWORD,你可以设置成你想要的任何值。

创建好这个文件之后,就可以去命令行项目根目录中执行docker-compose up,docker engine就会把上面配置的这4个组件全部启动起来。

注意:在启动完之后,需要去Kafka容器中创建一个名为CAR_NUMBER的topic,去Redis容器中创建一个名为counter的计数器(设置值为100,代表库存初始值为100),去MySQL容器中创建一个名为seckill的数据表(包含一个自增长的id自段和一个timestamp格式的date字段)。

代码片段

1 . Seckill Service

如何模拟一次阿里双11秒杀场景的实现?程序员必看

如何模拟一次阿里双11秒杀场景的实现?程序员必看

  • 第1-8行,引入了程序需要用到的对象,nodejs的mvc框架express, redis, kafka等
  • 第10行,利用express提供的方法暴露出一个path为/seckill的POST方法
  • 第12行,定义了一个方法,在54行会调用
  • 第13-22行,新建了一个redis client并且监听error事件
  • 第23行,这行代码非常关键,它的作用是让redis cilent监视redis中的counter值,之后会启动一个事务,如果在事务提交的时候发现有其它client修改了counter值的话,就会放弃这个事务。
  • 第24行,通过redis client的异步方法获取counter的值,因为redis的get操作是原子的,所以在这里不用担心有并发读写的问题。
  • 第25-28行,判断返回的库存值是否大于0,如果大于0,通过client.multi()启动一个事务,通过decr()方法将counter值减1,最后通过exec()方法提交事务;如果小于0,则执行第47行,打印卖完了并且关闭redis client。
  • 第29-46行,这里我们看一下multi.exec()中的这个回调方法。在前面我们已经使用watch对counter进行了监视。如果在事务提交过程中有其它client修改了counter值的话,回调方法中的replies参数就会是null,可以看到第29-31行,程序会打印“可能有冲突”并且再次调用fn方法重试。

如果replies的值不为null,就会使用kafka的producer发送一条message到CAR_NUMBER topic。

2 . seckill_kafka_consumer

如何模拟一次阿里双11秒杀场景的实现?程序员必看

这里的代码就比较简单了,会初始化一个kafka consumer监听CAR_NUMBER topic,对于新获取的消息会去MySQL的seckill表里插入一条记录。

操作步骤

  • 启动docker container
  • 启动Seckill_Service
  • 启动seckill_kafka_consumer
  • 启动JMeter发送2000个并发请求

结果

JMeter request results

如何模拟一次阿里双11秒杀场景的实现?程序员必看

Redis counter field

如何模拟一次阿里双11秒杀场景的实现?程序员必看

MySQL seckill table

如何模拟一次阿里双11秒杀场景的实现?程序员必看

可以看到,最后redis中的counter变成0,seckill数据表中会插入100条记录,没有发生超卖或者少卖的情况。当然在实际生产环境场景中,还有许多其它需要考虑的地方,希望此文可以起到一个抛砖引玉的作用,帮助大家更好的理解秒杀场景。

阅读目录(置顶)(长期更新计算机领域知识)

阅读目录(置顶)(长期更新计算机领域知识)

阅读目录(置顶)(长期科技领域知识)

歌谣带你看java面试题

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/423992.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

什么是“中台”

“中台”概念起源于军事范畴,其精髓是“大平台支撑精兵作战”,即前线小团队作战,后方建设强大的火力平台和信息化指挥系统机动支撑。企业中台战略随着Supercell、阿里巴巴、腾讯、华为等国内外科技巨头的应用和宣传,近年来在国内被…

新编标准日本语 第26课 课文

自転車に2人で乗るのは危ないです1.自転車に2人で乗るのは危ないです2.手紙を出すのを忘れました3.明日の朝は大雨になるでしょう4.森さんは今日会社を休むかもしれません李さんは絵をかくのが好きですね。ええ、大好きです。でも、あまり上手ではありませんよ。吉田さんが転勤…

pytorch矩阵相乘与点乘

1pytorch矩阵相乘与点乘 torch.mul(a, b) 矩阵点乘 矩阵点乘要求两个矩阵维度符合一定要求 a的形状是(x,y) b的形状是(x,y),那么得到(x,y)形状的矩阵b的形状是(x,1),那么得到(x,y)形状的矩阵,从2到y列的值与第一列的值相y1,b的形…

第一百三十六期:详细讲解 Redis 的两种安装部署方式

Redis 是一款比较常用的 NoSQL 数据库,我们通常使用 Redis 来做缓存,这是一篇关于 Redis 安装的文章,所以不会涉及到 Redis 的高级特性和使用场景,Redis 能够兼容绝大部分的 POSIX 系统。 作者:平头哥 Redis 是一款比…

docker 查询或获取私有仓库(registry)中的镜像

docker 查询或获取私有仓库(registry)中的镜像,使用 docker search 192.168.1.8:5000 命令经测试不好使。 解决: 1、获取仓库类的镜像: [rootshanghai docker]# curl -XGET http://192.168.1.8:5000/v2/_catalog {"repositories":[…

知识图谱需要解决的问题

1 知识图谱应用场景 1、数据可视化 2、基于图谱的问答系统 3、基于图谱的关系推理 4、便捷的关系查询,给模型提供更多数据特征 2 知识图谱的构建 非结构化数据源中的实体识别:一般来说是一个sequence labeling的任务。 非结构化数据源中的关系抽取&am…

spring mvc学习(43):处理静态资源

上图是目录结构&#xff0c;本节是有问同学的&#xff0c;当好好总结 pom.xml <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation"http://maven.apache.org/POM/4.0.…

每天学一点flash(14) as3.0 处理xml (官方)

把官方的教程贴上来&#xff0c;我觉得还是不错的说得很有条理&#xff1a; 转载于:https://www.cnblogs.com/guoyiqi/archive/2007/08/21/2069585.html

pytorch中的sum

pytorch的sum怎么那么烦人呢&#xff1f;我怎么知道应该给哪个维度做加和呢。 如果 x tensor([[0.5946, 0.3530, 0.2231], [0.7467, 0.2139, 0.4841], [0.6990, 0.6151, 0.1369], [0.1062, 0.5951, 0.7555], [0.7811, 0.2932, 0.2963]]) 那么我想 x.sum(dim1)&#xff0c;第0个…

oracle-SYSTEM表空间的备份与恢复

oracle-SYSTEM表空间的备份与恢复 这一篇在介绍备份及恢复数据文件的方法时&#xff0c;以备份和重做日志&#xff08;包括归档日志和在线日志&#xff09;没有丢失为前提 所谓关键数据文件&#xff1a;system表空间的数据文件与参数undo_tablespace指向的自动撤销表空间的数据…

Spring AOP学习笔记

需明确的几个概念: l 通知(Advice)&#xff1a;用于告知系统将有哪些新的行为。l 切入点(Pointcut):定义了通知应该在应用到那些连接点。l 目标对象(Target)&#xff1a;被通知的对象。l 代理(Proxy)&#xff1a;将通知应用到目标对象后创建的…

spring mvc学习(44):springMVC运行原理

springMVC处理请求的流程 SpringMVC的工作原理图&#xff1a; SpringMVC流程 1、 用户发送请求至前端控制器DispatcherServlet。 2、 DispatcherServlet收到请求调用HandlerMapping处理器映射器。 3、 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找)&…

pytorch中的squeeze和unsqueeze

squeeze&#xff1a;压缩&#xff0c;要减少维度。 unsqueeze&#xff1a;解压缩&#xff0c;要增加维度。 torch.squeeze(input)&#xff0c;那么会把input中所有维度长度为1的维度去掉。 torch.squeeze(input,dim1)&#xff0c;那么在给定dim的情况下&#xff0c;就只去掉dim…

一段按页自动滚动文字或图片的Js代码

<div iddemo style"position:relative;padding:10px;border:solid 1px green;BACKGROUND: #ffffff; OVERFLOW: hidden; WIDTH: 510px; COLOR: red; HEIGHT: 100px"><div id"demo1"style"position:relative;">您的图片或者要滚动的内…

spring mvc学习(45):springMVC的三大组件

SpringMvc框架结构图 处理器映射器&#xff1a;用户请求路径到Controller方法的映射处理器适配器&#xff1a;根据handler(controlelr类&#xff09;的开发方式&#xff08;注解开发/其他开发&#xff09; 方式的不同区寻找不同的处理器适配器 视图解析器&#xff1a;根据hand…

[NLP-CNN] Convolutional Neural Networks for Sentence Classification -2014-EMNLP

1. Overview 本文将CNN用于句子分类任务 (1) 使用静态vector CNN即可取得很好的效果&#xff1b;> 这表明预训练的vector是universal的特征提取器&#xff0c;可以被用于多种分类任务中。 (2) 根据特定任务进行fine-tuning 的vector CNN 取得了更好的效果。 (3) 改进模型架…

知识图谱中三元组抽取

内容来自七月算法nlp课程。 这是要解决知识图谱中的其中一个问题&#xff1a;从非结构文本中抽取三元组。 要解决这个问题&#xff0c;总体思路有通过模板抽取、通过模型抽取。 三元组工业界一般都存储在neo4j中&#xff0c;学术界会采用RDF形式存储。 1结构化数据抽取 定义…

spring mvc学习(46):自定义配置类

上图是目录结构&#xff0c;本节是有问同学的&#xff0c;当好好总结 pom.xml <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation"http://maven.apache.org/POM/4.0.…

图谱问答-理解query

内容来自七月算法nlp课程。 图谱问题是用户输入一句话&#xff0c;系统返回这句话的答案。这里分多种情况。例如根据实体和关系查询尾实体&#xff0c;或者根据实体查询关系&#xff0c;甚至还会出现多跳的情况&#xff0c;不同的情况采用的方法略有不同。 文章目录1 根据实体…

python NoSuchElementException异常处理

python爬虫程序&#xff0c;用Selenium模拟点击时报出异常NoSuchElementException&#xff1a;Unable to locate...... 出错原因&#xff1a;https://www.cnblogs.com/cttcarrotsgarden/p/11210883.html 异常通常发生于找不到目标元素的时候 导入Selenium的NoSuchElementExcept…