秒杀/抢购系统设计优化

12306抢票,票是有限的,库存一份,瞬时流量非常多,都读相同的库存,读写冲突,锁非常严重;
小米手机每周二的秒杀,可能手机只有1万部,但瞬时进入的流量可能是几百几千万;
这是秒杀业务难的地方。那我们怎么优化秒杀系统呢?

一、难点

(1)高并发
用户在秒杀开始前,通过不停刷新浏览器页面以保证不会错过秒杀,这些请求如果按照一般的网站应用架构,访问应用服务器、连接数据库,会对应用服务器和数据库服务器造成负载压力。
(2)超卖
由于库存并发更新的问题,导致在实际库存已经不足的情况下,库存依然在减,导致卖家的商品卖得件数超过秒杀的预期。

二、架构

常见的站点架构基本是这样的:
(1)浏览器端,最上层,会执行到一些JS代码
(2)站点层,这一层会访问后端数据,拼HTML页面返回给浏览器
(3)服务层,向上游屏蔽底层数据细节,提供数据访问
(4)数据层,最终的库存是存在这里的

三、思路

(1)将请求尽量拦截在上游:传统秒杀系统之所以挂,请求都压倒了后端数据层,数据库读写锁冲突严重,导致响应慢,下单基本不能成功
(2)利用缓存:这是一个典型的读多写少的应用场景,非常适合使用缓存

四、解决方案

(1)浏览器层请求拦截
1.产品层面,用户点击“查询”或“购票”后,按钮置灰,禁止用户重复提交请求
2.js层面,限制用户在n秒之内只能提交一次请求
(2)站点层请求拦截与页面缓存
1.静态化,将活动页面上的所有可以静态的元素全部静态化,并尽量减少动态元素
2.限频率,同一个UID,限制访问频率,做页面缓存,n秒内到达站点层的请求,均返回同一页面
(3)服务层请求拦截与数据缓存
1.对于写请求,将所有写请求在缓存(Redis或Memcached)中,做请求单队列排队,每次只透过有限的写请求异步写入到数据层,如果均成功再放下一批,如果库存不够则队列里的写请求全部返回“已售完”
2.对于读请求,用Redis或Memcached
缓存写性能和读性能都远高于MySQL,只有非常少的写和读缓存的请求会透到数据层去
(4)数据层
1.尝试扣减库存,扣减库存成功才会进行下单逻辑(由于MySQL事务的特性,不可能完全避免超卖)

UPDATE table_name SET n=n-1 WHERE n>1;

2.扣减库存后进行检查,保证减完不能等于负数
查看更多:
开发一个微信小程序实例教程
HTTP协议整理
PHP安全之Web攻击
MySQL优化
Linux下常见的IO模型
参考资料:
https://my.oschina.net/xianggao/blog/524943
http://www.infoq.com/cn/articles/flash-deal-architecture-optimization

时间: 2024-08-18 05:07:52

秒杀/抢购系统设计优化的相关文章

Java秒杀系统方案优化---高性能高并发实战

Java秒杀系统方案优化---高性能高并发实战网盘地址:https://pan.baidu.com/s/1htNv2zq 密码: ssyt备用地址(腾讯微云):https://share.weiyun.com/889808c023b6e9d9f504399a5b07276f 密码:1WaUHB 亮眼的!高并发秒杀系统核心技术 课程以"秒杀"场景为例,但技术都是通用的,举一反三,方得始终应对大并发:多层次多粒度缓存+消息队列异步+服务器分布式部署 专业的压测工具:有依有据,鉴证系统的优化

redis使用watch完成秒杀抢购功能(转)

redis使用watch完成秒杀抢购功能: 使用redis中两个key完成秒杀抢购功能,mywatchkey用于存储抢购数量和mywatchlist用户存储抢购列表. 它的优点如下: 1. 首先选用内存数据库来抢购速度极快. 2. 速度快并发自然没不是问题. 3. 使用悲观锁,会迅速增加系统资源. 4. 比队列强的多,队列会使你的内存数据库资源瞬间爆棚. 5. 使用乐观锁,达到综合需求. 我觉得以下代码肯定是你想要的. [php] view plain copy print? <?php hea

