架构方案设计

1、秒杀场景 前端层面 前端优化(前端按钮点击频率限制、限制用户维度访问频率、限制商品维度访问频率、验证码机制等) 页面数据的静态化+多级缓存(CDN加速+N

1、秒杀场景

前端层面

前端优化(前端按钮点击频率限制、限制用户维度访问频率、限制商品维度访问频率、验证码机制等)

页面数据的静态化+多级缓存(CDN加速+Nginx+Redis)

服务层面

web服务器优化(tomcat、undertow)

nginx限流

负载均衡

服务器硬件升级

削峰处理

服务降级、熔断

jvm性能调优

业务层面

数据库分库分表、读写分离

sql调优

代码调优

 

 

超卖常用解决方案

事务

我们可以使用使用redis的 watch + multi 指令,去监听秒杀商品库存,如果库存数发生改变,则后续无法进行修改库存操作。

缺点:(1)由于watch采用乐观锁机制,没有对其它线程修改操作作限制,因此事务有可能频繁失败;需要用while循环去重复尝试;

(2)增加服务器压力

分布式锁

利用分布式锁,保证同一时刻只有一个线程进行读库存---修改库存操作。

缺点:同一个商品多用户同时下单的时候,会基于分布式锁串行化处理,导致没法同时处理同一个商品的大量下单的请求,并发处理能力较弱。

redis 队列

将库存缓存到redis队列,队列里面放sku_id,例如库存为5个,就放5个id。

通过rightPop操作取出商品,预扣减库存,如果pop出来的元素为空,说明售罄 。

这里利用了redis单线程操作特性,队列取id即扣减库存,相当于原子操作,高并发场景下不需要开事务,也不用加锁同步,性能、数据一致性均好于以上两种方案。

 

 

 

重复下单问题

MQ在整个秒杀流程中扮演了很重要的角色,因为下单数据全部暂存在MQ中,一旦消费者重复消费,就有可能出现一个用户秒杀到两个商品的重复下单情况。

所以代码有必要进行重复消息判断。

解决方案:

利用redis:发送消息时指定消息的全局唯一id;收到消息后查询redis是否有该id,有则说明是重复消息。然后立即将id存入redis中。

业务校验:生成订单时校验用户是否已经秒杀过该商品。

 

下单消息丢失

如果下单消息丢失了,用户秒的这个商品就可能永远卖不出去了,造成少卖问题。

以rabbit为例:

生产者丢失消息

(1)使用事务;

(2)使用confirm模式;

(3)异步监听确认模式

MQ丢失消息

开启消息持久化

消费者丢失消息

消费者消费完成后回执确认,如果一段时间后MQ没有收到消费者的回执确认,MQ就认为消息没有被成功消费,会将消息重新发送给其他消费者。

标签: 下单 秒杀 去了