首页 > 首页 > 数据库 > 向量数据库 > Qdrant > [原创] Qdrant v1.17.0 Bugfix内容深度解析
2026
03-02

[原创] Qdrant v1.17.0 Bugfix内容深度解析

Contents
  1. 简介说明
  2. 一、Bug Fixes:逐条深度分析(v1.17.0 中列出的所有修复)
  3. 二、Improvements:关键优化项逐条说明“优化了什么”
  4. 三、Features:v1.17.0 新增功能解决了哪些核心问题?
  5. 四、综合判断:对你选型/升级的实际意义

简介说明

下面是基于 v1.17.0 官方 Release Notes 已有信息,对“每个 Bug 的触发场景、影响、以及具体解决了什么问题”的系统性分析,重点放在你作为使用/运维 Qdrant 的人,什么时候会踩坑、会出什么问题、升级后具体避免了什么

地址:https://github.com/qdrant/qdrant/releases/tag/v1.17.0

一、Bug Fixes:逐条深度分析(v1.17.0 中列出的所有修复)

1. #7850 – Flush 顺序错误导致 CoW 刷盘中断时可能数据丢失

  • 触发场景
    1. 使用 gridstore / CoW 机制的集合
    2. 存在多个有依赖关系的 segment(例如新 segment 基于老 segment 合并、复制产生)
    3. 在进行 flush(刷盘)​ 时:
      1. 进程被杀、宕机,或
      2. 磁盘瞬时 I/O 错误中断了 flush
  • 影响
    1. Flush 顺序不遵守 segment 依赖:
      1. 有的 segment 刷成“新版本”,有的还保持“旧版本”
      2. 崩溃后从磁盘恢复时,就落在一个“半新半旧”的不一致状态
    2. 在 CoW 模型下,这会直接变成静默数据丢失或回滚
      • 你以为已经确认写入的数据,重启后消失
  • 修复内容 & 解决的问题
    1. 修改 flush 实现,强制按照 segment 依赖关系的拓扑顺序刷盘
      1. 永远先把“被依赖的旧 segment”安全落盘
      2. 再写依赖它的新 segment
    2. 这样即使中途崩溃,恢复后要么全是“旧世界”,要么是“新世界”,不再出现混杂状态
    3. 对你意味着:在异常中断(kill/宕机)时,数据持久化语义更可靠,不会“部分成功部分失败”

2. #8103 – 流式记录传输(stream records transfer)中的数据竞争,可能漏掉正在写入的更新

  • 触发场景
    1. 集群下存在:
      1. 分片迁移(shard transfer)
      2. 副本同步
    2. Qdrant 使用 stream records transfer 从源节点向目标节点同步数据
    3. 同一时间源节点上仍有并发写入(insert / update / delete)
  • 影响
    1. 由于内部有 data race:
      1. 部分并发写入没有被纳入传输流,被静默丢失
    2. 迁移/同步结束后:
      1. 源节点和目标节点看起来“都成功”
      2. 实际上目标落后一些更新 → 副本不一致,并且不会自动修复
  • 修复内容
    1. 修正并发访问逻辑,保证:
      1. 在某个时间边界之前的所有更新,都能被正确捕获并传输
    2. 实际效果:
      1. 在分片迁移、扩容、重平衡时,不会因为并发写入导致副本静默漏数据

3. #7983 – 创建 Payload 索引时的互锁问题

  • 触发场景
    1. 对集合上的 payload 字段创建索引(例如 keyword/integer 索引)
    2. 同时有其他管理操作或者并发索引操作
    3. 内部锁使用方式不当,导致“互锁”(interlocking)
  • 影响
    1. 索引创建可能:
      1. 长时间卡住
      2. 影响其他依赖相同锁的操作(例如集合更新、优化任务)
    2. 在你这边表现为:
      1. 建索引的 API/CLI 卡死或超时
      2. 集合长时间保持在 yellow / “optimizing” 状态
  • 修复内容
    1. 优化锁粒度和锁顺序,让 payload 索引构建与集合其他操作不产生死锁/长时间互锁
    2. 效果:在有大量索引任务时,其他集合级操作不再被拖死,索引创建过程也更稳定

