关注牛哥公众号:牛牛码特,回复:1,即可获得秋招大礼包
面经统计表/Java Top100面试题/秋招企业投递表
秒杀活动的难点在于应对高并发流量、防止库存超卖、保证系统稳定性和优化用户体验。为了达成以上目标,整个秒杀链路都需要进行优化:
核心目标:从用户交互层过滤重复/无效请求,降低后端压力。
具体实现:
用户ID+商品ID的最近请求时间),限制每分钟最多发起5次请求,超过则提示“操作过频”。核心目标:将请求均匀分发到应用集群,同时拦截超量请求。
具体实现:
limit_req模块设置全局限流阈值(如每秒10万请求),超过阈值的请求直接返回503或“系统繁忙”页面,不转发到应用层。核心目标:在业务逻辑处理前,验证请求的合法性,避免无效请求进入核心链路。
具体实现:
Set结构存储user:seckill:{商品ID},存在则拦截)。timestamp(时间戳)和sign(签名,如MD5(商品ID+用户ID+timestamp+密钥)),服务端验证签名有效性,防止伪造请求。核心目标:通过Redis快速判断库存是否充足并预扣减,避免直接操作数据库导致的性能瓶颈。
具体实现:
SET seckill:stock:{商品ID} 1000),确保秒杀时直接从Redis读取库存。DECR命令或Lua脚本实现“判断库存+扣减库存”的原子操作(避免并发下超卖):-- KEYS[1] = 商品库存键,ARGV[1] = 扣减数量
local stock = redis.call('get', KEYS[1])
if not stock or tonumber(stock) < tonumber(ARGV[1]) then
return 0 -- 库存不足
end
return redis.call('decrby', KEYS[1], ARGV[1]) -- 扣减库存并返回剩余数量核心目标:通过消费消息队列中的秒杀成功消息,异步完成订单创建和数据库库存扣减,保证数据一致性。
具体实现:
UPDATE product_stock SET stock = stock - 1 WHERE product_id = ? AND stock > 0(双重校验,防止Redis异常导致的超卖)。核心目标:解决分布式系统中可能出现的库存数据不一致问题(如Redis扣减成功但数据库未扣减)。
具体实现:
GET seckill:stock:{商品ID}),与数据库product_stock表的库存进行对比。SET seckill:stock:{商品ID} 数据库库存值),并记录差异日志(用于排查原因,如消息丢失、消费失败等)。