引言
高并发场景在现场的日常工作中很常见,特别是在互联网公司中,这篇文章就来介绍如何实现高并发秒杀的几种方式。
实现方式
1.缓存
使用缓存可以减少数据库的访问量,提高系统吞吐量。可以缓存热点数据、查询结果等。
@Cacheable(value = "goods", key = "#goodsId")
public Goods getGoods(Integer goodsId) {
// 查询数据库
}
2.前端实现方式
通过前端 JS 代码限制用户请求频率,避免过大流量涌入,导致系统崩溃。比如可以实现每秒钟限制请求次数等。
var requestTimes = 0;
var lastRequestTime = 0;
function requestSecKill() {
var now = new Date();
if (now - lastRequestTime < 1000 && requestTimes > 5) {
alert('请求过于频繁,请稍后再试!');
return;
}
lastRequestTime = now;
requestTimes++;
// 发送秒杀请求
}
3.队列削峰
当请求流量超过系统容量时,暂存多余请求到消息队列,然后逐渐削峰处理。比如定时从队列中取出一定数量请求处理。
BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(1000);
public void addTask(Runnable task) {
boolean offered = queue.offer(task);
if (!offered) {
// 队列满了,请求太多,返回限流提示
}
}
public void handleTasks() {
Runnable task = queue.poll();
if (task != null) {
executor.execute(task);
}
}
4.限流
使用令牌桶或者漏桶算法根据系统容量限制请求通过速率。超过速率的请求被拒绝或进入队列等待。
RateLimiter rateLimiter = RateLimiter.create(10); // 每秒不超过10个请求
if (rateLimiter.tryAcquire()) {
// 请求通过
} else {
// 请求超过限流频率
}
5.数据库读写分离
将数据库分成主库和从库,秒杀相关读操作从从库读取,防止主库压力过大。
@Autowired
private GoodsRepository goodsRepository;
public Goods getGoods(Integer goodsId) {
// 读取从库
return goodsRepository.read(goodsId);
}
public void reduceStock(Integer goodsId) {
// 写入主库
goodsRepository.write(goodsId);
}
6.缓存失效时间
可以根据系统负载动态调整缓存失效时间,在高流量期间缩短失效时间,避免缓存相同数据长时间。
@Cacheable(value = "goods", key = "#goodsId", expire = "#expireTime")
public Goods getGoods(Integer goodsId, Integer expireTime) {
// 查询数据库
}
// 调整失效时间
cacheManager.setCacheExpired(cacheName, expireTime);
7.版本控制
对缓存或商品数据设置版本号,当数据修改时版本号递增。请求带上版本号,如果缓存版本低,则从数据库重新加载数据。可以确保用户获取最新数据。
后端:
@Cacheable(value = "goods", key = "#goodsId + #version")
public Goods getGoods(Integer goodsId, Integer version) {
// 查询数据库,带版本号校验
}
public void updateGoods(Integer goodsId, Integer version) {
goods.setVersion(version + 1);
// 更新数据库
}
前端:
$.get("/goods/" + goodsId + "?v=" + version, function(data) {
// 处理返回结果
});
总结
如果要完美解决高并发场景,需要 从缓存、限流、消息队列、数据库扩展多方面考虑,而不仅仅是一两个技术就可以。还需要注意系统的稳定性、扩展性,要足够灵活与健壮。
写在最后
如果大家对相关文章感兴趣,可以关注公众号"架构殿堂",会持续更新AIGC,java基础面试题, netty, spring boot,spring cloud等系列文章,一系列干货随时送达!