58沈剑:秒杀系统架构优化思路

有个兄弟分享秒杀系统的优化,其观点有些赞同,大部分观点却并不同意,结合自己的经验,谈谈自己的一些看法. 一.为什么难 秒杀系统难做的原因:库存只有一份,所有人会在集中的时间读和写这些数据. 例如小米手机每周二的秒杀,可能手机只有1万部,但瞬时进入的流量可能是几百几千万. 又例如12306抢票,亦与秒杀类似,瞬时流量更甚. 二.常见架构 流量到了亿级别,常见站点架构如上: 1)浏览器端,最上层,会执行到一些JS代码 2)站点层,这一层会访问后端数据,拼html页面返回给浏览器 3)服务层,向上游屏

redis使用watch完成秒杀抢购功能:

使用redis中两个key完成秒杀抢购功能,mywatchkey用于存储抢购数量和mywatchlist用户存储抢购列表. 它的优点如下: 1. 首先选用内存数据库来抢购速度极快. 2. 速度快并发自然没不是问题. 3. 使用悲观锁,会迅速增加系统资源. 4. 比队列强的多,队列会使你的内存数据库资源瞬间爆棚. 5. 使用乐观锁,达到综合需求. 我觉得以下代码肯定是你想要的. <?php header("content-type:text/html;charset=utf-8")

zookeeper实现商品秒杀抢购

package com.test; import java.io.IOException; import java.util.List; import java.util.concurrent.CyclicBarrier; import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.WatchedEvent; import org.

微信红包系统设计 &amp; 优化

微信红包系统设计 & 优化 浏览次数:151次 腾讯大讲堂 2015年04月02日 字号: 大 中 小 分享到:QQ空间新浪微博腾讯微博人人网豆瓣网开心网更多0 编者按:经过2014年一年的酝酿,2015微信红包总量创下历史新高,峰值1400万次/秒,8.1亿次每分钟,微信红包收发达10.1亿次,系统整体运行平稳, 在这里我分享下微信红包背后的技术. 讲师:jeri 核心功能&目标 首先,了解下微信红包的4个逻辑:摇/发/抢/拆.看似简单,实现可不简单再review下微信红包要实现目标:

一句JS帮你秒杀,抢购

刚刚看到一哥们儿写了一篇jquery插件之倒计时-团购秒杀  突然想到一个主意就是如题 想法:现在很多地方有类似秒杀,抢购等拼手速,网速的(其实就是服务器渣,如:某米),  很多人就想到可以写个客户端,开启一直刷, 我觉得应该可以直接通过js代码来执行. 下面进入正题 如果大家了解并会使用各浏览器的开发者工具就非常好办咯, 本人习惯用chrome,本例也就用chrome F12打开开发者工具 在控制台直接输入js带是可以执行的,所以大家应该有头绪了 测试: 写一个测试页面 <div> <

redis使用watch完成秒杀抢购功能

redis使用watch完成秒杀抢购功能: 使用redis中两个key完成秒杀抢购功能,mywatchkey用于存储抢购数量和mywatchlist用户存储抢购列表. 它的优点如下: 1. 首先选用内存数据库来抢购速度极快. 2. 速度快并发自然没不是问题. 3. 使用悲观锁,会迅速增加系统资源. 4. 比队列强的多,队列会使你的内存数据库资源瞬间爆棚. 5. 使用乐观锁,达到综合需求. 我觉得以下代码肯定是你想要的. [php] view plain copy print? <?php hea

Java秒杀系统方案优化视频教程 Java高性能高并发实战

第1章 课程介绍及项目框架搭建 技术选型思路分析,基于Maven的Spring-Boot工程框架的搭建,集成Thymeleaf,集成Mybatis,安装Redis,集成Redis等等. 第2章 实现用户登录以及分布式session功能 实现用户登录功能,实现密码两次MD5入库以及分布式Session.一则熟悉SpringBoot开发模式和该选型下的技术衔接,二则为后面的秒杀功能提供必备的用户信息. 第3章 秒杀功能开发及管理后台 实现秒杀的交互设计和秒杀功能的前端和后台实现,随着后期优化策略,秒