AI 应用中的高并发处理:从限流、异步到缓存与队列

AI 应用中的高并发处理:从限流、异步到缓存与队列

做普通 Web 项目时,高并发主要解决的是数据库、接口和服务器的问题。

但 AI 应用有一个比较特殊的地方:一次请求背后往往不是一次简单的函数调用,而是一整条比较重的处理链路。

例如一个智能客服请求可能经历:

text 复制代码
用户请求
  ↓
FastAPI
  ↓
身份认证
  ↓
查询会话历史
  ↓
查询长期记忆
  ↓
RAG 向量检索
  ↓
Rerank
  ↓
调用大模型
  ↓
工具调用
  ↓
再次调用大模型
  ↓
返回结果

如果同时来了 1000 个用户,真正需要解决的并不是"Python 能不能同时处理 1000 个请求",而是:

  • 大模型 API 能不能承受?
  • 数据库连接够不够?
  • 向量数据库会不会成为瓶颈?
  • 大量请求同时调用模型会不会触发限流?
  • 一个 Agent 请求执行几十秒,会不会把 Web 服务线程全部占满?
  • 相同的问题是不是被重复计算了很多次?
  • 某一个下游服务挂掉以后,会不会把整个系统拖死?

所以 AI 应用的高并发,通常不是靠某一个技术解决,而是从请求入口到模型调用,再到数据存储,一层一层削减压力。


一、先搞清楚:AI 应用为什么比普通接口更容易遇到并发问题

传统接口可能是:

text 复制代码
请求
 ↓
查询数据库
 ↓
返回

整个请求可能几十毫秒就结束。

而 AI 应用可能是:

text 复制代码
请求
 ↓
RAG
 ↓
向量检索
 ↓
Rerank
 ↓
LLM
 ↓
Tool
 ↓
LLM
 ↓
返回

一次请求可能持续几秒甚至几十秒。

这意味着:

AI 应用真正需要控制的是"同时执行中的请求数量",而不只是 QPS。

例如:

text 复制代码
普通接口:

100 QPS
每个请求 50ms

和:

text 复制代码
AI 接口:

10 QPS
每个请求 20s

第二种情况反而可能更容易把系统拖垮。

因为假设每秒进入 10 个请求,每个请求平均执行 20 秒,那么系统中可能同时存在:

text 复制代码
10 × 20 = 200

个正在执行的请求。

因此做 AI 应用时,经常需要同时关注:

text 复制代码
QPS
并发请求数
平均响应时间
P95 / P99 延迟
Token 消耗
LLM 并发限制
数据库连接数
GPU 显存

二、第一步:先把同步调用改成异步

如果你的 AI 服务使用 FastAPI,第一步通常不是 Redis,也不是 Kafka,而是先检查代码是不是大量使用了同步阻塞调用。

例如:

python 复制代码
@app.post("/chat")
def chat(request: ChatRequest):
    result = llm.invoke(request.message)
    return {"answer": result}

如果 llm.invoke() 本身是一个阻塞操作,那么在模型响应回来之前,这个请求就一直处于等待状态。

更合理的方式是使用异步接口:

python 复制代码
@app.post("/chat")
async def chat(request: ChatRequest):
    result = await llm.ainvoke(request.message)
    return {"answer": result}

这样做的核心不是让"大模型变快"。

而是:

模型等待网络响应的时候,不要让 Web 服务白白占着执行资源。


三、异步并不等于高并发

这是一个非常容易误解的问题。

很多人看到:

python 复制代码
async def
await

就认为系统已经可以处理高并发了。

实际上不是。

假设同时有 10,000 个用户请求:

text 复制代码
FastAPI
   ↓
异步
   ↓
10,000 个请求
   ↓
全部调用 DeepSeek

一样会出问题。

因为瓶颈可能已经转移到了:

text 复制代码
LLM API
数据库
Redis
向量数据库
网络
GPU

