我的 RAG 系统用纯向量语义检索、平时答得挺好,可用户一搜精确的产品型号、错误码、或某个生僻专有名词,就死活召不回对应的那篇文档,明明库里就躺着,排查很久才明白向量检索天生就不擅长这种字面精确匹配我得给它配一个关键词检索来互补的深度复盘

我的 RAG 系统流程很标准:文档切块、用 embedding 转成向量存进向量库,用户提问时把问题也转成向量去库里找语义最相近的几个块喂给大模型。对问意思的问题(怎么退货、这个功能怎么用)表现很好,因为语义检索擅长找意思相近的内容。可用户一搜精确的东西就抓瞎:搜产品型号 X-2000Pro、错误码 ERR_5021、生僻专有名词或人名,经常召不回那篇原文里就有这个词的文档,要么返回一堆语义沾边实则不相关的块、要么干脆漏掉。我以为是 embedding 不够好换了更强的模型、精确搜索照样召不回,又怀疑切块切坏了、检查发现那个词好端端待在某个块里。直到把精确查询和该被召回的块分别转成向量算相似度才看清:它俩相似度并不高。根因是向量检索按语义相似召回,而型号、错误码、罕见专有名词这类词语义信息稀薄、其意义在于字面 token 本身而非语义,被压成稠密语义向量后字面精确性几乎被抹平、在语义空间里反而不近,所以纯向量检索对精确字面匹配有天生盲区。语义检索擅长意思相近但用词不同(同义、改写、概念关联),关键词检索(BM25/倒排全文)擅长精确包含某个词(专有名词、错误码、代码)但抓不住意思相近却没共同词的内容,两者盲区恰好互补。正解是用混合检索:同时跑语义检索和关键词检索、各取 top-N、用 RRF 倒数排名融合或加权融合综合排序,再叠一层 cross-encoder rerank 精排;不同检索方式是为不同类型的相关(语义相关 vs 字面精确相关)设计的而真实查询两种都有,召不回精确词别只想着换更强 embedding(不是工具不利是用错种类),要引入互补的关键词检索补盲区,并用含语义类和精确类两种查询的评估集分别量化召回率调权重。这篇复盘从故障现场讲到语义与关键词检索各擅长一类各有盲区、对照表、怎么诊断,再到混合检索 RRF 与 rerank 的完整正解与骨架,以及只靠 LLM/单一距离度量/统一 prompt/统一缓存策略等同类坑,和方法的专长与盲区、用互补的多种方法覆盖多样问题的认知。

我的 RAG 系统用纯向量语义检索、平时答得挺好,可用户一搜精确的产品型号、错误码、或某个生僻专有名词,就死活召不回对应的那篇文档,明明库里就躺着,排查很久才明白向量检索天生就不擅长这种字面精确匹配、我得给它配一个关键词检索来互补

这是一次让我把 RAG 检索这件事,从"用向量语义检索就够了",重新理解成"语义检索有它天生的盲区、得用关键词检索来互补"的事故。我的 RAG 系统用纯向量(语义)检索,平时答得挺好。可用户一搜精确的产品型号、错误码、或某个生僻专有名词,就死活召不回对应的那篇文档——明明库里就躺着。我排查了很久才明白:向量检索天生就不擅长这种"字面精确匹配",我得给它配一个关键词检索来互补。这篇就把这次"语义检索召不回精确关键词"的事故,从头到尾复盘一遍。

故障现场:语义问题答得好,精确关键词却怎么都搜不到

我的 RAG 系统流程很标准:把文档切块、用 embedding 模型转成向量、存进向量库;用户提问时,把问题也转成向量,去库里找"语义最相近"的几个块,喂给大模型生成答案。对那些"问意思"的问题——"怎么退货""这个功能怎么用"——它表现很好,因为语义检索擅长找"意思相近"的内容。

可问题来了:用户一旦搜精确的东西,它就抓瞎。比如搜产品型号 X-2000Pro、搜错误码 ERR_5021、搜一个生僻的专有名词或人名,系统经常召不回那篇明明原文里就有这个词的文档,要么返回一堆"语义上沾点边、实则不相关"的块,要么干脆漏掉。我一开始以为是 embedding 模型不够好,换了更强的模型,精确搜索的问题依旧。我又怀疑是切块切坏了,检查发现那个词好端端地待在某个块里。直到我把"用户的精确查询"和"该被召回的块"分别转成向量、算了下相似度,才看清根因——它俩的向量相似度并不高!向量检索是按"语义相似"召回的,而像产品型号、错误码、罕见专有名词这类词,语义信息很稀薄、很难和别的内容拉开语义距离,它们的"意义"恰恰在于"这个字面 token 本身",而不在于"它的语义";向量模型把它压成一个稠密语义向量时,这种"字面精确性"几乎被抹平了。于是 ERR_5021 这种词,在语义空间里和真正含它的文档,反而没那么""。纯向量检索,对这类精确字面匹配,有一个天生的盲区。

