做设计素材在哪个网站,成都网站建设名录,北京海淀区网站建设,免费建立网页秒杀活动可以说在互联网上随处可见#xff0c;从12306抢票#xff0c;到聚划算抢购#xff0c;我们生活的方方面面都可以看到秒杀的身影。
作者#xff1a;IT技术管理那些事儿
秒杀活动可以说在互联网上随处可见#xff0c;从12306抢票#xff0c;到聚划算抢购#xf…秒杀活动可以说在互联网上随处可见从12306抢票到聚划算抢购我们生活的方方面面都可以看到秒杀的身影。
作者IT技术管理那些事儿
秒杀活动可以说在互联网上随处可见从12306抢票到聚划算抢购我们生活的方方面面都可以看到秒杀的身影。 秒杀的架构设计也是对于一个架构师架构设计能力的一次考验。本文的目的并不在于提供一个可以直接落地的设计方案而是意在提供一个简单的方法一个思路使大家能够对于秒杀背后的一些设计有更感性的认识, 并且可以自己亲自动手实践一下。
所有的配置及源码都在本文最后的GitHub repository中可以找到。
首先先简单介绍下本文中会涉及到的一些组件如下图所示 JMeter用JMeter来模拟秒杀活动中大量并发的用户请求
Seckill Service基于Nodejs使用Express实现的秒杀service图中的步骤234都是在这个service中处理的
Redis一个Redis的docker container在其中保存一个名为counter的数据来表示当前剩余的库存大小
Kafka: 一个Kafka的docker container其实这里还有一个zookeeper的docker containerKafka用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次并发请求。 在这个Thread Group下新建一个Http Request的Sampler并命名为Seckill按下图配置host nameport numberhttp request method以及request path 2 . 安装RedisKafka, Zookeeper和MySQL
为了方便搭建环境这几个组件会以docker container的形式启动。在此之前需要去Docker官网下载并安装Docker EngineDocker Machine和Docker Compose。如果是在Windows或者Mac上Docker官网提供Docker For Windows/Docker For Mac安装程序可以很方便的把这3个组件安装好。
3 . 编写Docker Compose文件
创建一个Seckill项目文件夹新建一个docker-compose.yml文件内容如下 配置文件中一共配置了4个services对应4个docker container分别是zookeeperkafkaredis以及mysql。这里有两个地方需要设置成你实际环境的值一个是kafka配置下面的KAFKA_ADVERTISED_HOST_NAME字段这个需要设置成本地机器的IP。另一个是MYSQL配置下面的MYSQL_ROOT_PASSWORD你可以设置成你想要的任何值。
创建好这个文件之后就可以去命令行项目根目录中执行docker-compose updocker engine就会把上面配置的这4个组件全部启动起来。
注意在启动完之后需要去Kafka容器中创建一个名为CAR_NUMBER的topic去Redis容器中创建一个名为counter的计数器(设置值为100代表库存初始值为100)去MySQL容器中创建一个名为seckill的数据表(包含一个自增长的id自段和一个timestamp格式的date字段)。
代码片段
1 . Seckill Service 第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 这里的代码就比较简单了会初始化一个kafka consumer监听CAR_NUMBER topic对于新获取的消息会去MySQL的seckill表里插入一条记录。
操作步骤
启动docker container启动Seckill_Service启动seckill_kafka_consumer启动JMeter发送2000个并发请求
结果
JMeter request results Redis counter field MySQL seckill table 可以看到最后redis中的counter变成0seckill数据表中会插入100条记录没有发生超卖或者少卖的情况。当然在实际生产环境场景中还有许多其它需要考虑的地方希望此文可以起到一个抛砖引玉的作用帮助大家更好的理解秒杀场景。
阅读目录置顶)(长期更新计算机领域知识
阅读目录置顶)(长期更新计算机领域知识
阅读目录置顶)(长期科技领域知识
歌谣带你看java面试题