所以异步解决的是:

提高服务器等待 I/O 时的资源利用率。

而限流、队列、缓存等解决的是:

控制系统到底允许多少请求同时进入下游。

两者不是一回事。


四、第二步:限制大模型并发数

这是 AI 应用非常重要的一层。

假设你的模型服务允许:

text 复制代码
最大并发:20

但是前端突然来了:

text 复制代码
500 个请求

如果直接全部调用模型:

text 复制代码
500 requests
      ↓
500 LLM calls

很容易出现:

text 复制代码
429 Too Many Requests
Timeout
Connection Error
服务雪崩

更合理的方式是增加并发控制。

Python 中可以使用 asyncio.Semaphore

python 复制代码
import asyncio

llm_semaphore = asyncio.Semaphore(20)


async def call_llm(prompt):
    async with llm_semaphore:
        return await llm.ainvoke(prompt)

此时:

text 复制代码
500 个请求
      ↓
并发控制
      ↓
最多 20 个同时调用 LLM
      ↓
其余请求等待

这样虽然不能让模型变快,但可以避免大量请求瞬间把模型服务打爆。


五、第三步:限流

如果系统允许任何用户无限请求,后面的所有优化都会失去意义。

最简单的情况:

text 复制代码
一个用户
 ↓
疯狂请求
 ↓
1000 次 LLM 调用
 ↓
其他用户全部排队

所以 AI 应用一般需要做限流。

常见限流维度:

text 复制代码
IP
用户
API Key
租户
接口
模型
Token

例如:

text 复制代码
普通用户:
60 requests / minute

VIP 用户:
300 requests / minute

或者限制 Token:

text 复制代码
用户每天最多消耗 1,000,000 tokens

六、常见限流算法

1. 固定窗口

例如:

text 复制代码
1分钟最多100次

实现简单,但是存在临界问题。

例如:

text 复制代码
12:00:59 → 100次
12:01:00 → 又100次

短时间内可能突然出现 200 次请求。


2. 滑动窗口

统计最近一段时间内的请求数量。

例如:

text 复制代码
最近60秒

超过阈值就拒绝。

相比固定窗口更加平滑。


3. 令牌桶

实际系统中非常常见。

可以理解成:

text 复制代码
桶
 ↓
不断产生令牌
 ↓
请求进来消耗一个令牌
 ↓
没有令牌就等待/拒绝

例如:

text 复制代码
桶容量:100
生成速度:10 tokens/s

可以允许短时间的流量突发,同时限制长期平均请求速度。

Redis + Lua 经常用于实现分布式限流。


七、第四步:缓存是 AI 应用非常重要的一层

AI 应用中有大量重复请求。

例如:

text 复制代码
用户A:什么是RAG?

用户B:RAG是什么?

用户C:RAG的作用是什么?

如果业务允许,可以通过缓存减少重复计算。

常见缓存内容:

text 复制代码
LLM结果
Embedding结果
RAG检索结果
用户会话
Agent状态
热点知识
系统配置

八、LLM 结果缓存

例如:

python 复制代码
cache_key = hash(prompt)

第一次:

text 复制代码
用户问题
 ↓
Redis没有缓存
 ↓
调用LLM
 ↓
保存结果
 ↓
返回

第二次:

text 复制代码
相同问题
 ↓
Redis命中
 ↓
直接返回

这样原本:

text 复制代码
1000次LLM调用

可能变成:

text 复制代码
100次LLM调用
900次缓存命中

对于成本比较高的模型,这个优化非常明显。

但 LLM 缓存不能简单地只使用用户问题作为 Key。

例如:

text 复制代码
prompt
model
system_prompt
temperature
知识库版本
用户权限

发生变化,都可能导致结果不同。

因此实际项目中的 Cache Key 往往类似:

text 复制代码
hash(
    model +
    system_prompt +
    user_prompt +
    temperature +
    knowledge_version
)