# 我的 RAG: 纯向量(语义)检索
def retrieve(query, k=5):
    qv = embed(query)                      # 查询转成语义向量
    return vector_db.search(qv, top_k=k)   # 找语义最相近的块

# 表现:
#   "怎么退货" → 召回退货政策文档 ✓ (语义检索擅长"意思相近")
#   "X-2000Pro 的保修期" → 召不回含 X-2000Pro 的文档 ✗
#   "ERR_5021 怎么解决" → 召回一堆"语义沾边"的报错文档, 漏掉真正那篇 ✗

# 我以为是 embedding 模型不够好 → 换更强的 → 精确搜索照样召不回
# 真相: 向量检索按"语义相似"召回, 而型号/错误码/专有名词这类词,
#   语义稀薄、其意义在于"字面 token 本身"而非"语义",
#   被压成稠密语义向量后, 字面精确性几乎被抹平 → 语义空间里反而不"近"
#   → 纯向量检索对"精确字面匹配"有天生盲区

问题被钉死在这个认知错位上:我以为"向量语义检索"是一种万能的、能 cover 所有检索需求的方式,但它其实只擅长一类问题——"找语义相近的内容";对另一类问题——"找精确包含某个字面词(尤其是型号、错误码、ID、罕见专有名词)的内容"——它有天生的短板。这两类需求,需要两种不同特性的检索方式。语义检索把文本压成稠密向量,优点是能跨越措辞差异抓住"意思",代价是丢失了"字面精确";而精确关键词匹配,恰恰是传统关键词检索(如 BM25、全文索引)的强项。我用纯向量检索去通吃,等于用一把擅长"找相似"的工具,去做"找精确"的活,自然在精确匹配上栽跟头。我以为我选了一把万能钥匙,其实它只能开一类锁,另一类锁它天生拧不动。

第一件事:想明白语义检索和关键词检索,各擅长一类、各有盲区

把这次事故彻底想清楚,关键是理解向量(语义)检索和关键词(字面)检索,是两种特性互补的检索方式:语义检索把文本编码成稠密向量、按语义相似度召回,擅长"意思相近但用词不同"(同义、改写、概念关联),但对精确字面、罕见词、型号 ID 这类"语义稀薄、靠 token 本身表意"的内容召回弱;关键词检索(BM25/倒排全文索引)按词项精确匹配和词频召回,擅长"精确包含某个词"(尤其专有名词、错误码、代码),但抓不住"意思相近但没有共同词"的内容。两者的盲区恰好互补。

这就是为什么生产级 RAG 大多用"混合检索(hybrid search)":同时跑语义检索和关键词检索,再把两路结果融合排序(如 RRF——倒数排名融合),取长补短。语义检索保证"问意思"的问题能召回措辞不同但相关的内容;关键词检索保证"搜精确词"(型号、错误码、人名)的问题能命中字面包含它的文档。任何单一检索方式,都必然在自己不擅长的那类查询上留下盲区;指望一种方式通吃所有查询,就一定会有一类用户的搜索体验很差。关键认知是:不同的检索方式,是为不同类型的"相关"而设计的;"语义相关"和"字面精确相关"是两种不同的相关,需要不同的手段,而真实的查询两种都有。

# 正解: 混合检索 —— 语义检索 + 关键词检索, 结果融合排序
def hybrid_retrieve(query, k=5):
    # 1) 语义检索: 擅长"意思相近、措辞不同"
    sem_hits = vector_db.search(embed(query), top_k=20)
    # 2) 关键词检索(BM25/全文): 擅长"精确包含型号/错误码/专有名词"
    kw_hits = keyword_index.search(query, top_k=20)
    # 3) 融合排序: 用 RRF(倒数排名融合)把两路结果综合
    return rrf_fuse(sem_hits, kw_hits, k=k)

