Contents
- 简介说明
- 一、Bug Fixes:逐条深度分析(v1.17.0 中列出的所有修复)
- 1. #7850 – Flush 顺序错误导致 CoW 刷盘中断时可能数据丢失
- 2. #8103 – 流式记录传输(stream records transfer)中的数据竞争,可能漏掉正在写入的更新
- 3. #7983 – 创建 Payload 索引时的互锁问题
- 4. #7999 – 集合级更新操作的互锁问题
- 5. #8131 – Snapshot 创建过程中并发更新导致死锁
- 6. #8128 – gRPC/HTTP2 出现 too_many_internal_resets 错误
- 7. #8019 – 连接池中 HTTP2 通道关闭处理不当
- 8. #8104 – WAL 与 shard 时钟快照中的数据竞争
- 9. #7961 – 部分快照 manifest 使用错误版本号
- 10. #8095 – 分片快照传输使用了错误内部协议
- 11. #7950 – 高 limit 的 query batch 整数溢出
- 12. #7972 – limit=0 时搜索聚合器 panic
- 13. #8100 – 整型索引未正确使用 round 后的浮点值(JSON 不区分 int/float)
- 14. #8097 – 使用 score boosting 的查询中 score_threshold 不生效
- 15. #7877 – 磁盘写满时触发 Corrupted ID tracker mapping storage
- 16. #7944 – gRPC API 响应状态在监控中的统计错误
- 17. #7857 – replicate points + filter 时进度统计错误
- 18. #7856 – 自定义分片 + 空集合时创建 payload 索引失败
- 19. #8099 – 内部请求忽略已配置的 CA 证书
- 20. #8176 – 某些 API 端点缺失 timeout 参数
- 二、Improvements:关键优化项逐条说明“优化了什么”
- 三、Features:v1.17.0 新增功能解决了哪些核心问题?
- 四、综合判断:对你选型/升级的实际意义
简介说明
下面是基于 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 刷盘中断时可能数据丢失
- 触发场景
- 使用 gridstore / CoW 机制的集合
- 存在多个有依赖关系的 segment(例如新 segment 基于老 segment 合并、复制产生)
- 在进行 flush(刷盘) 时:
- 进程被杀、宕机,或
- 磁盘瞬时 I/O 错误中断了 flush
- 影响
- Flush 顺序不遵守 segment 依赖:
- 有的 segment 刷成“新版本”,有的还保持“旧版本”
- 崩溃后从磁盘恢复时,就落在一个“半新半旧”的不一致状态
- 在 CoW 模型下,这会直接变成静默数据丢失或回滚:
- 你以为已经确认写入的数据,重启后消失
- Flush 顺序不遵守 segment 依赖:
- 修复内容 & 解决的问题
- 修改 flush 实现,强制按照 segment 依赖关系的拓扑顺序刷盘:
- 永远先把“被依赖的旧 segment”安全落盘
- 再写依赖它的新 segment
- 这样即使中途崩溃,恢复后要么全是“旧世界”,要么是“新世界”,不再出现混杂状态
- 对你意味着:在异常中断(kill/宕机)时,数据持久化语义更可靠,不会“部分成功部分失败”
- 修改 flush 实现,强制按照 segment 依赖关系的拓扑顺序刷盘:
2. #8103 – 流式记录传输(stream records transfer)中的数据竞争,可能漏掉正在写入的更新
- 触发场景
- 集群下存在:
- 分片迁移(shard transfer)
- 副本同步
- Qdrant 使用 stream records transfer 从源节点向目标节点同步数据
- 同一时间源节点上仍有并发写入(insert / update / delete)
- 集群下存在:
- 影响
- 由于内部有 data race:
- 部分并发写入没有被纳入传输流,被静默丢失
- 迁移/同步结束后:
- 源节点和目标节点看起来“都成功”
- 实际上目标落后一些更新 → 副本不一致,并且不会自动修复
- 由于内部有 data race:
- 修复内容
- 修正并发访问逻辑,保证:
- 在某个时间边界之前的所有更新,都能被正确捕获并传输
- 实际效果:
- 在分片迁移、扩容、重平衡时,不会因为并发写入导致副本静默漏数据
- 修正并发访问逻辑,保证:
3. #7983 – 创建 Payload 索引时的互锁问题
- 触发场景
- 对集合上的 payload 字段创建索引(例如 keyword/integer 索引)
- 同时有其他管理操作或者并发索引操作
- 内部锁使用方式不当,导致“互锁”(interlocking)
- 影响
- 索引创建可能:
- 长时间卡住
- 影响其他依赖相同锁的操作(例如集合更新、优化任务)
- 在你这边表现为:
- 建索引的 API/CLI 卡死或超时
- 集合长时间保持在 yellow / “optimizing” 状态
- 索引创建可能:
- 修复内容
- 优化锁粒度和锁顺序,让 payload 索引构建与集合其他操作不产生死锁/长时间互锁
- 效果:在有大量索引任务时,其他集合级操作不再被拖死,索引创建过程也更稳定
4. #7999 – 集合级更新操作的互锁问题
- 触发场景
- 调用集合级更新:
- 修改 optimizer_config
- 调整 hnsw_config
- 修改分片、复制因子等
- 同时存在其他后台操作(优化、索引构建等)
- 调用集合级更新:
- 影响
- 集合级更新被卡住,可能导致:
- API 超时
- 集合状态长时间卡在中间态
- 对运维来说,更新配置的操作不可靠
- 集合级更新被卡住,可能导致:
- 修复内容
- 重新整理集合级更新与内部任务之间的锁交互方式
- 避免两边互相等待,提升整体可用性
5. #8131 – Snapshot 创建过程中并发更新导致死锁
- 触发场景
- 对集合或集群执行 snapshot 创建
- 同时仍有大量更新请求进来
- Snapshot 过程和更新过程在锁层面形成环形依赖
- 影响
- 典型死锁症状:
- 所有请求(读写)都卡住
- CPU 占用可能不高,但延迟无限上升
- 容器/进程最终可能被外部强制 kill
- 在生产非常危险:一次快照把整库锁死
- 典型死锁症状:
- 修复内容
- 调整锁顺序和粒度,使 snapshot 和 update 可以安全并行或正确让路
- 之后你可以放心地边 running 边打 snapshot,顶多 snapshot 稍微慢一点,而不会锁死服务
6. #8128 – gRPC/HTTP2 出现 too_many_internal_resets 错误
- 触发场景
- 使用 gRPC/HTTP2 通信
- 存在大量:
- 客户端取消请求
- 超时重试
- Qdrant 内部取消请求的实现方式不符合 HTTP2 对 reset 的预期
- 影响
- 频繁出现 too_many_internal_resets 错误:
- 客户端 SDK 日志充满 HTTP2 错误
- 高并发下请求随机失败
- 影响整体吞吐和稳定性
- 频繁出现 too_many_internal_resets 错误:
- 修复内容
- 改进内部取消请求机制:
- 控制 reset 的使用
- 符合 HTTP2 协议预期
- 实际效果:gRPC/HTTP2 连接更稳定,高并发+超时+重试场景下错误率明显下降
- 改进内部取消请求机制:
7. #8019 – 连接池中 HTTP2 通道关闭处理不当
- 触发场景
- 高并发下使用连接池
- 连接频繁关闭、重建(例如负载均衡、网络抖动)
- 影响
- 若连接池未正确感知和清理已关闭 channel:
- 向“死连接”发请求 → 失败/超时
- FD/内存泄漏,长期运行后“神秘变慢或崩溃”
- 若连接池未正确感知和清理已关闭 channel:
- 修复内容
- 增强连接池对已关闭 channel 的检测与清理
- 避免向无效连接发请求,降低资源泄漏风险
8. #8104 – WAL 与 shard 时钟快照中的数据竞争
- 触发场景
- 对 WAL 和 shard 内部时钟做快照:
- snapshot
- 增量同步 / 复制
- 同时有写入在不断推进 WAL
- 对 WAL 和 shard 内部时钟做快照:
- 影响
- 若快照获取过程中发生 data race:
- 快照记录的“版本时间”与 WAL 实际状态不一致
- 导致:
- 恢复/复制时认为自己已同步到某时间点,实际仅部分更新被包含
- 再次出现静默落后的副本
- 若快照获取过程中发生 data race:
- 修复内容
- 使 WAL 和 shard clock 快照读取在同一一致视图下完成
- 保障基于快照做的增量同步“时间线干净”,从而保证副本真正 up-to-date
9. #7961 – 部分快照 manifest 使用错误版本号
- 触发场景
- 使用 partial snapshot(只导部分集合/分片)
- 集合正在持续有写入,内部版本不断推进
- 影响
- manifest 中记载的版本号与真实数据版本不一致:
- 增量恢复时以为“版本已追平”,实际仍有差异
- 导致增量回放缺失或重复
- manifest 中记载的版本号与真实数据版本不一致:
- 修复内容
- 规范 partial snapshot manifest 版本号生成逻辑,确保与实际数据版本对齐
- 保证恢复/同步时版本判断正确
10. #8095 – 分片快照传输使用了错误内部协议
- 触发场景
- 通过 snapshot 在节点间传输 shard(典型在集群模式中)
- 影响
- 使用了与当前版本不匹配的内部协议:
- 传输失败
- 或卡在 transferring / partial 状态
- 或导入后 shard 行为异常
- 使用了与当前版本不匹配的内部协议:
- 修复内容
- 将 shard snapshot 传输逻辑统一为正确版本的内部协议
- 使 shard 级快照迁移在 v1.17.0 上行为可预期、稳定
11. #7950 – 高 limit 的 query batch 整数溢出
- 触发场景
- 使用批量查询接口(batch query)
- 不小心配置了异常大的 limit(例如来自上游 bug/错误配置)
- 影响
- 内部使用不合适的整数类型引发溢出:
- 返回条数莫名其妙
- 或在极端情况下引发 panic → 节点崩溃
- 内部使用不合适的整数类型引发溢出:
- 修复内容
- 修正整数类型、加入边界检查:
- 对超大 limit 直接报错,而不是溢出/崩溃
- 提升 API 对异常参数的“防御性”
- 修正整数类型、加入边界检查:
12. #7972 – limit=0 时搜索聚合器 panic
- 触发场景
- 查询时设置 limit = 0:
- 仅想拿 aggregate/统计结果,不需要任何 point
- 或 SDK 默认行为
- 查询时设置 limit = 0:
- 影响
- 聚合器没考虑 limit=0 的分支:
- 直接 panic
- 导致整个 Qdrant 节点进程崩溃
- 聚合器没考虑 limit=0 的分支:
- 修复内容
- 显式支持 limit=0:
- 返回空结果/仅返回统计信息
- 让“边界参数”不再是一击必杀
- 显式支持 limit=0:
13. #8100 – 整型索引未正确使用 round 后的浮点值(JSON 不区分 int/float)
- 触发场景
- payload 字段建了 integer 索引
- 实际查询时通过 JSON 传入的是
3.0这种浮点数字(很多语言/SDK 默认把数字解析成 float)
- 影响
- 内部未正确做 float → int 的 round:
- 3.0 匹配不到索引中存储的 3
- 业务表现为:过滤条件逻辑上应该命中,结果被漏掉
- 内部未正确做 float → int 的 round:
- 修复内容
- 在整型索引匹配时,对浮点数进行合理 round/转换
- 提升 JSON 数值处理的直觉一致性,减少莫名其妙的“查不到”
14. #8097 – 使用 score boosting 的查询中 score_threshold 不生效
- 触发场景
- 使用 Hybrid/HNSW + payload scoring 的得分增强查询
- 同时设置 score_threshold 过滤低分结果
- 影响
- threshold 被忽略:
- 低分结果仍被返回
- 结果集过大,浪费网络和下游处理资源
- 业务上需要额外手动过滤
- threshold 被忽略:
- 修复内容
- 将 score_threshold 正确套用在 score boosting 查询的最终得分上
- 现在服务端会直接丢弃低于阈值的结果 → 结果集更干净、延迟略降
15. #7877 – 磁盘写满时触发 Corrupted ID tracker mapping storage
- 触发场景
- 磁盘空间被写满(快照、日志、海量向量等)
- 仍持续进行写入/更新
- 影响
- ID tracker 映射结构被破坏:
- 某些点永远找不到或删除不了
- segment 结构损坏,可能整个集合无法正常工作
- 这是极其严重的数据结构损坏问题
- ID tracker 映射结构被破坏:
- 修复内容
- 改进“磁盘满”场景下的行为:
- 停止继续向损坏方向写入
- 拒绝新写入,但保护现有结构不被进一步破坏
- 对你而言:磁盘打满最坏情况变成“写入失败”,而不是“库被写坏”
- 改进“磁盘满”场景下的行为:
16. #7944 – gRPC API 响应状态在监控中的统计错误
- 触发场景
- 通过 Prometheus/OpenMetrics 监控 Qdrant gRPC 接口
- 依赖请求状态(成功/失败)指标构建 SLA/SLO
- 影响
- 响应状态计数不准确:
- 成功/失败混淆
- 告警与可视化不可信
- 响应状态计数不准确:
- 修复内容
- 修正 gRPC 响应状态在遥测中的统计逻辑
- 让基于 metrics 的报警/容量规划更可靠
17. #7857 – replicate points + filter 时进度统计错误
- 触发场景
- 使用 replicate_points 或类似 API
- 仅复制满足某 filter 条件的一部分点(增量分发/多租户)
- 影响
- Progress tracker 的“总数/已完成数”错误:
- 进度条显示 0% 或已经 100% 但实际未完成
- 运维容易误判复制是否完成,进而错误地切流量或销毁旧集群
- Progress tracker 的“总数/已完成数”错误:
- 修复内容
- 进度统计改为基于实际“被 filter 中的数据”
- 让带过滤的复制进度可视化真实可信
18. #7856 – 自定义分片 + 空集合时创建 payload 索引失败
- 触发场景
- 集合使用 user-defined sharding
- 集合当前还没有任何 point(空)
- 希望“先创建 payload 索引,再导数”
- 影响
- 索引创建失败或行为异常:
- 不得不改为“先导入数据再建索引”
- 导入流程更复杂、索引构建对导入过程影响更大
- 索引创建失败或行为异常:
- 修复内容
- 支持在“空集合 + 自定义分片”组合下正常创建 payload 索引
- 使得标准化流程“建表/建索引 → 导数据”在分布式模式下也成立
19. #8099 – 内部请求忽略已配置的 CA 证书
- 触发场景
- 集群内部使用 TLS / mTLS
- 配置了 CA 证书,希望所有节点间通信都基于它验权
- 影响
- 部分内部请求路径没用配置的 CA:
- 要么握手失败、通信不稳定
- 要么产生“部分加密/部分不加密”的不一致安全边界
- 部分内部请求路径没用配置的 CA:
- 修复内容
- 修正所有内部请求对 CA 设置的使用
- 保证集群内所有通道统一基于配置的 CA 验证,提高安全性与行为一致性
20. #8176 – 某些 API 端点缺失 timeout 参数
- 触发场景
- 部分 API 没有 timeout 控制
- 在异常或网络抖动下,请求无限挂起
- 影响
- 上游调用栈被拖死,无法收敛/重试
- 整体服务质量下降
- 修复内容
- 为缺失 timeout 的端点补充 timeout 参数
- 提高 API 的“可控性”和故障自恢复能力
二、Improvements:关键优化项逐条说明“优化了什么”
这里只挑对生产环境最重要的几大类说明,每一条都来自官方“Improvements 🤸”列表。
1. I/O & Snapshot 性能
- #8025 / #8059 / #7883:snapshot 恢复 & 刷盘流程优化
- 不再创建临时中间文件,直接恢复到目标文件系统
- 使用
syncfs批量刷盘,提高大量小文件持久化效率 - 效果:快照恢复时间显著缩短,磁盘 IO、空间占用压力明显降低
- #8072:snapshot 创建不再锁住 shard holder
- 之前:snapshot 时阻塞分片级操作
- 现在:snapshot 与正常请求可并行,减少对线上读写的干扰
- #8166:snapshot 下载增加超时
- 网络卡住时可自动放弃,不会长时间占用资源/连接
2. 锁竞争 & 并发调度
- #8007 / #8056:segments 锁方式改进
- 减少读写之间的锁冲突
- 提升高并发场景下整体吞吐和 tail latency
- #8105:单 shard 并行更新数限制为 64
- 防止超多并行更新导致顺序跟踪/内存开销炸裂
- 在高并发写入场景中平衡“吞吐 vs 稳定性”
- #8169:降低 Gridstore 中的锁持有时间
- 直接收敛为搜索尾延迟的下降,尤其是“高写入+高读取”的双高场景
- #8164:closed WAL segment 的 cache 主动释放
- 减少长期运行中的内存占用和碎片
- #8093:序列化新 update 时不再锁整个 WAL
- 大批量写入场景下减少锁带来的全局等待,提高整体写入吞吐
3. 索引与搜索性能
- #7952:禁用未索引字段的 in-place payload 更新
- 提高索引 Segment 的不可变性(immutability),使部分快照更可靠
- 从侧面提升数据一致性和恢复安全
- #7887 / #8125:可禁用 payload 索引的额外 HNSW 边 & 对删除向量不构建额外边
- 降低构建 payload 索引的 CPU/内存开销
- 对某些负载(不需要极致 payload 召回质量)可有效提高导入/更新速度
- #8163 / #8175:改进高 limit 场景下的结果处理 & HNSW 过滤搜索的内存分配
- 在 limit 很大时减少不必要操作
- 降低内存分配与 GC 频率,提升高 limit 查询的稳定性与性能
4. 存储与系统特性
- #7971:启用“单文件 mmap”向量存储模式
- 减少文件句柄、简化管理
- 提升启动和加载速度(大集合场景尤其明显)
- #7928:批量读取向量时使用 io_uring
- 更充分发挥新内核异步 I/O 能力,降低 IOPS 开销
- #7834:当副本挂掉时延长 WAL 保留时间
- 避免因为副本下线时间长而被迫 full shard transfer
- 提升副本恢复的资源效率(更多使用增量追赶)
- #7565:禁用 1.15.0 以来废弃的旧 shard key 格式
- 清理兼容债务,为后续版本演进做准备
5. 配置 & 可用性
- #8053:可配置 collections/shards/segments 的 load 并发度
- 比如启动时恢复一堆大集合,可以根据环境调整并发,避免“瞬时 I/O 风暴”
- #7809:更便捷地为外部推理/embedding provider 提供 API-keys
- 简化与 OpenAI、Azure、Anthropic 等外部模型服务集成时的配置管理
- #7919:改进 datetime 解析出错提示
- 虽然看似小变更,但对排障体验很关键
三、Features:v1.17.0 新增功能解决了哪些核心问题?
来自“Features 🏋️”列表,这些是 1.17 的卖点功能。
1. 搜索质量与检索策略
- Relevance Feedback(相关反馈检索) – milestone#38
- 场景:用户对部分结果点“标注”类似“相关/不相关”,希望用这些反馈动态优化下一轮搜索
- 意义:
- 向量数据库层面原生支持 relevance feedback,不必在业务层重复管理复杂逻辑
- 对 RAG、推荐系统、交互式搜索效果提升巨大
- 解决的问题:让搜索能“听懂”用户反馈,逐步靠近真正需求,而不是一次向量检索定死。
- Weighted RRF(加权 Reciprocal Rank Fusion) – #8063
- 场景:混合多路检索(dense / sparse / BM25 / 其他模型),不同检索路劲重要性不同
- 意义:
- 默认 RRF 给每路查询同等权重,这在实际中经常不合理
- Weighted RRF 允许你对不同子查询设置不同权重
- 解决的问题:混合搜索时,可以更精准地调节“谁说了算”(比如更信 dense、或者更信 BM25)。
- Upsert update_mode 参数 – #7963
- 场景:
- 只允许“插入新点,不覆盖旧点”(insert-only)
- 或只允许“更新存在点,不新建”(update-only)
- 意义:
- 避免业务误用 upsert 导致“老数据被覆盖”或“无意创建垃圾点”
- 解决的问题:提供了更严格的数据写入语义控制,对数据质量敏感的业务很关键。
- 场景:
2. 延迟与吞吐(低延迟搜索)
- “Unlimited update queue” – milestone#43
- 结合官方博客可知,这实际上是更智能的 update queue 设计(文案中“unlimited”更多是语义上不再用小 buffer 限制写入):
- 能平滑 absorb 写入高峰
- 结合后续的 prevent_unoptimized 设置(见 #7643),避免未优化 segment 冲垮搜索性能
- 解决的问题:在写入突增场景,不再丢写/卡写,而是在可控地排队+节流。
- 结合官方博客可知,这实际上是更智能的 update queue 设计(文案中“unlimited”更多是语义上不再用小 buffer 限制写入):
- 控制 update 吞吐、防止未优化搜索 – #7643
- 场景:高写入+高读混合负载
- 痛点:
- 如果写入很猛,优化器来不及合并/建索引,会堆出很多 unoptimized segment → 查询变慢
- 功能:新增配置,让系统在“优化跟不上时”主动节流写入,避免 unoptimized segment 爆炸
- 效果:在高写入环境下显著提升搜索延迟稳定性(尤其是 P95/P99)。
- 可配置 read fan-out delay – #7929
- 场景:分布式集群,多副本查询时,某副本偶尔很慢(tail latency 问题)
- 机制:
- 正常情况下先发请求到一个或少数副本
- 若在“可配置延迟阈值”内没回复,再 fan-out 到其他副本
- 解决的问题:降低 P99 延迟,同时避免对所有查询都一开始 fan-out 到所有副本那种“资源浪费”。
3. 观测性 & 运维
- 优化进度与阶段 API – milestone#44
- 场景:你想知道某集合的优化(建索引、segment 合并)具体进行到哪一步,而不是只看到 yellow。
- 功能:
- 新 API 暴露详细的优化阶段和进度百分比
- 解决痛点:
- 帮助判断“是正常慢”还是“卡死了”;
- 可以在运维面板中展示优化 timeline。
- 集群聚合遥测 API – milestone#40
- 场景:分布式部署,需要一眼看到整个集群:
- peers、collections、shard transfers、resharding 状态等
- 意义:
- 原来可能需要逐节点抓 metrics 再聚合
- 现在有 cluster 视角的 telemetry,一次调用拿整体状态
- 解决问题:运维/监控实现难度大幅下降,可视化更友好。
- 场景:分布式部署,需要一眼看到整个集群:
- Dedicated /metrics HTTP 端口 – #7838
- 场景:Prometheus/监控系统抓取指标
- 意义:
- 将 /metrics 暴露在一个单独端口 → 避免与业务 REST 流量互相影响
- 解决问题:
- 安全(可以只对白名单开放 metrics 端口)
- 稳定(监控抓 metrics 不会与业务请求争同一监听)
- Audit Access Logging – #8071
- 场景:有合规要求,需要审计谁在什么时候对哪些资源做了什么操作
- 功能:
- 对所有需要认证/鉴权的 API 操作记录详细 log
- 意义:
- 支持安全审计、异常行为分析、合规检查
- 二级 API Key 支持 – #7835
- 场景:你想轮换 API key,但不能停机
- 功能:
- 支持 primary + secondary API key,并行生效一段时间
- 解决问题:
- 实现真正的“零停机密钥轮换”
4. 分布式与分片管理
- 列出 Shard Keys 的 API – #7615
- 场景:使用 user-defined sharding,把不同租户/业务线分布到不同 shard key
- 功能:
- 增加 API 列出所有 user-defined shard keys
- 价值:
- 方便检查分片策略、做迁移/重平衡决策
四、综合判断:对你选型/升级的实际意义
- 如果你在生产用集群模式(多节点、多副本)
- 多个 bug fix(#7850, #8103, #8104, #7961, #8095, #7877 等)都是实打实的数据一致性与持久化风险补洞
- 建议:v1.17.0 应视为 1.17.x 系列的最低生产版本。
- 如果你的负载是“高写入 + 高查询”
- “无限更新队列”+prevent_unoptimized+可配置 read fan-out delay 等组合,几乎就是专门针对“写多读多”瓶颈做的系统级优化
- 可以显著降低高写场景下搜索延迟的波动(P95/P99)。
- 如果你做的是 RAG / 搜索 / 推荐
- Relevance Feedback + Weighted RRF + update_mode
- 给你更多“控制检索质量 & 行为”的旋钮,而不是只能一味调 HNSW 参数。
- 如果你有审计、安全、合规要求
- Audit Logging + CA 修复 + 二级 API key
- 让 Qdrant 更符合企业环境安全标准。
- 本文固定链接: http://www.jiagou.cc/1714/
- 转载请注明: 摘星怪 于 架构迷 发表