4. #7999 – 集合级更新操作的互锁问题

  • 触发场景
    1. 调用集合级更新:
      1. 修改 optimizer_config
      2. 调整 hnsw_config
      3. 修改分片、复制因子等
    2. 同时存在其他后台操作(优化、索引构建等)
  • 影响
    1. 集合级更新被卡住,可能导致:
      1. API 超时
      2. 集合状态长时间卡在中间态
    2. 对运维来说,更新配置的操作不可靠
  • 修复内容
    1. 重新整理集合级更新与内部任务之间的锁交互方式
    2. 避免两边互相等待,提升整体可用性

5. #8131 – Snapshot 创建过程中并发更新导致死锁

  • 触发场景
    1. 对集合或集群执行 snapshot 创建
    2. 同时仍有大量更新请求进来
    3. Snapshot 过程和更新过程在锁层面形成环形依赖
  • 影响
    1. 典型死锁症状:
      1. 所有请求(读写)都卡住
      2. CPU 占用可能不高,但延迟无限上升
      3. 容器/进程最终可能被外部强制 kill
    2. 在生产非常危险:一次快照把整库锁死
  • 修复内容
    1. 调整锁顺序和粒度,使 snapshot 和 update 可以安全并行或正确让路
    2. 之后你可以放心地边 running 边打 snapshot,顶多 snapshot 稍微慢一点,而不会锁死服务

6. #8128 – gRPC/HTTP2 出现 too_many_internal_resets 错误

  • 触发场景
    1. 使用 gRPC/HTTP2 通信
    2. 存在大量:
      1. 客户端取消请求
      2. 超时重试
    3. Qdrant 内部取消请求的实现方式不符合 HTTP2 对 reset 的预期
  • 影响
    1. 频繁出现 too_many_internal_resets 错误:
      1. 客户端 SDK 日志充满 HTTP2 错误
      2. 高并发下请求随机失败
    2. 影响整体吞吐和稳定性
  • 修复内容
    1. 改进内部取消请求机制:
      1. 控制 reset 的使用
      2. 符合 HTTP2 协议预期
    2. 实际效果:gRPC/HTTP2 连接更稳定,高并发+超时+重试场景下错误率明显下降

7. #8019 – 连接池中 HTTP2 通道关闭处理不当

  • 触发场景
    1. 高并发下使用连接池
    2. 连接频繁关闭、重建(例如负载均衡、网络抖动)
  • 影响
    1. 若连接池未正确感知和清理已关闭 channel:
      1. 向“死连接”发请求 → 失败/超时
      2. FD/内存泄漏,长期运行后“神秘变慢或崩溃”
  • 修复内容
    1. 增强连接池对已关闭 channel 的检测与清理
    2. 避免向无效连接发请求,降低资源泄漏风险

8. #8104 – WAL 与 shard 时钟快照中的数据竞争

  • 触发场景
    1. 对 WAL 和 shard 内部时钟做快照:
      1. snapshot
      2. 增量同步 / 复制
    2. 同时有写入在不断推进 WAL
  • 影响
    1. 若快照获取过程中发生 data race:
      1. 快照记录的“版本时间”与 WAL 实际状态不一致
    2. 导致:
      1. 恢复/复制时认为自己已同步到某时间点,实际仅部分更新被包含
      2. 再次出现静默落后的副本
  • 修复内容
    1. 使 WAL 和 shard clock 快照读取在同一一致视图下完成
    2. 保障基于快照做的增量同步“时间线干净”,从而保证副本真正 up-to-date

9. #7961 – 部分快照 manifest 使用错误版本号

  • 触发场景
    1. 使用 partial snapshot(只导部分集合/分片)
    2. 集合正在持续有写入,内部版本不断推进
  • 影响
    1. manifest 中记载的版本号与真实数据版本不一致:
      1. 增量恢复时以为“版本已追平”,实际仍有差异
      2. 导致增量回放缺失或重复
  • 修复内容
    1. 规范 partial snapshot manifest 版本号生成逻辑,确保与实际数据版本对齐
    2. 保证恢复/同步时版本判断正确