def rrf_fuse(*result_lists, k=5, c=60):
    scores = {}
    for hits in result_lists:
        for rank, doc in enumerate(hits):
            # 每个文档的分 = 各路里 1/(c+排名) 之和; 两路都靠前的得分最高
            scores[doc.id] = scores.get(doc.id, 0) + 1.0 / (c + rank)
    ranked = sorted(scores, key=scores.get, reverse=True)
    return ranked[:k]

# 效果:
#   "怎么退货"            → 语义路召回相关政策(关键词路也补充)
#   "X-2000Pro 的保修期"  → 关键词路精确命中含该型号的文档
#   "ERR_5021 怎么解决"   → 关键词路命中含该错误码的那篇, 语义路补背景
#   两类查询都能召回, 盲区被互补掉了 ✓

想通这一层,我才明白自己错在哪:我把"向量语义检索"当成了一种没有短板的、可以一招通吃的检索方案,而忽略了它只是"为语义相似而生"的一种手段、对字面精确匹配有天生盲区。我一遍遍去换更强的 embedding 模型,是在"把这把擅长找相似的工具磨得更锋利",可问题根本不在工具不够利,而在我用错了工具种类——精确匹配的活,得交给关键词检索。认清每种检索方式擅长什么、对什么有盲区,再用互补的方式把盲区补上,而不是指望一种方式包打天下。

第二件事:正解——混合检索,语义与关键词两路并跑、融合排序

找到根因,正解就清晰了:别用单一的向量检索通吃,改用混合检索(hybrid search)——同时跑语义(向量)检索和关键词(BM25/全文)检索,各取 top-N,再用 RRF(倒数排名融合)或加权融合把两路结果综合排序。这样"问意思"的查询靠语义路、"搜精确词"(型号/错误码/专有名词)的查询靠关键词路,两类都不漏。

# 错误: 只有语义检索, 精确关键词召不回
def retrieve(query, k=5):
    return vector_db.search(embed(query), top_k=k)   # ✗ 字面精确匹配是盲区

# 正解1: 混合检索, 两路并跑 + RRF 融合(已在上文给出 rrf_fuse)
def hybrid_retrieve(query, k=5):
    sem = vector_db.search(embed(query), top_k=30)    # 语义路
    kw  = keyword_index.search(query, top_k=30)       # 关键词路(BM25)
    return rrf_fuse(sem, kw, k=k)

# 正解2: 很多向量库已内置混合检索, 直接用其 hybrid 接口
# 例: Elasticsearch / OpenSearch 的 BM25 + kNN 混合
#     Weaviate / Milvus / pgvector + 全文索引 等都支持
results = client.hybrid_search(
    query_text=query,
    query_vector=embed(query),
    alpha=0.5,          # 语义与关键词的权重, 按业务调
    top_k=k,
)

# 正解3: 混合召回后再加重排序(rerank)精排, 进一步提质
candidates = hybrid_retrieve(query, k=20)
final = rerank_model(query, candidates)[:5]   # cross-encoder 精排 top5

这套做法的精髓,是承认"没有一种检索方式能覆盖所有类型的相关",于是用两种盲区互补的方式并跑、再融合,让整体召回既不漏"语义相近"、也不漏"字面精确"。语义检索负责跨越措辞差异、关键词检索负责锁定精确词项,RRF 这类融合算法则不需要两路分数可比、只看排名,把"两路都觉得相关"的拉到最前。再叠一层 rerank 精排,质量更上一层。不是把单一手段优化到极致去硬扛它本就不擅长的查询,而是引入互补手段、各司其职。

【做 RAG 检索, 我现在认死的几条】

1. 语义(向量)检索 擅长"意思相近、措辞不同", 弱于"精确字面匹配"

2. 关键词(BM25/全文)检索 擅长"精确含某词", 弱于"同义改写"

3. 型号/错误码/ID/罕见专有名词 = 语义稀薄, 纯向量检索的盲区

4. 生产 RAG 用混合检索: 语义 + 关键词两路并跑, RRF/加权融合

5. 召不回精确词别只想着换更强 embedding —— 那不是工具不利, 是用错种类

6. 混合召回后再加 rerank(cross-encoder)精排, 质量更高

7. 用评估集(含语义类 + 精确类查询)分别量化两类召回率, 据此调权重

第三件事:其他"用一种擅长某类的方法去通吃所有类"的同类坑

顺着"用一种只擅长某类问题的方法去通吃所有问题、在它的盲区栽跟头"这条线,我把同类的坑都排查了一遍:

第一个,只靠 LLM、不接检索做问答。LLM 擅长通用知识和推理,但对私有/最新/精确事实会幻觉;这类问题必须靠 RAG 检索真实资料来补,而不是指望模型记得。

第二个,只用一种距离度量。余弦相似度适合方向、欧氏距离适合绝对位置,场景不同选错度量,召回质量就差。

第三个,所有任务都用同一个 prompt 模板。一个模板适合某类任务,套到结构、目标不同的任务上效果就崩,要按任务类型分别设计。

第四个,一套缓存策略用到所有数据。热数据、冷数据、强一致数据特性不同,用同一种缓存 TTL/策略,总有一类数据被坑。

第四件事:语义检索 vs 关键词检索——一张对照表

我把两种检索方式摆在一起对比,核心看"各擅长哪类查询、对哪类有盲区":

维度 语义(向量)检索 关键词(BM25/全文)检索
按什么召回 语义相似度(稠密向量) 词项精确匹配 + 词频
擅长 意思相近、同义、改写 精确含某词、专有名词、ID
盲区 型号/错误码/罕见词等字面精确 措辞不同但意思相近
"X-2000Pro" 常召不回(语义稀薄) 精确命中 ✓
"怎么退货" 召回退换货政策 ✓ 可能漏(无共同词)
提升方向 换更强 embedding/rerank 分词/同义词扩展

看清这张表,方案就明确了:两种检索擅长的"相关"类型不同、盲区恰好互补,生产 RAG 应当用混合检索把两路并跑融合,而不是指望任何一种单独通吃。我这次踩坑,就是只用语义检索,在它"字面精确匹配"的盲区上,被型号、错误码这类查询打了个措手不及。型号搜索靠关键词路、意思搜索靠语义路,缺哪一路都会有一类用户搜不到东西。

第五件事:我曾经对向量检索想当然的几个误区

这次事故也把我对向量检索的一堆"想当然"照了个底朝天:

我以为 实际上
向量语义检索能 cover 所有检索需求 它只擅长语义相似, 对字面精确匹配有盲区
精确词召不回是 embedding 不够强 是检索方式用错了种类, 换模型也救不了
型号/错误码也能被语义检索召回 这类词语义稀薄, 在语义空间里反而不"近"
关键词检索过时了, 向量更先进 两者互补, 生产 RAG 普遍用混合检索
一种检索方式优化到极致就够了 单一方式必有盲区, 互补才能覆盖各类查询

这些误区的根子是同一个:我把一种"为某类相关而设计"的检索手段,当成了能覆盖一切相关的通用方案,而没意识到"相关"本身有不止一种,每种手段都只对其中一类拿手。向量检索的强项是"语义相关",这让我误以为它能处理所有检索;可"字面精确相关"是另一种相关,它恰恰不擅长。我一味优化这一种手段,却始终没去引入那个能补上盲区的、完全不同的手段。把一种擅长某类的方法误当成万能,于是在它的盲区里反复挣扎、却不去找互补的工具,是这类问题的共同根源。

第六件事:做 RAG 检索、排查"某类查询总召不回"时,我现在的自检习惯

现在每当我做 RAG 检索、或排查"有一类查询总是召不回正确文档",我都会先按这张图问自己:

这张图的精髓,是"先分清召不回的是精确词还是意思相近;精确词是向量检索的盲区,要加关键词检索;两路并跑融合,别指望单一方式通吃"设计就用混合检索把语义路和关键词路并跑融合、再加 rerank、用含两类查询的评估集调权重、排查就先看召不回的查询属于哪类、对应是哪种检索的盲区这套习惯,让我从"纯向量检索通吃"变成了"先认清每种检索的盲区再互补"——核心始终是:向量(语义)检索和关键词(字面)检索是两种特性互补的检索方式:语义检索把文本编码成稠密向量、按语义相似度召回,擅长意思相近但用词不同(同义、改写、概念关联),但对精确字面、罕见词、型号 ID、错误码这类语义稀薄、靠 token 本身表意的内容召回弱——因为它们的意义在于字面 token 本身而非语义,被压成稠密语义向量后字面精确性几乎被抹平、在语义空间里反而不近;关键词检索(BM25/倒排全文索引)按词项精确匹配和词频召回,擅长精确包含某个词(尤其专有名词、错误码、代码),但抓不住意思相近却没有共同词的内容;两者的盲区恰好互补,所以生产级 RAG 大多用混合检索(hybrid search)——同时跑语义检索和关键词检索、各取 top-N、再用 RRF 倒数排名融合或加权融合把两路结果综合排序,并可在融合召回后再叠一层 cross-encoder rerank 精排;关键认知是不同检索方式是为不同类型的相关(语义相关 vs 字面精确相关)而设计的、而真实查询两种都有,任何单一方式都必然在自己不擅长的那类查询上留下盲区,召不回精确词时别只想着换更强的 embedding(那不是工具不利而是用错了种类),而要引入互补的关键词检索把盲区补上,并用含语义类和精确类两种查询的评估集分别量化召回率来调权重。