九、Embedding 也可以缓存

RAG 系统中经常会出现:

text 复制代码
用户问题
 ↓
Embedding
 ↓
向量检索

如果同一个问题重复出现,没有必要每次重新计算 Embedding。

可以:

text 复制代码
query
 ↓
hash(query)
 ↓
Redis
 ↓
命中 → 直接拿 embedding
未命中 → 调用 embedding 模型

对于高频问答系统,这种缓存非常实用。


十、第五步:把耗时任务放到消息队列

并不是所有 AI 请求都适合让用户一直等待。

例如:

text 复制代码
上传1000页PDF
 ↓
解析PDF
 ↓
OCR
 ↓
切分
 ↓
Embedding
 ↓
写入向量数据库

如果直接在 HTTP 请求里做:

text 复制代码
POST /upload
       ↓
等待60秒
       ↓
返回

非常不合理。

应该改成:

text 复制代码
用户上传
   ↓
API
   ↓
消息队列
   ↓
立即返回任务ID
   ↓
Worker后台执行

例如:

text 复制代码
POST /document
        ↓
    task_id=123
        ↓
      Redis
        ↓
    Worker
        ↓
 PDF解析
        ↓
 Embedding
        ↓
 向量数据库

前端再通过:

text 复制代码
GET /task/123

查询任务状态。


十一、常见消息队列

Python AI 项目常见选择:

text 复制代码
Celery + Redis
Celery + RabbitMQ
RQ
Kafka
Redis Streams

不要看到 Kafka 就觉得一定要用。

如果只是:

text 复制代码
PDF解析
文档Embedding
图片处理
批量生成题目

这种后台任务,很多时候:

text 复制代码
Celery + Redis

就已经够用了。

Kafka 更适合:

text 复制代码
大规模事件流
日志
数据管道
多个消费者
高吞吐场景

十二、为什么 Agent 特别适合使用任务队列

Agent 最大的问题之一就是:

一次请求可能执行很多步骤。

例如:

text 复制代码
用户问题
 ↓
Agent
 ↓
搜索工具
 ↓
数据库
 ↓
代码执行
 ↓
再次调用LLM
 ↓
生成最终答案

如果这些操作全部占用一个 HTTP 请求:

text 复制代码
请求持续30秒

并发量一大就很难受。

可以将一些不需要立即返回的任务异步化:

text 复制代码
用户请求
 ↓
Agent
 ↓
创建任务
 ↓
Queue
 ↓
Worker
 ↓
执行工具
 ↓
保存状态

十三、第六步:数据库连接池

很多 AI 应用并不是模型先挂,而是数据库先挂。

例如:

text 复制代码
1000个并发请求
 ↓
每个请求创建一个数据库连接
 ↓
1000个数据库连接
 ↓
数据库连接耗尽

所以不能每个请求都:

python 复制代码
connect()
query()
close()

应该使用连接池。

例如:

text 复制代码
Application
     ↓
Connection Pool
 ↓ ↓ ↓ ↓ ↓
DB Connections
     ↓
 Database

数据库连接池的作用就是:

提前维护一定数量的连接,让请求复用,而不是每次重新创建。

常见配置:

text 复制代码
pool_size
max_overflow
pool_timeout
pool_recycle

具体数值需要根据数据库和业务压测,而不是照抄一个固定值。


十四、第七步:RAG 的高并发优化

RAG 通常有:

text 复制代码
Embedding
 ↓
Vector Search
 ↓
Rerank
 ↓
LLM

所以 RAG 本身就是一条多阶段链路。

可以针对每一层优化。

1. Embedding 缓存

text 复制代码
query
 ↓
Redis
 ↓
命中 → 直接使用

2. 减少检索数量

不要:

text 复制代码
top_k = 100

然后再让 Rerank 处理 100 个文档。

可以根据效果选择合理的:

text 复制代码
Vector Search top_k = 20
 ↓
Rerank top_k = 5
 ↓
LLM

3. 缓存热点查询

例如:

text 复制代码
"公司的报销制度是什么?"

每天可能有几百个人问。

可以缓存:

text 复制代码
问题
 ↓
RAG结果

减少:

text 复制代码
向量搜索
Rerank
LLM

的重复执行。


十五、第八步:不要让所有请求都直接打到一个模型

生产环境中可以做模型分层。

例如:

text 复制代码
简单问题
 ↓
小模型

复杂问题
 ↓
大模型

需要推理
 ↓
Reasoning Model

需要工具
 ↓
Agent

例如:

text 复制代码
                ┌→ 小模型
用户请求 → Router ┤
                └→ 大模型

简单问题没必要全部调用最贵、最慢的模型。

这实际上也是一种成本和并发优化


十六、第九步:模型服务本身需要并发优化

如果你不是调用第三方 API,而是自己部署模型,那么问题就完全不一样了。

例如:

text 复制代码
FastAPI
 ↓
vLLM
 ↓
GPU

这时候真正的瓶颈可能是:

text 复制代码
GPU显存
GPU计算能力
KV Cache
Batch Size
并发请求数
上下文长度

常见推理框架:

text 复制代码
vLLM
SGLang
TensorRT-LLM

其中 vLLM / SGLang 在大模型推理服务中比较常见。


十七、Continuous Batching 是什么

普通推理可能是:

text 复制代码
请求1
 ↓
模型
 ↓
完成

请求2
 ↓
模型
 ↓
完成

GPU利用率并不高。

Continuous Batching 可以动态把多个请求放到一起处理:

text 复制代码
Request A ─┐
Request B ─┼→ GPU
Request C ─┘

当 A 完成之后:

text 复制代码
Request D

可以继续进入批次,而不需要等整个 Batch 全部完成。

这对于高并发 LLM 推理非常重要。


十八、第十步:流式输出解决的是"用户等待",不是吞吐

AI 应用经常使用:

text 复制代码
stream=True

然后:

text 复制代码
用户提问
 ↓
模型开始生成
 ↓
第一个Token
 ↓
马上显示
 ↓
继续生成

用户感觉会明显更快。

但是需要注意:

流式输出主要降低的是首 Token 感知延迟,并不会直接提升模型的计算能力。

甚至流式连接会保持更长时间,所以并发特别高时,也需要考虑连接数量和资源占用。

因此:

text 复制代码
流式输出 ≠ 高并发方案

它主要解决的是用户体验。


十九、第十一步:设置超时

高并发系统最怕一种情况:

text 复制代码
下游服务卡住
 ↓
请求一直不结束
 ↓
连接一直占用
 ↓
越来越多请求堆积
 ↓
最终整个系统不可用

所以所有外部调用都应该设置 Timeout。

例如:

python 复制代码
async with httpx.AsyncClient(timeout=30) as client:
    response = await client.post(url, json=data)

模型调用、数据库、Redis、第三方 API 都应该考虑超时。


二十、第十二步:重试一定要有条件

例如:

text 复制代码
LLM请求失败
 ↓
马上重试
 ↓
又失败
 ↓
马上重试
 ↓
所有请求一起重试

这可能造成更严重的问题。

这叫:

重试风暴。

正确做法通常是:

text 复制代码
失败
 ↓
判断错误类型
 ↓
是否值得重试?
 ↓
指数退避
 ↓
再次请求

例如:

text 复制代码
第一次:等待 1s
第二次:等待 2s
第三次:等待 4s

而像参数错误:

text 复制代码
400 Bad Request

通常没必要一直重试。


二十一、第十三步:熔断和降级

假设:

text 复制代码
DeepSeek API

突然不可用。

如果你的服务一直:

text 复制代码
请求 → DeepSeek
请求 → DeepSeek
请求 → DeepSeek

