日拱一卒无有尽,功不唐捐终入海

php秒杀系统架构设计实例

解决方案 Sam 724℃ 0评论

① 对现有网站业务的冲击,如果秒杀程序部署到现有的服务器上,可能导致整个网站瘫痪

解决方法
把秒杀活动部署到单独的机子上,并且用单独的域名

② 高并发,用户在秒杀活动开始之前会不停的刷新页面,如果用php脚本连接数据库的方式,会对服务器的压力较大
解决方法
使用静态页面,并且使用cdn缓存,解决带宽压力大等问题

③ 避免用户直接通过下单连接下单
解决方法
带个随机参数,在秒杀开始之前才能得到

④ 控制抢购按钮,页面设计为静态页面并且使用了cdn缓存,如何点亮抢购按钮
解决方法
js文件后面带个随机版本号,这样不会被cdn缓存,直接到达服务器,来控制按钮点亮,这个js文件要小,不然会对服务器带来带宽的压力

⑤ 抢购程序设计,如果直接使用数据库事务,数据库压力太大
解决方法
使用redis或memcache等内存缓存,速度快还能解决超卖等问题

抢购静态页面代码

使用二级域名,用cdn缓存html页面,css,js,图片等
nocdn.js生成脚本

主要生成nocdn.js文件的内容,用linux crontab设置定时脚本
内容主要是显示秒杀的按钮,生成随机的参数,生成ajax的提交脚本

抢购代码

主要是redis的watch,如果执行事务发现mywatchkey变动过就执行事务失败,redis事务失败不会回滚,代码测试过
用ab测试没有超卖的问题

上面的代码有个问题,就是会出现少卖的问题
下面来解释一下原因,

时间 客户端 A 客户端 B
T1 WATCH name
T2 MULTI
T3 SET name peter
T4 SET name john
T5 EXEC

在时间 T4 ,客户端 B 修改了 name 键的值, 当客户端 A 在 T5 执行 EXEC 时,Redis 会发现 name 这个被监视的键已经被修改, 因此客户端 A 的事务不会被执行,而是直接返回失败。
所以结果是name等于john

上面的代码sleep(5)可以测试,就会发现出现少买的问题,我测试去除sleep之后不会出现这个问题

转载请注明:PHP笔记 » php秒杀系统架构设计实例

喜欢 (0)
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)