10. #8095 – 分片快照传输使用了错误内部协议

  • 触发场景
    1. 通过 snapshot 在节点间传输 shard(典型在集群模式中)
  • 影响
    1. 使用了与当前版本不匹配的内部协议:
      1. 传输失败
      2. 或卡在 transferring / partial 状态
      3. 或导入后 shard 行为异常
  • 修复内容
    1. 将 shard snapshot 传输逻辑统一为正确版本的内部协议
    2. 使 shard 级快照迁移在 v1.17.0 上行为可预期、稳定

11. #7950 – 高 limit 的 query batch 整数溢出

  • 触发场景
    1. 使用批量查询接口(batch query)
    2. 不小心配置了异常大的 limit(例如来自上游 bug/错误配置)
  • 影响
    1. 内部使用不合适的整数类型引发溢出:
      1. 返回条数莫名其妙
      2. 或在极端情况下引发 panic → 节点崩溃
  • 修复内容
    1. 修正整数类型、加入边界检查:
      1. 对超大 limit 直接报错,而不是溢出/崩溃
    2. 提升 API 对异常参数的“防御性”

12. #7972 – limit=0 时搜索聚合器 panic

  • 触发场景
    1. 查询时设置 limit = 0:
      1. 仅想拿 aggregate/统计结果,不需要任何 point
      2. 或 SDK 默认行为
  • 影响
    1. 聚合器没考虑 limit=0 的分支:
      1. 直接 panic
      2. 导致整个 Qdrant 节点进程崩溃
  • 修复内容
    1. 显式支持 limit=0:
      1. 返回空结果/仅返回统计信息
    2. 让“边界参数”不再是一击必杀

13. #8100 – 整型索引未正确使用 round 后的浮点值(JSON 不区分 int/float)

  • 触发场景
    1. payload 字段建了 integer 索引
    2. 实际查询时通过 JSON 传入的是 3.0 这种浮点数字(很多语言/SDK 默认把数字解析成 float)
  • 影响
    1. 内部未正确做 float → int 的 round:
      1. 3.0 匹配不到索引中存储的 3
    2. 业务表现为:过滤条件逻辑上应该命中,结果被漏掉
  • 修复内容
    1. 在整型索引匹配时,对浮点数进行合理 round/转换
    2. 提升 JSON 数值处理的直觉一致性,减少莫名其妙的“查不到”

14. #8097 – 使用 score boosting 的查询中 score_threshold 不生效

  • 触发场景
    1. 使用 Hybrid/HNSW + payload scoring 的得分增强查询
    2. 同时设置 score_threshold 过滤低分结果
  • 影响
    1. threshold 被忽略:
      1. 低分结果仍被返回
      2. 结果集过大,浪费网络和下游处理资源
    2. 业务上需要额外手动过滤
  • 修复内容
    1. 将 score_threshold 正确套用在 score boosting 查询的最终得分上
    2. 现在服务端会直接丢弃低于阈值的结果 → 结果集更干净、延迟略降

15. #7877 – 磁盘写满时触发 Corrupted ID tracker mapping storage

  • 触发场景
    1. 磁盘空间被写满(快照、日志、海量向量等)
    2. 仍持续进行写入/更新
  • 影响
    1. ID tracker 映射结构被破坏:
      1. 某些点永远找不到或删除不了
      2. segment 结构损坏,可能整个集合无法正常工作
    2. 这是极其严重的数据结构损坏问题
  • 修复内容
    1. 改进“磁盘满”场景下的行为:
      1. 停止继续向损坏方向写入
      2. 拒绝新写入,但保护现有结构不被进一步破坏
    2. 对你而言:磁盘打满最坏情况变成“写入失败”,而不是“库被写坏”

16. #7944 – gRPC API 响应状态在监控中的统计错误

  • 触发场景
    1. 通过 Prometheus/OpenMetrics 监控 Qdrant gRPC 接口
    2. 依赖请求状态(成功/失败)指标构建 SLA/SLO
  • 影响
    1. 响应状态计数不准确:
      1. 成功/失败混淆
      2. 告警与可视化不可信
  • 修复内容
    1. 修正 gRPC 响应状态在遥测中的统计逻辑
    2. 让基于 metrics 的报警/容量规划更可靠