最终整个系统都可能被拖垮。

可以做降级:

text 复制代码
主模型不可用
      ↓
备用模型
      ↓
仍不可用
      ↓
返回缓存结果
      ↓
仍不可用
      ↓
友好提示

也可以根据请求类型降级:

text 复制代码
复杂问题 → 大模型

大模型不可用
 ↓
小模型

小模型不可用
 ↓
固定知识库回答

二十二、第十四步:水平扩展

单台服务器最终一定存在上限。

例如:

text 复制代码
             Nginx
               ↓
        ┌──────┼──────┐
        ↓      ↓      ↓
      API-1  API-2  API-3
        ↓      ↓      ↓
             Redis
               ↓
           Database

多个 API 实例共同处理请求。

这就是水平扩展。

常见部署方式:

text 复制代码
Nginx
Docker
Kubernetes
云服务器负载均衡

但这里有一个重要问题:

API 服务最好设计成无状态。

不要把重要状态只保存在某一个 API 进程的内存里。

例如不要:

python 复制代码
conversation_history = {}

然后把用户会话全部放进 Python 内存。

如果:

text 复制代码
请求1 → API-1
请求2 → API-2

就可能出现状态不一致。

应该把状态放到:

text 复制代码
Redis
MySQL
PostgreSQL
MongoDB

等共享存储中。


二十三、AI Agent 的并发架构可以怎么设计

如果是一个比较典型的 Agent 系统,可以考虑:

text 复制代码
                    用户
                     ↓
                  Nginx
                     ↓
               FastAPI API
                     ↓
              ┌──────┴──────┐
              ↓             ↓
            Redis          DB
              ↓
         Agent Service
              ↓
        ┌─────┴─────┐
        ↓           ↓
      Cache       Queue
                    ↓
                  Worker
                    ↓
             ┌──────┼──────┐
             ↓      ↓      ↓
            RAG    Tools   LLM
             ↓      ↓      ↓
          VectorDB  API   Model

各部分职责比较明确:

text 复制代码
Nginx
→ 负载均衡、入口控制

FastAPI
→ 接收请求、鉴权、业务编排

Redis
→ 缓存、限流、短期状态

Queue
→ 削峰、异步任务

Worker
→ 执行耗时任务

VectorDB
→ RAG 检索

Database
→ 持久化业务数据

LLM
→ 推理

模型服务
→ 真正执行模型计算

二十四、真正生产环境不要一上来就上 Kafka + Kubernetes

这是做项目时非常容易犯的错误。

如果你的系统只有:

text 复制代码
10~50并发

可能:

text 复制代码
FastAPI
+ Redis
+ PostgreSQL
+ 向量数据库
+ LLM API

就已经够用了。

如果出现:

text 复制代码
100~500并发

再考虑:

text 复制代码
异步
+ 限流
+ 连接池
+ Redis缓存
+ Worker
+ 消息队列
+ 多实例部署

如果规模继续扩大:

text 复制代码
1000+

再考虑:

text 复制代码
负载均衡
Kubernetes
自动扩缩容
专业消息队列
独立模型服务
模型路由
监控告警

技术选型应该由实际瓶颈推动,而不是为了"看起来像生产环境"把所有组件都装一遍。


二十五、AI 应用高并发技术可以按问题来记

不要死记技术名称,直接按照"解决什么问题"来记。

问题 常用技术
Web 请求阻塞 asyncio、异步 API
请求太多 限流、令牌桶、滑动窗口
相同请求重复计算 Redis、LLM Cache
大量耗时任务 消息队列、Worker
数据库连接不足 Connection Pool
模型调用太多 并发控制、模型路由
LLM 推理太慢 vLLM、SGLang、Batching
单机扛不住 多实例、负载均衡
下游服务挂掉 超时、重试、熔断、降级
RAG 查询太慢 Embedding Cache、检索优化
Agent 执行时间太长 异步任务、任务队列
用户感觉等待太久 Streaming
服务故障无法发现 日志、指标、Tracing、告警