我立下的几条规矩

这场"语义检索召不回精确关键词"的事故,换来了我做 RAG 检索时,刻进骨子里的几条铁律:

  1. 语义(向量)检索擅长"意思相近",对"精确字面匹配"有天生盲区。
  2. 型号、错误码、ID、罕见专有名词,语义稀薄,纯向量检索召不回。
  3. 关键词(BM25/全文)检索擅长精确含某词,正好补语义检索的盲区。
  4. 生产 RAG 用混合检索:语义 + 关键词两路并跑,RRF/加权融合。
  5. 精确词召不回别只换更强 embedding——那不是工具不利,是用错了种类。
  6. 混合召回后再加 rerank(cross-encoder)精排,质量更高。
  7. 用含语义类 + 精确类查询的评估集,分别量化两类召回率、据此调权重。

附:我现在做 RAG 混合检索的"语义+关键词+RRF+rerank"骨架

这是我现在做 RAG 检索固定套的骨架——把这次踩坑的教训(语义与关键词两路并跑、RRF 融合、rerank 精排、评估集调权重)固化成一套结构,让"精确关键词召不回"那种坑再不会埋进系统:

from dataclasses import dataclass

@dataclass
class Hit:
    doc_id: str
    text: str

class HybridRetriever:
    def __init__(self, vector_db, keyword_index, reranker=None):
        self.vec = vector_db
        self.kw = keyword_index        # BM25/全文索引
        self.reranker = reranker       # cross-encoder, 可选

    def retrieve(self, query, k=5, recall=30):
        # 1) 两路并跑: 语义召回(补"意思相近") + 关键词召回(补"精确字面")
        sem = self.vec.search(embed(query), top_k=recall)
        kw  = self.kw.search(query, top_k=recall)
        # 2) RRF 融合: 不需两路分数可比, 只看排名, 两路都靠前的最优先
        fused = self._rrf(sem, kw, top=recall)
        # 3) rerank 精排(若配了): cross-encoder 对 query-doc 对逐一打分
        if self.reranker:
            fused = self.reranker.rank(query, fused)
        return fused[:k]

    @staticmethod
    def _rrf(*lists, top=30, c=60):
        score = {}
        for hits in lists:
            for rank, h in enumerate(hits):
                score[h.doc_id] = score.get(h.doc_id, 0) + 1.0 / (c + rank)
        order = sorted(score, key=score.get, reverse=True)
        return order[:top]

# 用评估集分别量化两类查询的召回率, 据此调权重/recall 数
EVAL = [
    {"q": "怎么退货",          "gold": "doc_refund",  "type": "semantic"},
    {"q": "X-2000Pro 保修期",  "gold": "doc_x2000",   "type": "exact"},
    {"q": "ERR_5021 怎么解决", "gold": "doc_err5021", "type": "exact"},
]
def eval_recall(retriever):
    by_type = {}
    for case in EVAL:
        hit = case["gold"] in [h for h in retriever.retrieve(case["q"], k=5)]
        by_type.setdefault(case["type"], []).append(hit)
    # 分别看 semantic 类和 exact 类的召回率, 别被总平均掩盖某一类的崩盘
    return {t: sum(v)/len(v) for t, v in by_type.items()}

这套骨架把我这次的教训钉死在了结构里:检索两路并跑——语义路补"意思相近"、关键词路补"精确字面"、用 RRF 融合(只看排名、不需分数可比)、再用 rerank 精排;评估时按查询类型分别统计召回率(语义类 vs 精确类),绝不让总平均掩盖某一类的崩盘。这样,型号、错误码这类精确查询由关键词路稳稳命中,意思相近的查询由语义路覆盖,而不再是当初那个"纯向量检索在精确匹配的盲区里干瞪眼"的局面。把"识别方法的专长与盲区、用互补的多种方法覆盖多样的问题"这个道理,沉淀成 RAG 检索的固定骨架,这是我对这次"型号搜不到"最实在的交代——毕竟,用户既会问意思、也会搜精确词,而一个好的检索,得两种都接得住。

