feat:增加秒杀系统设计文档

This commit is contained in:
2026-06-10 18:16:29 +08:00
parent b40d3f14a8
commit b839e361ac
4 changed files with 242 additions and 1 deletions

111
docs/Web/Others/Seckill.md Normal file
View File

@@ -0,0 +1,111 @@
---
title: 秒杀系统设计与实战
date: 2026-06-10
---
# 一、简介
  一个典型的秒杀系统通常采用 **限流 + 缓存 + 异步** 的架构:
```plain
客户端
Nginx / 网关(限流)
秒杀接口校验、Redis 预扣库存)
RocketMQ下单消息
订单服务(创建订单、真正扣库存)
MySQL
```
  **限流挡人、缓存决策、异步解耦**。
# 二、实战设计
## 2.1 限流
### 2.1.1 Nginx限流
```conf
# 定义规则
limit_req_zone $binary_remote_addr zone=seckill:10m rate=5r/s;
server {
listen 80 default_server;
listen [::]:80 default_server;
location /seckill-api/ {
# 启用限流
limit_req zone=seckill burst=10 nodelay;
# 返回 429
limit_req_status 429;
proxy_pass http://127.0.0.1:8080/;
}
}
```
  `limit_req_zone`用来制定规则,`limit_req`表示启用规则,如果某个`location`没写,则不会启动规则。
  `zone=seckill:10m`表示开辟一块`10MB`的内存,取名叫`seckill`,专门存`IP`访问记录,`rate=5r/s`表示每个`IP`每秒最多`5`个请求。
  `limit_req zone=seckill`表示启动`seckill`规则,`burst=10`表示突发请求缓冲,`nodelay`表示超出后直接失败。
::: tip
`limit_req_zone`一定要写在`http`模块中,如果是`Linux`部署的,直接写在最外面。
:::
::: warning
Nginx限流只能防止单ip高刷无法挡住大量不同IP的分布式攻击。
:::
### 2.1.2 Semaphore限流
  `Semaphore`是针对应用层限流,保护`JVM`,防止`Tomcat`线程池被打爆。
```java
private final Semaphore semaphore = new Semaphore(100);
if (!semaphore.tryAcquire()) {
return ResponseEntity.status(429).body("系统繁忙");
}
try {
} finally {
semaphore.release();
}
```
  `new Semaphore(100)`表示最多`100`个线程同时进来,超过则直接返回失败,不会进入排队,也不会卡住线程。
::: tip
Semaphore不是全局限流不具备分布式能力。
:::
### 2.1.3 Redis限流
```java
String userKey = "seckill:user:" + userId;
Boolean first = redis.opsForValue().setIfAbsent(userKey, "1", 60, TimeUnit.SECONDS);
if (Boolean.FALSE.equals(first)) {
return ResponseEntity.status(429).body("请勿重复尝试");
}
```
  如果是限制每个用户只能限购一次,则可以将过期时间设置为永久。
## 2.2 缓存
  先在`Redis`里面判断逻辑,然后再执行数据库。
```java
String stockKey = "seckill:stock:1";
Long remain = redis.opsForValue().decrement(stockKey);
if (remain == null || remain < 0) {
redis.opsForValue().increment(stockKey);
return ResponseEntity.status(200).body("已售罄");
}
```
&emsp;&emsp;要先减再判断如果小于0则表示已售罄再回滚数据。
## 2.3 异步
```java
rocketMQTemplate.convertAndSend("seckill-order", Map.of("userId", userId, "goodsId", 1));
return ResponseEntity.status(200).body("秒杀成功");
```
&emsp;&emsp;Redis成功后则通过发消息通知消费者操作数据库。
&emsp;&emsp;为了防止重复创建订单,还需要进行一次幂等校验,即根据订单号的唯一性判断是否有重复的。
# 三、压测
&emsp;&emsp;采用ApiPost工具进行压测。

View File

