高并发
一、前端
1.静态化页面,将页面缓存在用户的浏览器和CDN上
备注:CDN加速将网站的内容缓存在网络边缘(离用户接入网络最近的地方),然后在用户访问网站内容的时候,通过调度系统将用户的请求路由或者引导到离用户接入网络最近或者访问效果最佳的缓存服务器上,有该缓存服务器为用户提供内容服务;相对于直接访问源站,这种方式缩短了用户和内容之间的网络距离,从而达到加速的效果。
二、服务器集群
1.通过nginx分发请求,提前预判会产生的秒杀时参与人数,部署对应数量的服务器集群(tomcat)。
2.优化服务器中间件如tomcat jvm优化,并发连接优化(初始化 socket线程数,最大socket线程数等)
三、服务端层
1.秒杀业务是一个读多写少的场景,大部分请求是查询请求,多使用缓存对应读的请求,增加服务端响应速度,减少CPU处理多个连接数的压力 导致整体响应速度变慢,以及web服务器链接数被占满
减库存实现逻辑
2-1.将商品的开始时间放置在redis缓存中,判断是否到了秒杀开始时间
2-2.请求间隔是否符合正常时间(如将用户上一次的请求时间记录下来计算时间差)
2-3.将商品库存剩余数量放置到redis缓存中,判断库存数量是否还有剩余
2-4.有剩余的话,获取一个redis分布式锁
利用redis的.setnx命令,先判断是否存在再赋值
因为redis都是串行操作的,不存在并发问题
拿到锁:
2-5.处理业务逻辑,如将数据放置在一个mq中,然后通过incr、incrby、decr、decrby原子操作命令控制库存数,减少数据库IO的开销
- incr递增1并返回递增后的结果;
- incrby根据指定值做递增或递减操作并返回递增或递减后的结果(incrby递增或递减取决于传入值的正负);
- decr递减1并返回递减后的结果;
- decrby根据指定值做递增或递减操作并返回递增或递减后的结果(decrby递增或递减取决于传入值的正负);
2-6.释放锁,返回应答
未拿到锁:
2-7.线程sleep再次尝试拿锁 ,多次未拿到锁则返回用户活动太火爆
3.数据库层操作sql语句加上乐观锁做一个保护
四、防作弊
1.同一个账号,一次性发出多个请求
部分用户通过浏览器的插件或者其他工具,在秒杀开始的时间里,以自己的账号,一次发送上百甚至更多的请求。实际上,这样的用户破坏了秒杀和抢购的公平性。
应对方案:
1.同一账号请求记录时间戳标记位。(可以在redis里根据用户ID 记录一条数据,比如1秒后失效)
2.再次请求的时候判断标记位是否存在,如果存在就立即打回请求。
2.多个账号,一次性发送多个请求
例如微博中有转发抽奖的活动,如果我们使用几万个“僵尸号”去混进去转发,这样就可以大大提升我们中奖的概率。
如果发现某个IP请求频率很高
应对方案:
1.返回验证码,区分真实用户
3. 多个账号,不同IP发送不同请求
黑客操作多个肉鸡
应对方案:
1.活动开始前通过一些“数据挖掘”筛选过滤僵尸号,僵尸账号也还是有一些共同特征的,例如账号很可能属于同一个号码段甚至是连号的,活跃度不高,等级低,资料不全等等。根据这些特点,适当设置参与门槛,例如限制参与秒杀的账号等级。
4. 奢侈品秒杀
随着时代进步,消费水平的提高,尤其女性对奢侈品追求,在识别验证码的时候使用真实的人,中间搭建一个展示验证码图片的中转软件服务,真人浏览图片并填写下真实验证码,返回给中转软件。对于这种方式,验证码的保护限制作用被废除了,。
应对方案:
1.账号数据进行“数据挖掘”,这些黄牛账号也是有一些共同特征的,例如经常抢票和退票,节假日异常活跃等等。将它们分析出来,再做进一步处理和甄别。