17. #7857 – replicate points + filter 时进度统计错误

  • 触发场景
    1. 使用 replicate_points 或类似 API
    2. 仅复制满足某 filter 条件的一部分点(增量分发/多租户)
  • 影响
    1. Progress tracker 的“总数/已完成数”错误:
      1. 进度条显示 0% 或已经 100% 但实际未完成
    2. 运维容易误判复制是否完成,进而错误地切流量或销毁旧集群
  • 修复内容
    1. 进度统计改为基于实际“被 filter 中的数据”
    2. 让带过滤的复制进度可视化真实可信

18. #7856 – 自定义分片 + 空集合时创建 payload 索引失败

  • 触发场景
    1. 集合使用 user-defined sharding
    2. 集合当前还没有任何 point(空)
    3. 希望“先创建 payload 索引,再导数”
  • 影响
    1. 索引创建失败或行为异常:
      1. 不得不改为“先导入数据再建索引”
      2. 导入流程更复杂、索引构建对导入过程影响更大
  • 修复内容
    1. 支持在“空集合 + 自定义分片”组合下正常创建 payload 索引
    2. 使得标准化流程“建表/建索引 → 导数据”在分布式模式下也成立

19. #8099 – 内部请求忽略已配置的 CA 证书

  • 触发场景
    1. 集群内部使用 TLS / mTLS
    2. 配置了 CA 证书,希望所有节点间通信都基于它验权
  • 影响
    1. 部分内部请求路径没用配置的 CA:
      1. 要么握手失败、通信不稳定
      2. 要么产生“部分加密/部分不加密”的不一致安全边界
  • 修复内容
    1. 修正所有内部请求对 CA 设置的使用
    2. 保证集群内所有通道统一基于配置的 CA 验证,提高安全性与行为一致性

20. #8176 – 某些 API 端点缺失 timeout 参数

  • 触发场景
    1. 部分 API 没有 timeout 控制
    2. 在异常或网络抖动下,请求无限挂起
  • 影响
    1. 上游调用栈被拖死,无法收敛/重试
    2. 整体服务质量下降
  • 修复内容
    1. 为缺失 timeout 的端点补充 timeout 参数
    2. 提高 API 的“可控性”和故障自恢复能力

二、Improvements:关键优化项逐条说明“优化了什么”

这里只挑对生产环境最重要的几大类说明,每一条都来自官方“Improvements 🤸”列表。

1. I/O & Snapshot 性能

  • #8025 / #8059 / #7883:snapshot 恢复 & 刷盘流程优化
    1. 不再创建临时中间文件,直接恢复到目标文件系统
    2. 使用 syncfs 批量刷盘,提高大量小文件持久化效率
    3. 效果:快照恢复时间显著缩短,磁盘 IO、空间占用压力明显降低
  • #8072:snapshot 创建不再锁住 shard holder
    1. 之前:snapshot 时阻塞分片级操作
    2. 现在:snapshot 与正常请求可并行,减少对线上读写的干扰
  • #8166:snapshot 下载增加超时
    1. 网络卡住时可自动放弃,不会长时间占用资源/连接

2. 锁竞争 & 并发调度

  • #8007 / #8056:segments 锁方式改进
    1. 减少读写之间的锁冲突
    2. 提升高并发场景下整体吞吐和 tail latency
  • #8105:单 shard 并行更新数限制为 64
    1. 防止超多并行更新导致顺序跟踪/内存开销炸裂
    2. 在高并发写入场景中平衡“吞吐 vs 稳定性”
  • #8169:降低 Gridstore 中的锁持有时间
    1. 直接收敛为搜索尾延迟的下降,尤其是“高写入+高读取”的双高场景
  • #8164:closed WAL segment 的 cache 主动释放
    1. 减少长期运行中的内存占用和碎片
  • #8093:序列化新 update 时不再锁整个 WAL
    1. 大批量写入场景下减少锁带来的全局等待,提高整体写入吞吐

