千万级秒杀项目实战
一、设计思路
1. 设计分析
- 用户:量大,正常用户,恶意用户(数据清洗)
- 地区:全国范围内各地区都要访问到(cdn加速)
- 业务流程:前台(用户能看到的部分)后台(商家或者管理者使用)
2. 设计分层
- 第一层:商品展示层(负责对应商品的展示)
- 第二层:用户登记层(用户登记相关信息,秒杀准备)
- 第三次:数据接入(将用户的信息接入到数据库或者处理层)
- 第四层:数据处理层(接入层数据没有问题,存入处理层)
3. 导图
二、代码分析
1. 秒杀第一层(展示页面)
1)页面优化
页面
图片
- css
- js
- 压缩
2)cnd网络加速
- 阿里云cdn(推荐)–oss开放存储
- 解决全国各地访问不均衡的问题
- 内容刷新
3)隐藏跳转页面(重点)
修改页面信息
- 修改js
- 修改页面
双页面
展示页面
- 倒计时
- 1、用服务器时间(推荐设置成东9区)
- 2、考虑网络传输耗时(不是很明显,但是需要考虑)
- 3、获取时间可以冲ajax响应头中获取(通过getResponsetHeader(“Date”)来获取,服务器不需要写时间生成脚本)
- 倒计时实现方案
- 1、原则:尽量减少服务器请求
- 2、处理方式
- 刷新就获取服务器时间,然后自己累加
- 获取服务器时间
- js实现递减效果
- 倒计时
购买页面
1
2
3
4
5
6
7
8//第一步--删除文件
$file_path = 'a.txt';
$f = file_exists($file_path)&&unlink($file_path);
//第二部--生成自己需要的文件
$file_path = 'b.html';
$myfile = fopen($file_path,'w');
$txt = "<h1>大家好</h1>";
fwrite($myfile,$txt);
4)端口/最大连接数
- 关闭没用的端口
- 最大连接数设置
- 内存
- cpu
- 默认150个设置512个
5)电脑性能监控
- cpu
- 内存
- 网络
- 硬盘
- 版本推荐
- php7
- apache2.4
- 推荐理由
- 新品
- 缺点:很多扩展不全
- 服务器配置
- 1、选择unbuntu 14.04
- 2、安装ssh
- 3、apt-get update
- 4、tasksel install lmap-server
6)特点
- 应对高并发/高可用(主要cnd–阿里是6台机器回源,所有我们只要抗住6台机器请求就可以了)
7)构想
- 展示状态
- 三种
- 秒杀等待倒计时页面
- 秒杀进行中、秒杀按钮可用状态
- 秒杀结束提示页面
- 秒杀等待倒计时页面
- 技术难点
- 秒杀等待页面与秒杀按钮可用状态页面,切换的时候,不至于让秒杀登记的地址提前曝光!
- 方案:用linux定时任务crontab 执行shell脚本,进行文件的替换
- 秒杀等待页面与秒杀按钮可用状态页面,切换的时候,不至于让秒杀登记的地址提前曝光!
- 三种
- 高并发/高可用
- 技术关键点
- 高可用
- 双活
- 云解析(推荐+负载均衡)
- 高并发
- 负载均衡
- cdn加速
- 单台调优
- 最大连接数
- 可靠性能
- 高可用
- 结合当前页面的思考
- 页面特点
- 纯静态:html标签/css属性/js
- 如果是纯静态:高并发–cnd加速
- 页面特点
- 技术关键点
8)具体实施
- 页面
- 1.商品展示页
- 2.商品秒杀进行中
- 3.秒杀结束
- 知识点
- 切换
- 1-2切换
- a. linux cron定时任务
- b. shell脚本知识
- 2-3切换
- .php文件
- 1-2切换
- 秒杀倒计时
- js实现
- 服务器部署
- 切换
2.秒杀第二层(用户登记)
1)目的
- 登记用户信息
- 简单的小白过滤
- 肉鸡方案
- 控制多台计算机同时抢
- ajax数据发送
- 手机号/验证码之类
- 简单的小白过滤
2)知识点
- 静态页面/服务器(同第一层)
- 简单的数据验证
- ajax跨域
3)代码实现
3.秒杀数据接入层
1)任务
数据校验
存入队列
检测订单商品数量
2)知识点
数据校验
- ajax跨域安全
- 数据源验证
- 类似token数据校验
- 加密算法(类似序列号)
- ajax跨域安全
队列
why——高并发流浪数据插入
- 排队
- 微观角度 —— 其实从硬件IP可以排序!单一排序
- linux底层驱动,也是从缓存池中,获取数据
- 去重
- 排队
如何选择
- 多次任务存储
- 队列
- 链表
- 数组
- 堆栈
- nosql
- memcache
- 简单
- php控制逻辑+memcache控制数据
- redis
- php引擎
- PRdies:纯php完成
- phpredis:c扩展
- 命令选择
- 列表 ——无自动去重
- 集合
- 快速
- 随机无序
- 有序集合
- 过期时间
- mysql —— 消息队列插件
- PRdies:纯php完成
- 队列
- 多次任务存储
代码实现
- test_redis.php
- 本地
- 阿里
- 效果展示——流程演示
- 类封装——兼容本地以及远程的类封装
- 最终效果封装——基于阿里
- test_redis.php
- 商品数量检测
- 关键点:
- redis封装
- 序列号生成
4.秒杀第四层
1)数据处理
- 任务——转存nosql数据到mysql
- 知识点——无
三、具体代码实现
1.第一层代码实现
1)关键点:
倒计时:
css——背景图足够大,将倒计时固定
js
- 倒计时js
根据剩余秒数显示时间
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17function getNewSyTime(sec){
var s = sec % 60;
sec = (sec - s)/60;//min
var m - sec % 60;
sec = (sec - m)/60;//hour
var h = sec % 24;
var d = (sec - h) / 24;//day
var syTimeStr = "";
if(d > 0){
syTimeStr += d.toString() + "天";
}
syTimeStr = ("0"+h.toString()).substr(-2)+"时"
+("0"+m.toString()).substr(-2)+"分"
+("0"+s.toString()).substr(-2)+"秒;
return syTimeStr;
}
- 秒杀结束替换脚本
1. 秒杀替换脚本
1
2
3
4
#!/user/bin/env bash
date>>/root/456.txt
rm -rf '/alidata/www/deault/index.html'
cp '/alidata/www/deault/index_sale.html' '/alidata/www/deault/index.html'
2. 服务器定时任务
1
0 12 * * * root /bin/51miao.sh
3. php代码实现
1
2
3
4
5
6
7
8
9
10
//第一步删除文件
$file_path = 'index.html';
$f = file_exists($file_path)&&unlink($file_path);
//第二步:生成自己需要的文件
$file_path = 'index.html';
$myfile = fopen($file_path,"w");
//获取文件内容
$file_path = 'index_over.html';
$txt = file_get_contents(file_path);
fwrite($myfile,$txt);
2.第二层
1)js
- 对用户名手机号进行判断——value值
- value值序列号加密
- 正则手机号判断
- jsonp发送后台验证通过,则登记记录
3.第三层
- php
- 创建token
- 检验token
- 给1,2,4层发送通知
- redis插入数值
- 插入数值 flag+1
- 安全过滤
4.第四层
- redis获取数据插入到mysql中