概要:
1.高并发场景秒杀抢购超卖bug实战重现
2.阿里巴巴内部高并发秒杀下单方案首次揭秘
3.基于Reddis+MQ实现秒杀下单架构
4.10万订单每秒热点数据架构优化实践
5.秒杀下单MQ如何保证不丢失消息
6.解决MQ下单消息重复消费幂等机制详解
7.线上MQ百万秒杀订单发生积压如何处理
8.Redis集群崩溃如何保证秒杀系统高可用性
9.Redis主从切换导致库存同步异常以及超卖问题
10.MQ集群崩溃时,如何保证秒杀系统高可用性
11.秒杀链路种Redis和MQ如何保证事务一致性
12.秒杀系统限流防刷攻击静态页面等方案详解
1.高并发框架
三高架构一般指:高可用性、高并发性、高可扩展性
秒杀系统就属于一个三高架构,一般单独部署,防止由于其影响其他功能
场景介绍:
秒杀主要是实现一个减库存的操作,还有就是数据信息的访问。面对高并发场景,有可能会产生超卖问题。
根据前面的笔记: 这种情况可以通过添加分布式锁来解决超卖,但是加分布式锁会导致性能很难上去。
如果不加锁,怎么解决超卖问题。
public Integer updateStock(Long productId){
//update product set stock = stock - 1 where id = 166 and stock >0
return productDao.seckill(productId);
}
@Transactional
public String seckill(Long productId,Long userId){
Product product=get(productId);
if(product.getStock()<=0){
return "库存售完";
}
product.setStock(product.getStock()-1);
update(product);
//TODO 创建订单数据
return "抢购成功";
}
2.不加锁如何解决超卖问题
1.使用数据库的并发解决超卖问题
查看更新是否成功。能更新则更新,不能更新就失败——数据库乐观锁。
问题:但是数据库不能支撑每秒十万的情况,最多每秒几千。支撑不了高并发情况
@Transactional
public String seckill(Long productId,Long userId){
Product product=get(productId);
if(product.getStock()<=0){
return "库存售完";
}
// product.setStock(product.getStock()-1);
// update(product);
Integer updateCount=updateStock(productId);
if(updateCount<1){
return "抢购失败";
}
//TODO 创建订单数据
return "抢购成功";
}
2.阿里解决数据库性能瓶颈
源码改造,在数据库内部实现一个内存队列,一次性接收十万请求,但是数据库每次处理几千,多处理。——以此来提升性能问题。(一般的公司没有这个实力)
3.常规解大数据量访问问题:Redis+MQ
package com.example.controller;
import com.example.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class SeckillConntroller {
@Autowired
private ProductService productService;
/**
* 秒杀接口
* 实现10万并发秒杀系统三高架构
* @param productId 商品Id
* @param userId 用户Id
* @return
*/
public String secKill(Long productId, Long userId){
return productService.seckill(productId,userId);
}
}
@Transactional
public String seckillRedis(Long productId,Long userId){
String productStockKey = "stock:count:"+productId;
Integer productStock = redisUtil.get(productStockKey,Integer.class);
if(productStock<1){
return "库存售完";
}
Long stockCount = redisUtil.decr(productStockKey,1);
if(stockCount<0){
redisUtil.incr(productStockKey);
return "抢购失败";
}
//TODO 发送下单MQ,异步创建订单
return "抢购成功";
}
对于要秒杀的商品可以提前预热,下单时直接从redis里查,并发情况下减库存可能导致负数,所以要判断stockCount>0
下单是个异步的过程,否则前台会不断的转圈圈。直到订单生成。
当前系统还是不能支撑每秒十万,读写混合——最多每秒2万
3.Redis集群实现高并发
1.分片分散访问压力
redis集群架构将数据分片存储,理论上:只要节点足够多,将十万分到各个节点,基本能抗近10万并发
问题:redis将数据分散到各个节点时,恰好所有数据在一个节点上,性能又崩了,不足以支撑10W每秒
2.数据倾斜问题
redis 集群架构的数据倾斜:数据存在出在一个节点上,大量请求达到一个节点,这个节点压力非常大。
解决方案:预热及时发现数据倾斜,通过命令挪到其他节点上,数据迁移。如:hashTag前面{}里的值去hash,这样就可以控制hash结果了
3.热点商品
某一个商品特别热卖,导致大量访问访问一个商品,一个商品只在一个节点上,这就导致该节点访问压力暴增。——每秒十万并发又不行了。
解决方案:提前规划,在缓存预热时,就将其库存分在多个节点上,不同的分片
@Transactional
public String seckillRedis(Long productId,Long userId){
String productStockKey = "stock:count:"+productId+"01";//02 03 数据分片存储
Integer productStock = redisUtil.get(productStockKey,Integer.class);
if(productStock<1){
return "库存售完";
}
Long stockCount = redisUtil.decr(productStockKey,1);
if(stockCount<0){
redisUtil.incr(productStockKey);
return "抢购失败";
}
//TODO 发送下单MQ,异步创建订单
return "抢购成功";
}
4.Redis集群架构+MQ
Redis+MQ可能存在哪些问题呢?
可能存在的问题:MQ丢消息、消息积压、消费消息如何幂等。保证不丢消息?怎么做:ACK
1.MQ的简单实现
消息队列的两种模式及MQ简单实现_mq简易实现-CSDN博客
2.如何保证消费幂等
多并发可能存在的问题:
如何保证幂等。https://www.cnblogs.com/wzh2010/p/15888523.html
重复消费问题(消费幂等):给每个操作MSG+唯一的ActId,保证消息不被重复消费。
有很多种4-5种方式,也可以用uuid, 但是uuid在性能上有影响
3.订单积压如何解决
订单排队被消费——前端一直转圈圈——会丢失客户的
1.增加消费者,加快消费速度
2.插入redis比DB快的多,如果发送时间已经很久了,积压状态——>走redis,查的时候,先数据库,后redis.
后台任务——redis——>DB
3.超过1min订单丢掉——>转1min就下单不成功,请重试——redis+1
4.降级服务
写到本地缓存|本地磁盘文件——记到日志文件;
不断访问redis,访问成功就将 定时记录的日志流水操作到redis和MQ里去
后台不断重试——数据绝对一致不可能,性能也是变差了
5.Redis集群整个崩了怎么办?
如果Redis集群整个崩了,如何保证可用性——要求保证99.9999%的概率可用,保证很小的出错概率。
Redis如果起不来,就使用备用redis集群,同步、切换。但是Redis集群切换可能存在的问题:
redis异步同步——主节点-1,从节点没同步,主节点挂了,从节点变主节点——>超卖
解决方案一:问题不大|不解决——应为不能大批量超卖
解决方案二:一定要解决
1.用红锁
2.redis同步,改源码,性能下降
3.不要从节点,多个主节点
分布式架构CAP三个特性不可能全解决
6.MQ整个崩溃怎么办?
MQ集群崩溃咋办?2-3种方案——保证高可用
1.和redis一样
如何保证MQ的高可用_mq消息中间件如何保证高可用-CSDN博客
RocketMQ快速失败机制引发集群不稳定的思考和优化-CSDN博客
7.其他问题
redis和MQ一致性怎么保证事务一致性。
一套描述有很多其他的东西,很难。
上亿流量又如何让解决呢。
https://www.cnblogs.com/qingxuan0316/p/16594179.html