From b839e361ac1400f385b76f07eca2b26bcfca4f58 Mon Sep 17 00:00:00 2001 From: Cxx0822 <1556464090@qq.com> Date: Wed, 10 Jun 2026 18:16:29 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E5=A2=9E=E5=8A=A0=E7=A7=92=E6=9D=80?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E8=AE=BE=E8=AE=A1=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/.vitepress/theme/router/index.ts | 4 +- docs/Web/Others/Seckill.md | 111 +++++++++++++++++++++ docs/Web/SpringBoot/SpringBoot-Redis.md | 28 ++++++ docs/Web/SpringBoot/SpringBoot-RocketMQ.md | 100 +++++++++++++++++++ 4 files changed, 242 insertions(+), 1 deletion(-) create mode 100644 docs/Web/Others/Seckill.md create mode 100644 docs/Web/SpringBoot/SpringBoot-RocketMQ.md diff --git a/docs/.vitepress/theme/router/index.ts b/docs/.vitepress/theme/router/index.ts index 3e4274a..660a0fb 100644 --- a/docs/.vitepress/theme/router/index.ts +++ b/docs/.vitepress/theme/router/index.ts @@ -31,6 +31,7 @@ export const routers = [ { text: 'SpringBoot技巧', link: '/Web/SpringBoot/SpringBoot-Skills' }, { text: 'RestClient简介', link: '/Web/SpringBoot/SpringBoot-RestClient' }, { text: 'Redis简介和使用', link: '/Web/SpringBoot/SpringBoot-Redis' }, + { text: 'RocketMQ简介和使用', link: '/Web/SpringBoot/SpringBoot-RocketMQ' }, { text: 'WebSocket简介和使用', link: '/Web/SpringBoot/SpringBoot-WebSocket' }, { text: 'Quarzt简介和使用', link: '/Web/SpringBoot/SpringBoot-Quartz' }, { text: '线程与事件', link: '/Web/SpringBoot/SpringBoot-Thread' } @@ -84,7 +85,8 @@ export const routers = [ { text: 'AList简介和使用', link: '/Web/Others/AList' }, { text: 'InfluxDB简介和使用', link: '/Web/Others/InfluxDB' }, { text: '视频压缩', link: '/Web/Others/VideoCompressor' }, - { text: '图片处理服务', link: '/Web/Others/ImageProcessor' } + { text: '图片处理服务', link: '/Web/Others/ImageProcessor' }, + { text: '秒杀系统设计与实战', link: '/Web/Others/Seckill' } ] }, ] diff --git a/docs/Web/Others/Seckill.md b/docs/Web/Others/Seckill.md new file mode 100644 index 0000000..a8f8ae6 --- /dev/null +++ b/docs/Web/Others/Seckill.md @@ -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("已售罄"); +} +``` +  要先减再判断,如果小于0,则表示已售罄,再回滚数据。 + +## 2.3 异步 +```java +rocketMQTemplate.convertAndSend("seckill-order", Map.of("userId", userId, "goodsId", 1)); +return ResponseEntity.status(200).body("秒杀成功"); +``` +  Redis成功后则通过发消息通知消费者操作数据库。 +  为了防止重复创建订单,还需要进行一次幂等校验,即根据订单号的唯一性判断是否有重复的。 + +# 三、压测 +  采用ApiPost工具进行压测。 \ No newline at end of file diff --git a/docs/Web/SpringBoot/SpringBoot-Redis.md b/docs/Web/SpringBoot/SpringBoot-Redis.md index 75a9992..eebc58c 100644 --- a/docs/Web/SpringBoot/SpringBoot-Redis.md +++ b/docs/Web/SpringBoot/SpringBoot-Redis.md @@ -7,6 +7,7 @@   Redis是一个高性能的开源内存数据库,用作缓存、数据库和消息中间件。它以极快的读写速度(基于内存存储)支持字符串、列表、哈希等多种数据结构。Redis提供数据持久化、主从复制、哨兵模式等高可用特性,广泛应用于缓存、会话存储、排行榜、消息队列等场景。 # 二、安装 +## 2.1 apt安装 1. 通过apt包管理器安装: ```bash sudo apt update @@ -25,6 +26,33 @@ requirepass password   `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 +``` + +  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 diff --git a/docs/Web/SpringBoot/SpringBoot-RocketMQ.md b/docs/Web/SpringBoot/SpringBoot-RocketMQ.md new file mode 100644 index 0000000..5e17434 --- /dev/null +++ b/docs/Web/SpringBoot/SpringBoot-RocketMQ.md @@ -0,0 +1,100 @@ +--- + title: SpringBoot RocketMQ简介和使用 + date: 2026-06-10 +--- + +# 一、简介 +  [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 +``` + +  broker.conf: +```conf +brokerIP1=192.168.1.100 +autoCreateTopicEnable=true +``` + +::: tip +这里一定要配置brokerIP1,否则Broker的地址是docker的内网地址,具体可以在控制台中查看Broker的地址。 +::: + +# 三、SpringBoot使用 +## 3.1 引入依赖 +```xml + + + org.apache.rocketmq + rocketmq-spring-boot-starter + 2.3.6 + +``` + +::: tip +需要加上版本号,SpringBoot3使用2.3以上的版本。 +::: + +## 3.2 配置文件 +```yml +rocketmq: + name-server: 192.168.1.100:9876 + producer: + group: seckill-producer-group +```