写在最后

回头看,这场由"纯向量检索"引发的"精确关键词召不回"事故,真正教给我的,远不止"加一路关键词检索"这一个技巧。它让我对"每一种工具/方法,都是为了某一类特定的问题而设计的,它在那类问题上越强,往往意味着它在另一类问题上越有盲区;而当一种方法在它的强项上给我们留下深刻印象时,我们极容易产生一种错觉——以为它无所不能、可以拿来通吃所有问题,于是在它的盲区里反复碰壁,还误以为是'没把它用到极致'",有了一次刻骨的体会。我栽跟头,是因为我把一种"为某一类相关(语义相似)而生"的方法,误当成了能覆盖一切相关的通用方案——向量检索在"问意思"的问题上表现太好了,好到让我以为它能处理所有检索;我没意识到"相关"本身不止一种:"意思相近"是一种相关,"字面精确包含"是另一种相关,而向量检索只对前一种拿手;于是当用户搜型号、错误码这类"字面精确"的东西时,我一遍遍去换更强的 embedding——本质是在"把擅长找相似的工具磨得更利",却始终没意识到,这活根本就该换一种工具来干这让我领悟到一个关于"方法的专长与盲区"的深刻认知:任何方法、工具、模型,其能力都是有"形状"的——它为某类问题的特征而优化,因而在那类问题上表现卓越,同时也必然在与之相反特征的问题上存在盲区;能力越是专精于一端,另一端的盲区往往越深;因此,不存在能通吃所有问题的单一方法;真实世界的问题恰恰是多样的、跨越多种特征的,用任何单一方法去覆盖,都必然在它盲区对应的那类问题上失效;而最危险的,是被一种方法在其强项上的优异表现"晃了眼",误以为它全能,从而在它的盲区里不停地优化它本身(磨利同一把刀),而不去引入一种特性互补的、专门对付那类盲区问题的方法——真正的解法往往不是"把一种方法做到极致",而是"识别出有几类不同的问题、为每类配上擅长它的方法、再把它们融合起来"这给了我一种看待"一切'选用某种方法去解决一类问题'之事"时的清醒:每当我用一种方法处理一批问题、却发现总有一小类怎么都搞不定时,要追问"搞不定的这一类,是不是恰好落在了我这个方法的盲区里?它和我擅长的那类问题,特征是不是正相反?我该继续优化这一种方法,还是该引入一种互补的、专治这类问题的方法"——认清每种方法能力的形状与盲区,按问题的类型搭配互补的方法,而不是迷信一种方法通吃;"识别方法的专长与盲区、用互补的多种方法覆盖多样的问题",是做对 RAG 检索、也是解决一切复杂问题的关键认清语义检索有字面精确的盲区、要用关键词检索互补、生产 RAG 用混合检索——这,是我用一次"型号搜不到"的事故,换来的、关于 AI、也关于如何识别方法专长与盲区的、最朴素也最深刻的领悟。如果这篇复盘,能让你下次发现 RAG 有一类查询总召不回时,先别急着换更强的 embedding,而是想想"这类查询是不是落在了向量检索的盲区里?要不要加一路关键词检索?",并搭起混合检索,那我对着那个"明明库里有、却怎么都搜不到的型号"排查的大半天,就值了。

—— 别看了 · 2026
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理 邮箱1846861578@qq.com。
技术教程

我给容器化的服务做了优雅停机、代码里明明监听了 SIGTERM 信号,可每次 kubectl 删 Pod 它都不优雅退出、非要硬等三十秒被强杀,我对着代码反复确认信号处理逻辑没问题,最后才发现根子在 Dockerfile 那行用 shell 形式写的 CMD、我的应用压根不是容器里的 1 号进程的深度复盘

2026-6-3 8:23:13

技术教程

我给一批缓存数据统一设了一小时过期、平时缓存命中率高得很数据库压力很小,可每隔整整一小时数据库就会突然被海量请求瞬间打垮、CPU 飙满响应超时,排查很久才惊觉那批缓存是同一时刻批量写进去的、于是又在同一时刻集体失效把流量齐刷刷地全砸向了数据库的深度复盘

2026-6-3 8:36:14

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索