@@ -7,6 +7,7 @@
&emsp;&emsp;Redis是一个高性能的开源内存数据库用作缓存、数据库和消息中间件。它以极快的读写速度基于内存存储支持字符串、列表、哈希等多种数据结构。Redis提供数据持久化、主从复制、哨兵模式等高可用特性广泛应用于缓存、会话存储、排行榜、消息队列等场景。
# 二、安装
## 2.1 apt安装
1. 通过apt包管理器安装
```bash
sudo apt update
@@ -25,6 +26,33 @@ requirepass password
&emsp;&emsp;`systemctl restart redis-server`重启服务。
## 2.2 docker安装
```yml
services:
redis:
image: redis:8.6.4
container_name: redis
restart: always
ports:
- "6379:6379"
volumes:
- ./redis.conf:/usr/local/etc/redis/redis.conf
- ./data:/data
command: redis-server /usr/local/etc/redis/redis.conf
```
&emsp;&emsp;redis.conf:
```conf
bind 0.0.0.0
protected-mode yes
port 6379
requirepass password
```
## 2.3 客户端
[Tiny RDM](https://redis.tinycraft.cc/zh/)
# 三、SpringBoot使用
## 3.1 引入依赖
```xml

View File

@@ -0,0 +1,100 @@
---
title: SpringBoot RocketMQ简介和使用
date: 2026-06-10
---
# 一、简介
&emsp;&emsp;[RocketMQ](https://rocketmq.apache.org/zh/)Apache RocketMQ 是一款面向万亿级消息规模的 AI 原生异步通信引擎。诞生于阿里巴巴高并发电商场景经过数千家企业的生产验证RocketMQ 已从高性能消息队列演进为统一消息平台,横跨传统业务消息、事件流处理和新兴的 AI 原生通信三大范式。
# 二、安装
## 2.1 docker安装
```yml
services:
namesrv:
image: apache/rocketmq:5.3.2
container_name: rmqnamesrv
ports:
- 9876:9876
networks:
- rocketmq
command: sh mqnamesrv
broker:
image: apache/rocketmq:5.3.2
container_name: rmqbroker
ports:
- 10909:10909
- 10911:10911
- 10912:10912
volumes:
- ./broker.conf:/home/rocketmq/rocketmq-5.3.2/conf/broker.conf
environment:
- NAMESRV_ADDR=rmqnamesrv:9876
depends_on:
- namesrv
networks:
- rocketmq
command: sh mqbroker -c /home/rocketmq/rocketmq-5.3.2/conf/broker.conf
proxy:
image: apache/rocketmq:5.3.2
container_name: rmqproxy
networks:
- rocketmq
depends_on:
- broker
- namesrv
ports:
- 8380:8080
- 8381:8081
restart: on-failure
environment:
- NAMESRV_ADDR=rmqnamesrv:9876
command: sh mqproxy
rocketmq-dashboard:
image: apacherocketmq/rocketmq-dashboard:2.1.0
container_name: rocketmq-dashboard
environment:
- JAVA_OPTS=-Drocketmq.namesrv.addr=rmqnamesrv:9876
ports:
- 8382:8082
networks:
- rocketmq
depends_on:
- namesrv
restart: always
networks:
rocketmq:
driver: bridge
```
&emsp;&emsp;broker.conf:
```conf
brokerIP1=192.168.1.100
autoCreateTopicEnable=true
```
::: tip
这里一定要配置brokerIP1否则Broker的地址是docker的内网地址具体可以在控制台中查看Broker的地址。
:::
# 三、SpringBoot使用
## 3.1 引入依赖
```xml
<!-- RocketMQ -->
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-spring-boot-starter</artifactId>
<version>2.3.6</version>
</dependency>
```
::: tip
需要加上版本号SpringBoot3使用2.3以上的版本。
:::
## 3.2 配置文件
```yml
rocketmq:
name-server: 192.168.1.100:9876
producer:
group: seckill-producer-group
```