3. 索引与搜索性能

  • #7952:禁用未索引字段的 in-place payload 更新
    1. 提高索引 Segment 的不可变性(immutability),使部分快照更可靠
    2. 从侧面提升数据一致性和恢复安全
  • #7887 / #8125:可禁用 payload 索引的额外 HNSW 边 & 对删除向量不构建额外边
    1. 降低构建 payload 索引的 CPU/内存开销
    2. 对某些负载(不需要极致 payload 召回质量)可有效提高导入/更新速度
  • #8163 / #8175:改进高 limit 场景下的结果处理 & HNSW 过滤搜索的内存分配
    1. 在 limit 很大时减少不必要操作
    2. 降低内存分配与 GC 频率,提升高 limit 查询的稳定性与性能

4. 存储与系统特性

  • #7971:启用“单文件 mmap”向量存储模式
    1. 减少文件句柄、简化管理
    2. 提升启动和加载速度(大集合场景尤其明显)
  • #7928:批量读取向量时使用 io_uring
    1. 更充分发挥新内核异步 I/O 能力,降低 IOPS 开销
  • #7834:当副本挂掉时延长 WAL 保留时间
    1. 避免因为副本下线时间长而被迫 full shard transfer
    2. 提升副本恢复的资源效率(更多使用增量追赶)
  • #7565:禁用 1.15.0 以来废弃的旧 shard key 格式
    1. 清理兼容债务,为后续版本演进做准备

5. 配置 & 可用性

  • #8053:可配置 collections/shards/segments 的 load 并发度
    1. 比如启动时恢复一堆大集合,可以根据环境调整并发,避免“瞬时 I/O 风暴”
  • #7809:更便捷地为外部推理/embedding provider 提供 API-keys
    1. 简化与 OpenAI、Azure、Anthropic 等外部模型服务集成时的配置管理
  • #7919:改进 datetime 解析出错提示
    1. 虽然看似小变更,但对排障体验很关键

三、Features:v1.17.0 新增功能解决了哪些核心问题?

来自“Features 🏋️”列表,这些是 1.17 的卖点功能。

1. 搜索质量与检索策略

  • Relevance Feedback(相关反馈检索) – milestone#38
    1. 场景:用户对部分结果点“标注”类似“相关/不相关”,希望用这些反馈动态优化下一轮搜索
    2. 意义
      1. 向量数据库层面原生支持 relevance feedback,不必在业务层重复管理复杂逻辑
      2. 对 RAG、推荐系统、交互式搜索效果提升巨大
    3. 解决的问题:让搜索能“听懂”用户反馈,逐步靠近真正需求,而不是一次向量检索定死。
  • Weighted RRF(加权 Reciprocal Rank Fusion) – #8063
    1. 场景:混合多路检索(dense / sparse / BM25 / 其他模型),不同检索路劲重要性不同
    2. 意义
      1. 默认 RRF 给每路查询同等权重,这在实际中经常不合理
      2. Weighted RRF 允许你对不同子查询设置不同权重
    3. 解决的问题:混合搜索时,可以更精准地调节“谁说了算”(比如更信 dense、或者更信 BM25)。
  • Upsert update_mode 参数 – #7963
    1. 场景
      1. 只允许“插入新点,不覆盖旧点”(insert-only)
      2. 或只允许“更新存在点,不新建”(update-only)
    2. 意义
      • 避免业务误用 upsert 导致“老数据被覆盖”或“无意创建垃圾点”
    3. 解决的问题:提供了更严格的数据写入语义控制,对数据质量敏感的业务很关键。

