秒杀程序基本思路

做秒杀活动的时候,最难应付的应该是在开始秒杀的那一瞬间,如何解决成千上万个用户同时造成的高并发问题。只有较好地解决这些问题,才能让你的程序 在这么多秒杀用户中,找到真正的秒杀得主。虽然之前做的秒杀活动最多的并发数也就在几十个,不过,还是积累了一些经验,在此记录并分享出来,希望对其他开 发秒杀产品的开发者有所帮助。

一、mysql连接数

最开始,我没有对mysql的并发连接数做调整,结果某一次秒杀用户多的时候,就提示mysql连接数过多,拒绝连接的提示。原来,mysql默认 的并发连接数是100,这对于秒杀瞬间来说,是远远不够的。可以通过在/etc/my.cnf文件中设置max_connections参数即可。比 如:max_connections = 800。

二、php-cgi进程数

后来,在之后的某一次秒杀中,在点击开始秒杀出现验证图片的时候,整个页面需要卡上10s左右才出来,我认为是php-cgi进程处理不过来,所以将其由最开始的100提高到256,这对于内存足够大的服务器来说,能尽快响应等待的请求,让用户尽快地得到响应。

三、session数目

不过,第二步在后来的进一步跟踪中,发现还并不是导致页面变慢的主要问题——真正的罪魁祸首是session。原来的session过期时间设定的 是30天,在session表中,存储了超过40万条的记录,在验证图片显示的页面,就需要利用到session来存储验证码,对一个40万的 session表操作,让mysql要索表0.5s,因此页面响应的速度急剧下降。后来通过删除无用的session信息,将session表记录减低到 7000,并将session有效时间调整为7天,就将页面的响应速度很快地降低下来了。

四、验证图片

验证图片用到session也增加了数据库操作次数,因此我考虑将验证图片从session剥离开来,直接利用memcached来存储用户的验证 码信息。用户请求的时候,分配一个唯一的sessionkey,用户请求验证图片时,需要通过sessionkey来请求,同时,系统存储一个键值对 (sessionkey=>validcode)到memcached,这样的话,将请求验证码图片的数据库操作次数将为0,对于秒杀系统的响应速 度也提供了极大的方便。

五、秒杀得主的决策

最开始,我们采取了如下的秒杀得主判定策略:秒杀者检查秒杀产品的秒杀得主是否为空,如果为空,则认定自己是秒杀得主,并将秒杀产品的秒杀得主设置为自己。(如下图所示)

秒杀者自己判定似乎否为秒杀得主

图一、秒杀者自己判定似乎否为秒杀得主

在内部测试期间,人数比较少,这种策略一直都没有出问题。不过到正式上线的时候,这种策略在高并发的情形下,则变得不堪一击:因为,在用户A检查自 己是否是秒杀得主的时候,已经有用户B,设置用户C、用户D也在进行这项检查,而这个时候,用户A还没有将自己是秒杀得主的消息写入秒杀产品的记录中,所 以,用户B、C、D都会认为自己也是秒杀得主。

我们曾经想过,将相关的数据操作用memcached缓存起来,不过,其实,虽然memcached在响应速度上虽然比mysql要快,但在高并发的情况下,它也依然无能为力,依然会遭遇到同样的问题。

后来,我们决定改变策略:用户秒杀的时候只让其插入秒杀记录,并不去判断自己是不是秒杀得主;判断得主的事情交给裁判——定时任务完成。定时任务根据各个用户秒杀时间的先后顺序,很容易就可以知道谁是秒杀得主,并将秒杀产品的秒杀得主设置为这个用户。(如下图所示)

由定时程序判定谁是秒杀得主

图二、由定时程序判定谁是秒杀得主

我想,我们在各种比赛中,都需要由裁判来主持公道,也是同样的道理吧。

通过做好如上所述的步骤,相信您的秒杀活动一定能更加完好地运行。

 

 

http://blog.ebar18.com/archives/126

posted @ 2013-11-25 12:16  coolid  阅读(4296)  评论(0编辑  收藏  举报