二十六、一个比较实用的 AI 应用高并发技术栈

如果现在让我从零搭一个中小型 AI 应用,我不会一开始就堆很多组件。

可以先从:

text 复制代码
                 Nginx
                   ↓
             FastAPI 多实例
                   ↓
        ┌──────────┼──────────┐
        ↓          ↓          ↓
      Redis    PostgreSQL   VectorDB
        ↓
      Worker
        ↓
       LLM

开始。

其中:

text 复制代码
FastAPI
→ API 服务

Redis
→ 缓存 + 限流 + Session + 队列辅助

PostgreSQL
→ 业务数据

VectorDB
→ RAG

Worker
→ PDF解析、Embedding、批量任务

LLM
→ 推理

然后通过压测观察:

text 复制代码
CPU
内存
QPS
并发数
P50
P95
P99
LLM耗时
数据库耗时
Redis命中率
Token消耗
错误率

真正发现瓶颈之后,再针对瓶颈优化。


二十七、最后总结

AI 应用的高并发并没有一个所谓的"万能技术"。

真正的思路是:

text 复制代码
先减少不必要的请求
        ↓
缓存

再限制请求进入速度
        ↓
限流

再控制下游并发
        ↓
Semaphore / Connection Pool

再把耗时任务异步化
        ↓
Queue + Worker

再提高单机处理能力
        ↓
Async + Batch

单机不够
        ↓
多实例 + Load Balancer

下游不稳定
        ↓
Timeout + Retry + Circuit Breaker + Fallback

模型成为瓶颈
        ↓
模型路由 + vLLM / SGLang + Batching

所以对于 AI 应用来说,高并发优化最重要的不是记住几十个组件,而是学会找到真正的瓶颈在哪里

例如:

text 复制代码
QPS高
→ 看限流

请求等待时间长
→ 看异步和下游耗时

LLM调用太多
→ 看缓存和模型路由

任务执行时间太长
→ 看消息队列

数据库报连接不足
→ 看连接池

GPU利用率低
→ 看Batching和推理框架

单机CPU/内存不足
→ 看水平扩展

第三方模型经常429
→ 看并发控制和限流

这才是 AI 应用高并发比较实际的处理思路。

不要先问"我要不要上 Kafka、Redis、Kubernetes",应该先问:现在系统的瓶颈到底在哪里。

相关推荐
IT_陈寒1 小时前
Vue的这个响应式陷阱,我调试了一整天才爬出来
前端·人工智能·后端
大模型搬砖师1 小时前
不同任务该用哪个模型?企业 AI 网关的智能路由策略手册
人工智能
今夕资源网1 小时前
SayIt语音输入+AI 润色 Typeless 替代品 GitHub开源语音输入法,可本地部署LLM亦可接入deepseek 或者其他大模型。
人工智能·开源·github·输入法·开源输入法·语音输入法
人工智能研究所1 小时前
ResearchStudio-Reel: 学术论文到海报、视频、博客的“最后一公里“
人工智能·microsoft·音视频·博客·ppt·学术论文·ai创作
小e说服饰1 小时前
2026年AI自动生成PPT工具推荐
人工智能·powerpoint
Freak嵌入式1 小时前
RP2040 内核电源调节器:软件可调电压 + 三种模式,低功耗设计的利器
人工智能·单片机·嵌入式硬件·机器人·开源
事变天下1 小时前
冲刺港三所,如何选则香港申请机构?香港留学机构对比及避坑指南
大数据·人工智能
2601_956456341 小时前
哪个品牌的学习机比较好?2026 市场调整期,步步高凭全场景 AI 实力成家庭优选
人工智能
王同学的AI学习日记1 小时前
编程用哪个AI大模型好?实测Qwen3.8和Kimi K3
人工智能·ai