2. 延迟与吞吐(低延迟搜索)

  • “Unlimited update queue” – milestone#43
    1. 结合官方博客可知,这实际上是更智能的 update queue 设计(文案中“unlimited”更多是语义上不再用小 buffer 限制写入):
      1. 能平滑 absorb 写入高峰
      2. 结合后续的 prevent_unoptimized 设置(见 #7643),避免未优化 segment 冲垮搜索性能
    2. 解决的问题:在写入突增场景,不再丢写/卡写,而是在可控地排队+节流
  • 控制 update 吞吐、防止未优化搜索 – #7643
    1. 场景:高写入+高读混合负载
    2. 痛点
      1. 如果写入很猛,优化器来不及合并/建索引,会堆出很多 unoptimized segment → 查询变慢
    3. 功能:新增配置,让系统在“优化跟不上时”主动节流写入,避免 unoptimized segment 爆炸
    4. 效果:在高写入环境下显著提升搜索延迟稳定性(尤其是 P95/P99)。
  • 可配置 read fan-out delay – #7929
    1. 场景:分布式集群,多副本查询时,某副本偶尔很慢(tail latency 问题)
    2. 机制
      1. 正常情况下先发请求到一个或少数副本
      2. 若在“可配置延迟阈值”内没回复,再 fan-out 到其他副本
    3. 解决的问题:降低 P99 延迟,同时避免对所有查询都一开始 fan-out 到所有副本那种“资源浪费”。

3. 观测性 & 运维

  • 优化进度与阶段 API – milestone#44
    1. 场景:你想知道某集合的优化(建索引、segment 合并)具体进行到哪一步,而不是只看到 yellow。
    2. 功能
      1. 新 API 暴露详细的优化阶段和进度百分比
    3. 解决痛点
      1. 帮助判断“是正常慢”还是“卡死了”;
      2. 可以在运维面板中展示优化 timeline。
  • 集群聚合遥测 API – milestone#40
    1. 场景:分布式部署,需要一眼看到整个集群:
      1. peers、collections、shard transfers、resharding 状态等
    2. 意义
      1. 原来可能需要逐节点抓 metrics 再聚合
      2. 现在有 cluster 视角的 telemetry,一次调用拿整体状态
    3. 解决问题:运维/监控实现难度大幅下降,可视化更友好。
  • Dedicated /metrics HTTP 端口 – #7838
    1. 场景:Prometheus/监控系统抓取指标
    2. 意义
      1. 将 /metrics 暴露在一个单独端口 → 避免与业务 REST 流量互相影响
    3. 解决问题
      1. 安全(可以只对白名单开放 metrics 端口)
      2. 稳定(监控抓 metrics 不会与业务请求争同一监听)
  • Audit Access Logging – #8071
    1. 场景:有合规要求,需要审计谁在什么时候对哪些资源做了什么操作
    2. 功能
      1. 对所有需要认证/鉴权的 API 操作记录详细 log
    3. 意义
      1. 支持安全审计、异常行为分析、合规检查
  • 二级 API Key 支持 – #7835
    1. 场景:你想轮换 API key,但不能停机
    2. 功能
      1. 支持 primary + secondary API key,并行生效一段时间
    3. 解决问题
      1. 实现真正的“零停机密钥轮换”

4. 分布式与分片管理

  • 列出 Shard Keys 的 API – #7615
    1. 场景:使用 user-defined sharding,把不同租户/业务线分布到不同 shard key
    2. 功能
      1. 增加 API 列出所有 user-defined shard keys
    3. 价值
      1. 方便检查分片策略、做迁移/重平衡决策

四、综合判断:对你选型/升级的实际意义

  • 如果你在生产用集群模式(多节点、多副本)​
    1. 多个 bug fix(#7850, #8103, #8104, #7961, #8095, #7877 等)都是实打实的数据一致性与持久化风险补洞
    2. 建议:v1.17.0 应视为 1.17.x 系列的最低生产版本
  • 如果你的负载是“高写入 + 高查询”
    1. “无限更新队列”+prevent_unoptimized+可配置 read fan-out delay 等组合,几乎就是专门针对“写多读多”瓶颈做的系统级优化
    2. 可以显著降低高写场景下搜索延迟的波动(P95/P99)。
  • 如果你做的是 RAG / 搜索 / 推荐
    1. Relevance Feedback + Weighted RRF + update_mode
    2. 给你更多“控制检索质量 & 行为”的旋钮,而不是只能一味调 HNSW 参数。
  • 如果你有审计、安全、合规要求
    1. Audit Logging + CA 修复 + 二级 API key
    2. 让 Qdrant 更符合企业环境安全标准。

最后编辑:
作者:摘星怪
这个作者貌似有点懒,什么都没有留下。

留下一个回复

你的email不会被公开。