你们秒杀并发量多少啊?
我们做活动的时候差不多2000左右
你们秒杀是怎么做的啊?
秒杀的时候流量比较大,我们把最近3天的场次信息,还有秒杀商品信息,全部放入redis,每个商品独立的设置一个随机码,对应库存也放入redis,为了解决超卖问题,秒杀的时候加了分布式锁,保证整个下单的原子性
那你们把库存放入redis,怎么保证redis和数据库库存一致?
我们这边后台管理有个库存,一个是redis实时库存数量,另外一个是数据库本身库存展示,最终库存抢购以redis为主,有个定时任务同步redis到数据库的库存
那你们把数据都放入redis,假如redis挂了,数据不是丢了吗?
我们redis做了集群,集群又做了主从,保证了服务的高可用,丢数据可能性比较小
你说下你们你们秒杀的时候有哪些表,还有秒杀的逻辑是什么?
- 秒杀系统是一个微服务,哪些表,场次表,sku商品表,秒杀商品表(),订单表,订单明细表,支付记录表
- 定时任务把最近3天的场次,秒杀信息放入reids,每个商品独立的设置一个随机码
- 获取秒杀信息的时候直接从reids取,如果不在时间段是没有随机码token的
- 秒杀下单(商品id,随机码token,数量),redis查商品,校验随机码,检验秒杀时间段,商品id和随机码是不是一样,检验每人限购数量,检验库存,锁定库存(减库存),orderVo放入MQ,order系统监听,产生订单
- 支付(下单接口(支付宝页面完成),主动查询结果,通知接口))
秒杀的接口安全性是怎么考虑的,假如我提前拿到了url地址我可以通过脚本攻击去抢购了?
我们在做活动之前会把所有的场次下面的商品放入redis,每个商品都会绑定一个token令牌,这个令牌只有在活动刚刚开始的时候才能获取到,真正抢购的时候我们获取校验token和商品id的匹配,所以活动不开始是不知道token的
另外也可以采用加密签名的方式
加密签名的方式怎么做的呢?
我们和前端约定好一个密钥,然后按照一定的规则把参数拼接一起同时拼上timestamp然后拼接一个密钥,对它MD5生成一个sign,服务端拿到参数后按照同样的规则签出来一个sign,和前台传过来的sign做对比,如果是一样的说明是正常的请求,如果不一样说明非正常请求拒绝
那你们秒杀流量比较大怎么办啊?
我们做了限流了的
你们限流怎么用的啊?
我们用的阿里的sentinal,首先我们需要导入alibaba-sentinal的jar包依赖,还有它有一个配置平台,里面有很多限流熔断策略,比如QPS(并发量),阈值,并发线程数,使用的过程我们加一个@SentinelResource,还可以自定义返回结果集,如下图: 
Sentinal原理怎么实现的?
它是基于aop,然后是基于滑动窗口实现的实时指标数据收集统计
如果我让你自己做个限流功能,你会怎么做?
这个时候需要限制单位时间用户访问的次数, redission框架ratelimiter,思路:单位时间内产生一定的次数,然后可以根据自定义key去限流,Aop可以做成切面,做了一个RateLimit注解 
做了一个切面,如下 

你抢购的时候RabbitMQ怎么用的?
秒杀下单传入(商品id,随机码token,数量),redis查商品,校验随机码,检验秒杀时间段,商品id和随机码是不是一样,检验每人限购数量,检验库存,锁定库存(减库存), orderVo放入MQ,order系统监听,产生订单
订单发到消息队列后,消息的重复消费是怎么解决的?
- 订单号唯一的,我们可以从数据库查询下,如果存在直接return,
- 把订单号放入redis并且设置一个时间,消息队列是有序的,一般不会去消费很早之前的信息,然后消费的时候从redis取,如果能取到说明被消费过,直接结束,不能取到说明之前没消费过
- 订单号做唯一索引
假如订单发到消息队列后,消息丢了,怎么办?你会怎么考虑?
- 保证MQ集群的高可用持久化(避免出现单点故障丢消息)
- 可以采用rabbitMq的ack确认机制(监听消息的时候手动签收消息确认)
- 消息落地,把消息保存到数据库,然后通过定时任务做补偿消费(在发送消息的时候,我们给每个消息分配一个message_id,把消息保存数据库,然后消息发送到MQ,在监听的时候)
秒杀下单你是怎么做的,说具体步骤,思路?
秒杀下单(商品id,随机码token,数量),redis查商品,校验随机码,检验秒杀时间段,商品id和随机码是不是一样,检验每人限购数量,检验库存,锁定库存(减库存),orderVo放入MQ,order系统监听,产生订单
订单超时怎么做的?
我们用的RabbitMQ延迟队列,当用户下单的时候,把订单号,延迟的时间(我们设置的是5MIN)放入,延迟队列,到对应时间后会执行订单取消,如果查询当前订单为未支付,把订单状态改为取消,同时把库存退还重新加入redis
RabbitMQ延迟队列的原理是什么?
我们给MQ设置2个队列,分别去绑定一个交换机,给一个队列设置过期时间和过期路由key和交换机,当下单的时候我们把消息发入带着设置过期时间的队列,不去监听这个队列,消息过期不消费它会路由到新的队列,然后我们去监听新的队列
为什么要用分布式锁啊?
因为我们的系统是分布式的,synchronized和lock锁只能是JVM级别的,这个时候需要分布式锁,它实现的思路: redis分布式锁其实就是往redis设置一个key和value同时设置一个有效时间,并且redis是单线程的,不会并发操作,(执行任务完成后),再把redis的key删除掉(解锁),这个过程需要注意的点是,必须保证设置key和value和设置时间保证它的原子性,不然可能出现死锁,另外一方面就是锁任务自动超时问题,所有我们一般用的redisson框架,它完美的帮我们封装了分布式锁,底层是基于LUA脚本实现保证原子性,同时redission还有watch dog,比如我们上锁3秒,但是任务执行5秒,它会自动加时间 伪代码: 分布式锁{ redis查商品,3 校验随机码, 检验秒杀时间段, 商品id和随机码是不是一样, 检验每人限购数量, 检验库存,3 锁定库存(减库存) 下单消息队列 }
redis分布式锁底层原理,为什么使用redission框架?
redis分布式锁其实就是往redis设置一个key和value同时设置一个有效时间,并且redis是单线程的,不会并发操作,(执行任务完成后),再把redis的key删除掉(解锁),我们必须保证设置key和value和设置时间保证它的原子性(LUA),redission类似看门狗的机制,watch dog,我们上锁3秒,但是任务执行5秒,它会自动加时间