我们的秒杀请求到了tomcat之后,我整个请求到了后端,我们怎么抗住高并发
也就是让他1s抗住10w的订单量,该怎么做
>> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >
一般来说秒杀系统都是需要单独部署的,因为它的并发压力很大他跟我们正常微服务或者web系统都是需要 单独剥离开的
这就是我们秒杀商品最简单的代码,假设我现在就只剩下一个库存了.我几十个请求同一时刻调用了查询db的方法,呢它都查到还有一个库存 ,都会减1 操作 意味着严重超卖update( product) -----> 意味着减1 操作超卖的问题如何解决 此时必然不能加sy锁,因为加了锁之后我们的并发就抗不到10w以上了如果要求并发不高可以加锁我们可以利用 update stock -1 where shock > 0 利用行锁
我其实是用数据库来帮我们解决并发 超卖的问题
我们其实是用数据库的乐观锁的方式来更新我们的e库存 解决超卖的问题
我就不用在整个代码逻辑上加锁了
这样来做性能会高一些有什么好的优化方案,让我这个系统的并发继续上升。
我们一般会用redis+mq
== == == == == == == == == == == == == == == == == == >> >> >> >> >> >> >> >> >> >> >> >> >
我们秒杀走缓存得方案,我们秒杀得商品库存 提前放到缓存中 这个叫做缓存预热然后我们真正减少db,然后我们真正减库存的时候 不是直接db干的,db并发太低了,我们一般在缓存中扣减库存
所以我们的秒杀系统,会提前预热商品缓存缓存
然后我们真正做秒杀的时候,从redis查商品库存一般mq下单,慢慢去消费。我异步创建订单.也就是前端下单链路 没有操作db的
性能很高得因为redis 的并发本身就可以支撑很高 如果用kafka 或者mq ,它得并发也很高
我前端给用户返回一个抢购成功前端 给用户一个缓冲 我可以每过2到3s中 往后台发一个查询订单的请求
看下你这个订单有没有下成功 如果你没有下成功
我继续再重发请求 又过2到3s 再去发 当你后端mq消费完毕 被下单成功后
我这个时候再去查询的时候 下单成功 转到支付页面
redis理论上每秒能抗10w的并发,但是实际上没有 而且一般是读的时候才可以
我们的redis是有读有写,也就是说redis既有查询又有写的时候 是支撑不了10w并发的
redis集群架构
正常用redis单节点 有单节点问题 如果用redis集群架构
我们服务端的redis集群 我们数据在redis集群中是分片存储的比方说我线上有10个商品 这10个商品实际上是分布式在不同的redis节点上
真正的redis节点它的数据是分片存储的
根据它的hash 分片算法
redis集群 他会帮我们把数据进行分片来存储
我一个redis节点读写并发 就2w左右
假设现在我有10个商品 我按照334 的拆分
我每秒 都能抗接近10w 的并发了
redis做集群架构 让你的所有的秒杀 活动 的商品均匀的分配在redis的节点
但是没有呢么理想 很有可能10 个商品 按照hash分片算法 都落在在了第一个节点
呢这套系统只能抗3w的并发
你的商品的key 都落在同一个节点上,导致我们所有的请求 都打在同一个节点上针对我们秒杀商品说白了,要缓存预热的时候 你这个商品在那个节点上,你自己肯定要知道的我预热的时候就得解决,我们通过一些redis命令,吧倾斜的商品进行移动,
或者我们可以用hashTag 把我们的商品进行分片
也就是说{ 1 ,2} 在一个节点上 { 3 ,4} 在一个节点上
其实说白了,我现在有10个秒杀商品.我其实来的10w并发 甚至更高的并发 都集中在1个商品上
我所有请求都只抢一个商品 呢意味着 你现在所有请求 又打到了某一个节点上
此时就不能支撑10w的并发了热点商品问题 怎么提升它的并发
一个商品的并发请求就很高
怎么让它扛到10w 的并发 有什么好的方案
我做秒杀的时候 我应该有一些预设 就不能把他的库存放在一个redis节点上
我在做缓存预热的时候 我就的要拆开了
就算此时都是抢茅台,我自己做一个负载均衡的策略 第一个请求 抢第一个 第二个请求抢第二个节点的100个
我们可以利用conHashMap进行分段存储,我们一个10w级别秒杀系统大概是这种的
我们在瞅瞅这个系统的架构中还有那些有问题 因为有问题 可能导致我们系统崩溃
我们此时除了满足系统高并发之外 还要高可用
redis 减库存 之后我们就丢到mq中 mq 用的时候 碰到过什么问题
mq丢消息怎么处理
mq消息挤压怎么处理
mq消费的时候怎么保证幂等 这些问题肯定会导致我们系统不稳定 影响我们的可用性
我在发mq的时候 记录一个日志表 然后等Mq消费成功之后 再去更新这个表状态 从待处理改成已处理万一我消息丢失了 我状态就是待处理状态,我后端可以搞个定时任务来轮询待处理的任务 进行重发
消费的过程中怎么保证它的幂等
比如说你发mq失败了,可能重试了,可能你一条消息发了2次,呢我下游可能同一个订单有 入库2次
就有可能生成2个订单
对于mq 幂等怎么处理有的时候订单id是在我服务端生成的 我订单id是在我服务端生成的 我可以用messageId 做主键
我也可以用(userId+productId+acvitityId) 做个业务主键,(一般来说你是那个秒杀活动) 组合一个唯一的Id我下单的时候我查下(redis/db) 这个主键在不在 如果不存在的化 就代表它是一笔
mq消息挤压 我后端消费来不及呢么快 消息挤压了怎么处理
我mq 里面存在了上百万条消息,这个时候会出现什么问题
我用户在前端还等着了 现在异步下单 意味着它此时的圈圈会一直转的
你这块挤压了有百万 意味着 一个订单生成个 很久才能被消费
用户是等不了这么久的
我如果拿到这个消息 (是有发送时间的) 我判断一下 如果这个消息是2分钟以前发的 呢意味着这条消息
已经在mq中等了2分钟了
我超过1分钟 我直接吧消息丢掉、、
如果转的超过2分钟 还没有查到 的化 我就认为你下单失败了
因为这个订单在1分钟没有被消费的时候 其实已经被丢掉了
假设此时抢购问题 redis集群出现问题怎么办,mq集群出现问题了怎么办