批量与并发怎么撑住
在线检索服务的吞吐取决于批量化与并发控制:把同一批查询向量拼成矩阵一次提交,能摊薄网络往返与调度开销;连接池与超时分开配置,异步框架下要设置并发上限,避免流量高峰把向量库连接打满。上限应当由压测得出,而不是凭经验拍一个数字,因为不同索引与数据规模下的承载能力差别很大。
基本信息
| 批量化 | 一次提交多个查询向量,减少往返次数 |
|---|---|
| 并发控制 | 用信号量或连接池限制同时在途的请求数 |
| 超时 | 单次检索要设置超时并配套降级路径 |
| 参数来源 | 以向量库的 P95 与 P99 压测结果为准 |
典型使用场景
- 批量评测:一次跑几百条查询,批量化能把耗时压缩数倍
- 高峰期保护:并发上限防止单个服务把向量库拖垮
- 多路召回:混合检索需要对同一批查询发起多路请求,适合合并提交
- 成本控制:批量请求减少每条的固定开销
- 降级设计:超时后返回缓存结果或关键词兜底,避免整体不可用
批量与并发
批量与并发
# 差:循环单条,往返开销叠加
for q in queries:
hits = store.search(q, top_k=10)
# 好(库支持时):一次提交矩阵
results = store.search_batch(query_vecs, top_k=10)
import asyncio
SEM = asyncio.Semaphore(32) # 上限按向量库容量压测定
async def search(q_vec):
async with SEM:
return await store.async_search(q_vec, top_k=10, timeout=2.0)
并发参数与依据
| 参数 | 作用 | 调整依据 |
|---|---|---|
| 批大小 | 单次请求包含的查询数 | 单批 P99 延迟与内存占用 |
| 并发上限 | 同时在途的请求数 | 向量库压测出的承载能力 |
| 超时时间 | 单次检索允许的耗时 | P99 加合理余量 |
| 重试策略 | 失败后的补偿动作 | 区分可重试与不可重试错误 |
先压测向量库的 P95 与 P99 与 CPU,再设定服务端并发上限;超时要有降级路径,避免检索服务异常时整个问答链路不可用。
批量不是越大越好:批大小增加会抬高单批延迟与内存占用,一旦超出服务端限制还会整体失败,收益反而消失,建议按 8 到 32 的区间逐档压测。