您的位置:首页 > 编程语言 > Java开发

Java 秒杀高并发系统的一些想法设计

2018-01-23 21:24 513 查看
最近因为业务需要,在设计一些秒杀的应用场景,根据网上已经有资料,经过自己综合分析,得出以下结论,还请多多赐教!!

高并发

一、前端

1,尽可能在上游拦截和限制请求,限制流入后端的量,保证后端系统正常。

因为无论多少人参与秒杀,实际成交往往是有限的,而且远小于参加秒杀的人数,因此可以通过前端系统进行拦截,限制最终流入系统的请求数量,来保证系统正常进行。

2,静态化页面,将页面缓存在用户的浏览器和CDN上

3,提交后按钮disabled,禁止用户重复提交

二、服务器集群

1.通过nginx分发请求,提前预判会产生的PV数,部署合适数量的服务器集群,防止其中一台Web机器挂了,导致流量分散到其他正常工作的机器上,再导致正常的机器也挂,将整个Web系统拖垮

2.优化服务器中间件如tomcat jvm优化(虚拟机初始化时的最小内存,可用最大内存,GC模式等),并发连接优化(初始化 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.账号数据进行“数据挖掘”,这些黄牛账号也是有一些共同特征的,例如经常抢票和退票,节假日异常活跃等等。将它们分析出来,再做进一步处理和甄别。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: