想象你走进一座像城市一样大的商场,里面陈列着几百万件商品。这时一位金牌导购迎了上来——她不会从一楼到顶楼挨个翻遍所有货架,而是先在脑海中快速圈定“这位顾客可能感兴趣的楼层和区域”,然后带着你在候选区里仔细比较价格、口碑和款式,最后递给你三五件最合适的商品。这套“先海选、再决赛”的接待流程,正是推荐系统的核心骨架:召回排序架构。 推荐系统每天面对亿级商品和上亿用户,根本没法让所有商品都跑一遍复杂模型。于是业界把整条链路拆成数据接入、召回、排序、重排四段,每段只做一件事,像漏斗一样逐级缩小候选范围。召回负责“快而全”地捞回可能感兴趣的物品,排序负责“精而准”地排出先后顺序。理解这套架构,你就把握住了工业级推荐系统的主干。
掌握召回排序架构,是搭建工业级推荐系统的基本功,也是推荐算法工程师面试与系统设计最核心的考点,直接决定你能否从“调包跑通”走向“设计落地”。
可视化演示
模拟推荐系统召回排序的多级漏斗,展示多路召回融合与精排打分排序,观察候选数量逐级筛选与Top-N结果生成。
本节配有交互动效(进入视口后自动加载,约 3KB)。
模式1:多级漏斗筛选 召回(万) 粗排(千) 精排(百) N = funnel(recall) 候选逐级筛减,数量从万级降至数十级。
整体架构流程
想象你走进一座像城市一样大的商场,几百万件商品陈列在货架上。金牌导购不会领着你从一楼到顶楼挨个翻,而是先在脑海里快速圈出“这位顾客可能喜欢的区域”,再在候选区里仔细比较,最后递给你三五件。这套“先海选、再决赛”的打法,就是推荐系统的召回排序架构。
推荐系统每天面对亿级物品和上亿用户,根本不可能让所有商品都跑一遍复杂模型。于是业界把链路拆成数据接入、召回、排序、重排四段:数据接入负责把用户行为、物品属性和上下文信号清洗后送入存储与特征系统;召回从全量候选中快速取回几百个“有戏”的物品;排序用复杂模型精细打分;重排再做多样性、新鲜度和商业规则的微调。整个流程像漏斗,逐级把范围缩小。
典型量级是:全量物品 $10^8$,多路召回后 $10^3$,精排模型真正打分的只有 $10^2$,最终展示给用户的大约 $10^1$ 个。每一层都只为下一层服务,绝不越俎代庖——召回阶段不会去算精细特征,精排阶段也不会面对全量物品。
导购“先圈区域、再比价、最后递给你”正是这个漏斗在现实中的投影:把有限的注意力花在最可能成交的几件商品上。理解了这个漏斗,你就抓住了推荐系统架构的第一根主线。
- 全量池$N_{\text{全量}}$ 是所有可推荐物品的总数,通常达到亿级,对应商场里的全部货架。
- 召回层$N_{\text{召回}}$ 是经过多路召回后的候选集,大约千级,对应导购圈出的几个区域。
- 精排层$N_{\text{精排}}$ 是真正跑复杂模型的物品数,约百级,对应导购拿起实物仔细比对的件数。
- 展示层$N_{\text{展示}}$ 是最终展示给用户的结果数,只有十个左右,对应导购最终递到你手里的商品。
多路召回策略
商场里其实不只有一位导购:有人专盯全场热销榜,有人熟悉老顾客的复购习惯,还有人擅长猜“和你口味相似的人都在买什么”。几位导购各自快速抓一把货放进同一个候选筐,再由专人合并去重。这就是多路召回的生动写照。
任何单一信号都有盲区:只看热度,推荐结果千人一面;只看你和某件物品的相似度,覆盖又太窄。于是工业界把不同信号拆成多路,每路用极低成本快速取回候选,最后合并。每路只求“快而全”,把精准排名的任务交给下游。
常用的路有四种:热度召回直接取全局或类目热销榜,零用户成本;协同过滤召回基于用户与物品的历史共现关系,推荐“和你相似的人买过的东西”;向量召回用双塔模型把用户和物品映射到同一向量空间,靠近邻检索快速找到相似物品;类目召回则从用户最近浏览的类目里取热门商品。各路背后有不同的索引支撑,如倒排索引、近似近邻索引等。
几位导购各凭本事抓货,汇聚到同一个筐里后,需要一把统一的“尺子”来衡量合不合口味,余弦相似度正是这把尺子。它把“合不合口味”量化成一个可排序的数字,召回阶段就可以按照分数从高到低快速切出候选。
- 用户向量$\mathbf{u}$ 表示用户的偏好,把历史行为映射成 $d$ 维向量,相当于导购脑中“这位顾客的画像”。
- 物品向量$\mathbf{i}$ 表示物品的特征,与用户处在同一个向量空间,相当于每件商品的“标签名片”。
- 点积与模长分子点积衡量两个向量方向的一致性,分母用模长乘积做归一化,消除物品本身长度的影响。
排序模型精排
候选筐里有几十上百件商品,导购开始逐件掂量:价格合不合适、评价好不好、上次买的类似款是否满意、今天有没有折扣。每件商品在心里打一个综合分,然后从高到低排好。排序模型精排,就是这个“货比三家”的精细打分环节。
召回负责“别漏掉对的”,精排则负责“把对的排前面”。精排的输入是候选物品及其特征,输出是对用户行为的预估——最常见的是点击率或转化率,然后按预估概率降序排列。早期工业界用逻辑回归,后来演进到因子分解机、深度神经网络,甚至多目标联合建模。
特征工程在此至关重要:用户侧特征包括性别、年龄段、历史偏好;物品侧包括类目、价格、质量分;上下文侧包括时间、地点、设备。为了让精排模型跑得动,前面通常还有一层粗排:用轻量模型先把候选从几千筛到几百,避免昂贵模型处理太多样本。粗排与精排的分工,就像导购先快速排除明显不合适的,再仔细比较剩下的。
导购打的“综合分”就是 $z$,最后报给顾客的推荐顺序,其实就是按 $\hat{y}$ 从高到低排列。分数越高,排得越靠前,越容易被用户看到和点击。
- 特征向量$\mathbf{x}$ 由用户、物品、上下文三类特征拼接而成,是模型判断的原料。
- 线性打分权重 $\mathbf{w}$ 与特征 $\mathbf{x}$ 做点积并加上偏置 $b$,得到综合印象分 $z$。每个 $w_k$ 表示对应特征的重要程度。
- 概率映射Sigmoid 函数把任意实数 $z$ 压缩到 $(0,1)$ 区间,作为点击概率的估计值。
离线与实时
导购每天开门前会做功课:翻一遍进货清单,把熟客档案更新到笔记本上,这是“离线计算”;开门营业后,根据顾客当下的表情、提问和犹豫随时调整话术,这是“在线服务”。两者分工明确,缺一不可。
推荐系统的模型与特征也分成离线与实时两条线。离线每天或每小时用全量日志训练模型、预计算用户画像和物品索引;在线服务在请求到达后的几十到几百毫秒内完成召回、排序、返回结果。实时特征则专门处理“刚刚发生的行为”,比如用户刚点击了一件商品,下一轮推荐要立刻反映出来。
离线计算重吞吐,通常用 Spark、MapReduce 一类批处理框架跑数小时;在线服务重延迟,靠高性能 RPC 与缓存支撑。特征新鲜度是两者衔接的关键问题:用户刚发生的动作价值很高,但不能为所有特征都铺实时链路,需要按变化速度分层——长期偏好走离线,短期行为走流式,当下场景走在线。
导购记得你昨天买过什么,这是稳定的离线画像;也盯着你现在的动作,这是实时行为。而那些“太久没更新的消息就不太当真”的直觉,正是衰减公式的味道——离线与实时不是二选一,而是按特征的新鲜程度分层配合。
- 特征快照$x(t_0)$ 是特征在 $t_0$ 时刻的值,来自最近一次离线或流式更新,相当于导购笔记本上的一条记录。
- 衰减系数$\lambda$ 表示特征随时间的“过期速度”,变化越快的信号 $\lambda$ 越大,比如实时点击行为比年龄变化快得多。
- 时效权重$\Delta t = t - t_0$ 是距离上次更新的时间间隔,间隔越久,指数项越小,该特征对当前预测的贡献越低。
评估指标体系
怎么判断一位导购干得好不好?看她推荐的东西顾客是否买走,是否愿意回头再来,推荐范围是不是太窄。如果不看这些,只说她“态度热情”,没有任何说服力。推荐系统同样需要一套评估体系来回答“到底行不行”。
离线阶段用历史日志回放模型,看排序质量;线上阶段通过 A/B 实验看点击率、转化率、人均时长等业务指标。离线指标是“模拟考”,线上指标是“真实考”。两者共同构成评估体系:离线评测快、成本低,适合模型迭代;线上实验慢、成本高,却是最终裁决。
混淆矩阵定义了三个基本概念:TP 是推荐了且用户确实点击;FP 是推荐了但用户不感兴趣;FN 是该推荐却漏掉了。在此基础上,精确率回答“推荐的里面有多少是对的”,召回率回答“用户感兴趣的东西里我们找回了多少”。AUC 则衡量模型把正样本排在负样本前面的概率,不依赖阈值,适合对比不同模型。GAUC 进一步按用户分组计算再加权,消除用户活跃度差异的干扰。
评价导购既看“你听了她的推荐买没买”(精准),也看“你想买的东西她有没有漏掉”(全面)。理解了精确率与召回率,再去看 AUC、GAUC 等指标时,就会明白它们都是为了更全面地刻画“推荐质量”这同一个目标。
- 真阳性 TP推荐了某物品,用户也确实点击或购买了,代表一次“说中了”。
- 假阳性 FP推荐了但用户没有点击,代表一次“误报”。
- 假阴性 FN没有推荐,但用户其实会喜欢,代表一次“漏报”。
- 两指标对比Precision 回答“推得准不准”,Recall 回答“找得全不全”,二者往往此消彼长。
企业级落地案例
把导购团队搬进真实商场:早高峰客流暴涨,团队要提前排班扩编;来了个第一次逛店的新顾客,档案是空的,该怎么接待?各楼层业绩如何汇总考核?这些场景正是推荐系统企业级落地时最常遇到的问题。
工业界的推荐系统无一例外遵循召回排序架构,但具体形态因业务而异。电商更重转化与 GMV,短视频更重时长与留存,广告则把精排得分与出价结合决定曝光。以电商“猜你喜欢”为例:用户打开 App,请求在几十毫秒内完成——先走多路召回拿回上千候选,粗排筛到几百,精排深度模型打分,重排融入运营规则后输出。大促期间流量暴涨,靠缓存、降级、索引扩容扛住峰值。
短视频推荐则强依赖实时行为:用户刚看完一个视频,相似内容立刻进入召回;新用户没有历史数据,系统就主动推荐一些高热度、差异化的内容试探反应,这就是冷启动。冷启动的本质是在“探索”与“利用”之间做平衡:是利用已知信息求稳,还是冒险推荐新内容收集反馈。
新顾客没有档案,聪明的导购会“大胆试”——推荐几件差异大的商品观察反应。这正是 ε-greedy 在真实商场里的做法:偶尔的不确定,换来的是对用户更完整的理解,也让冷启动不再冰冷。
- 最优动作$a^{*}$ 是当前模型预测的最优推荐,对应导购认为最可能成交的商品。
- 探索率$\varepsilon$ 是一个很小的概率值,通常取 0.01 到 0.1,代表“冒险尝试”的比例。
- 随机探索以 $\varepsilon$ 概率故意推荐随机物品,收集点击反馈后反哺模型,改善长期效果。
性能优化策略
客流爆满时,导购怎么做到快而不乱?提前把热销款摆在最顺手的位置,把楼层和货架分区编号,人手不足时优先服务大客户。性能优化就是这套“让系统跑得快、扛得住”的工程手段,对应到推荐系统里分别是缓存、索引和降级。
推荐链路的每一步都有性能成本:召回要扫索引,排序要算模型,特征服务要读数据。瓶颈常常出现在精排——候选多、模型重,计算量可观。优化思路分四层:数据索引加速、多级缓存、降级容灾、资源规划。
向量召回用 HNSW、FAISS 这类近似近邻检索,把暴力搜索的 $O(N)$ 复杂度降到接近对数级别;排序特征和模型预测结果可以做 key-value 缓存,避免同一请求反复计算;当峰值流量超过系统容量时,先跳过低收益的召回路或直接退回热度推荐,保证核心体验不崩溃;资源规划则通过容量评估和弹性伸缩,在成本和稳定性之间找平衡。
导购把热销款放在手边、给货架分区编号,正是“缓存”与“索引”的智慧。性能优化的本质,永远是在资源有限的前提下,让最常见的请求走最快的路,让系统在最极端的流量下依然体面。
- 命中次数$h$ 是缓存直接返回结果的次数,相当于导购直接从手边拿起热销款。
- 未命中次数$m$ 是缓存没有、需要回源计算的次数,相当于导购不得不跑一趟仓库。
- 命中率命中率越高,重复计算越少,平均响应延迟越低,系统吞吐能力越强。
AI 应用场景
电商首页“猜你喜欢”的在线推荐链路
阶段:召回 + 排序在线推断
解决的问题:传统人工运营只能覆盖几十个商品位,且无法个体化;AI 用召回排序架构在几十毫秒内从亿级商品中为每个用户生成个性化列表,同时兼顾点击率与 GMV。
具体案例:某电商 App 用户打开首页,请求到达推荐服务后,多路召回并行取回上千候选,粗排筛至几百,精排深度模型打分,重排融入“已购过滤、新品加权”规则,最终返回 20 个商品。遇到大促流量洪峰,系统自动降级部分非核心召回路,保证接口不超时。
短视频信息流的实时个性化排序
阶段:实时特征 + 排序模型 + 重排
解决的问题:短视频场景用户切换极快,传统批处理无法跟上实时兴趣变化;需要基于实时行为特征,在数百毫秒内完成“下一个视频”的推荐,最大化用户时长与留存。
具体案例:用户刚看完一条美食视频,系统通过实时特征管道立刻捕捉到该行为,向量召回将相似美食视频纳入候选,精排模型结合“完播率、点赞率、评论率”多目标打分,重排再对连续同质内容做打散,避免用户审美疲劳。
广告 CTR 预估与竞价排序
阶段:精排打分 + 与出价结合
解决的问题:广告场景中,模型既要预估用户点击概率,又要结合广告主出价决定最终曝光顺序。传统规则排序无法兼顾相关性与商业价值;精排 CTR 模型输出概率后,与出价做乘积或加权,实现平台收益与用户体验的平衡。
具体案例:某信息流广告平台,召回圈定广告候选后,精排模型预估每条广告的点击率,再按“预估值 × 出价”计算综合排序分,同时加入频控与负反馈特征,避免同一条广告反复打扰用户。
Python 演示
# -*- coding: utf-8 -*-"""多路召回 + 排序的推荐系统演示"""import random class MockRecommender: def __init__(self, item_size=2000): self.item_pool = [] for i in range(item_size): self.item_pool.append({ "id": i, "cat": i % 10, # 物品类目 "hot": random.random(), # 热度分 "vec": [random.random() for _ in range(8)] # 8 维特征向量 }) self.user_history = [random.randrange(item_size) for _ in range(30)] def recall_by_hot(self, top_n=100): """召回1:热度榜""" s = sorted(self.item_pool, key=lambda it: it["hot"], reverse=True) return s[:top_n] def recall_by_cat(self, top_n=100): """召回2:用户最近浏览过的类目""" cats = {self.item_pool[i]["cat"] for i in self.user_history[-5:]} s = [it for it in self.item_pool if it["cat"] in cats] s = sorted(s, key=lambda it: it["hot"], reverse=True) return s[:top_n] def recall_by_vec(self, top_n=100): """召回3:基于最近一次交互的向量相似召回""" fav = self.user_history[-1] fav_vec = self.item_pool[fav]["vec"] def sim(it): v = it["vec"] dot = sum(a * b for a, b in zip(fav_vec, v)) n1 = sum(a * a for a in fav_vec) ** 0.5 n2 = sum(a * a for a in v) ** 0.5 return dot / (n1 * n2 + 1e-9) s = sorted(self.item_pool, key=sim, reverse=True) return s[:top_n] def merge_candidates(self, lists): """合并多路召回并按热度粗筛""" seen, cand = set(), [] for lst in lists: for it in lst: if it["id"] not in seen: seen.add(it["id"]) cand.append(it) return sorted(cand, key=lambda it: it["hot"], reverse=True)[:300] def rank(self, cand, top_n=10): """精排:加权打分模拟 CTR 模型""" fav_ids = set(self.user_history[-5:]) def score(it): sc = 0.3 * it["hot"] history_bonus = 0.5 if it["id"] in fav_ids else 0.0 return sc + history_bonus + random.random() * 0.2 s = sorted(cand, key=score, reverse=True) return s[:top_n] def recommend(self): recalls = [ self.recall_by_hot(), self.recall_by_cat(), self.recall_by_vec() ] cand = self.merge_candidates(recalls) return self.rank(cand) if __name__ == "__main__": r = MockRecommender(2000) print("=== Top 10 推荐 ===") for it in r.recommend(): print("id=%d cat=%d hot=%.3f" % (it["id"], it["cat"], it["hot"]))
self.item_pool = []初始化物品池,每个物品携带类目、热度分和随机特征向量,相当于商场的全部货架。s = sorted(self.item_pool, key=lambda it: it["hot"], reverse=True)按热度从高到低排序取前 100 件,模拟热度召回。cats = {self.item_pool[i]["cat"] for i in self.user_history[-5:]}从最近 5 次浏览中提取类目集合,构造用户偏好信号。dot / (n1 * n2 + 1e-9)余弦相似度打分,分母加极小值防止除零,是向量召回的核心。if it["id"] not in seen多路召回合并且去重,避免同一物品被多路重复送入排序。history_bonus = 0.5 if it["id"] in fav_ids else 0.0对用户最近互动过的物品额外加 0.5 分,模拟精排模型中的历史行为特征。random.random() * 0.2加入随机扰动,模拟模型预测中的噪声与探索。self.recall_by_hot(), self.recall_by_cat(), self.recall_by_vec()三路召回并行执行,各自取回 100 个候选,体现“分头行动、汇总候选”的思想。
常见误区
误区以为召回结果越多越好,把几万候选全部塞给精排模型,觉得模型看到的信息更全,推荐自然更准。
正解召回是“海选”而不是“决赛”。精排算力有限,候选过多会导致延迟飙升,大量无关样本还会稀释排序模型的判别力。漏斗每一层只做该层的事:召回保证“别漏掉对的”,精排保证“把对的排前面”。就像导购不会把整层楼的商品都搬给你试穿——展示太多反而让你无从选择。
为何常见:直觉上信息越多越好,但忽视了在线延迟与模型精度的平衡,也低估了噪声对排序的干扰。
误区离线评测跑分很高,模型上线后点击率却下跌,于是怀疑是线上系统出了 bug,而不是模型本身的问题。
正解离线数据来自历史,线上样本分布会漂移——用户今天的兴趣可能已经变了。离线指标只衡量排序一致性,没考虑展示位置偏差、用户反馈闭环等因素。最终效果必须靠线上 A/B 实验裁决。就像模拟考试的出题风格未必等于真实考场的考题,模拟考高分不能保证真考必胜。
为何常见:离线评测跑得快、反馈及时,人们下意识把它当成上线效果的保证,忽略了环境差异。
误区把数百个特征全部拼进模型,认为“堆料”就能提升精度,即使很多特征从业务上说不清含义。
正解冗余特征会带来噪声和过拟合,还会增大训练与在线推断的开销。工业界更看重特征“有用且新鲜”,通过特征重要性分析、消融实验来裁剪。好比导购记不住一千条没用的小道消息,记住几个关键偏好就足以服务好顾客。
为何常见:大数据时代“数据多即正义”的惯性思维,让人忽略特征质量与计算成本的代价。
误区把各路召回结果直接取并集,然后拿各自的原始分数比大小,认为分数高就说明更相关。
正解各路召回的打分尺度不同,热度分是 0 到 1 的归一值,向量余弦值在 -1 到 1 之间,而协同过滤的分数可能没有上界。直接比较毫无意义,需要先做规则融合或用粗排模型统一打分,再交给精排。就像不同导购用的评价标准不同,要先换算成同一套“顾客满意度”再比较。
为何常见:忽略了不同信号源的量纲差异,只想着快速上线,结果排序结果混乱。
误区认为所有特征都要做成实时流,模型也要分钟级更新,这样才够“先进”。
正解实时性成本很高,而且大多数信号变化很慢。用户年龄、长期兴趣这类特征离线天级更新完全够用,只有当下行为才需要秒级响应。实践中按特征变化速度分层:长期画像离线、短期行为流式、实时上下文在线。盲目追求全实时,只是把成本烧在收益极低的地方。
为何常见:受“实时=先进”技术叙事的影响,忽略了投入产出比,也低估了实时链路的稳定性代价。
面试题
Q1. 推荐系统典型流程中,“从亿级物品中快速圈出几百个候选”属于哪个阶段?
- A.数据清洗
- B.召回阶段← 正确答案
- C.精排阶段
- D.重排阶段
答案:B。召回负责海选,精排负责精细打分,重排负责多样性调整。就像导购先圈定几个区域再看具体商品,而不是直接一件件比价。
Q2. 多路召回中,哪一路对任何用户都会返回同样的结果?
- A.协同过滤召回
- B.向量召回
- C.热度召回← 正确答案
- D.相似物品召回
答案:C。热度召回按全局热度排序,与用户无关,因此所有用户拿到的候选基本相同。其他三路都依赖用户历史行为,属于个性化召回。
Q3. 逻辑回归用于 CTR 预估时,输出层用哪个函数把线性得分映射到 (0,1)?
- A.ReLU
- B.Softmax
- C.Sigmoid← 正确答案
- D.Tanh
答案:C。Sigmoid 将任意实数压缩到 0 到 1 之间,正好解释为点击概率。Softmax 用于多分类,ReLU 常用于隐藏层,Tanh 输出范围是 -1 到 1。
Q4. AUC 的统计含义是什么?
- A.模型预测的准确率
- B.随机正样本得分高于随机负样本的概率← 正确答案
- C.召回率能达到的最大值
- D.模型训练收敛的速度
答案:B。AUC 衡量排序质量,不依赖分类阈值,等价于随机正样本排在随机负样本前面的概率。AUC 越高,说明模型把真正该推荐的物品排得更靠前。
Q5. 下列哪些属于工业界常见的多路召回策略?
- A.热度召回← 正确答案
- B.协同过滤召回← 正确答案
- C.向量召回← 正确答案
- D.全量精确匹配
答案:ABC。热度、协同过滤、向量召回都是典型的多路召回策略。全量精确匹配复杂度极高,且与召回“快而全”的目标相悖,工业界不会对全量物品做逐条精确匹配。
Q6. 离线 AUC 很高,线上点击率反而下降,最可能的原因是什么?
- A.参数量过小导致欠拟合
- B.分布漂移且缺 A/B 实验← 正确答案
- C.精排链路耗时过长
- D.召回候选集数量过大
答案:B。离线数据分布与线上真实分布不一致(分布漂移),且缺乏线上 A/B 实验验证,是离线在线效果不一致的最典型原因。参数量大小、延迟和候选数量更多影响效率,而不是直接的模型效果。
Q7. 下列哪些手段可以有效降低精排阶段的延迟?
- A.粗排先筛掉大部分候选← 正确答案
- B.特征与模型结果做缓存← 正确答案
- C.使用向量近似近邻索引← 正确答案
- D.对全量物品逐个精排打分
答案:ABC。粗排减少进入精排的候选数,缓存避免重复计算,近似近邻索引加速向量检索,都能降低延迟。D 与降延迟目标完全相反,全量逐个精排在工业界不可行。
Q8. 冷启动场景下,给新用户随机推荐一些物品来收集反馈,属于哪种策略?
- A.热度召回
- B.探索与利用← 正确答案
- C.向量检索
- D.重排打散
答案:B。用 ε-greedy 这类策略以一定概率推荐随机物品,本质是“探索”——牺牲短期精准度换取用户偏好数据。热度召回、向量检索、重排打散都不直接产生探索反馈。
Q9. 精排建模中,把用户、物品、上下文信息拼接成向量作为模型输入,这一步叫什么?
- A.特征工程← 正确答案
- B.样本采样
- C.归并排序
- D.数据清洗
答案:A。构造并拼接特征向量是特征工程的核心工作。样本采样处理数据不平衡,归并排序是排序算法,数据清洗发生在接入层,都不是“拼接特征”这一步。
Q10. 关于召回排序架构的工业实践,下列说法正确的有哪些?
- A.召回快而全,排序精而准← 正确答案
- B.粗排可选但大流量必备← 正确答案
- C.多路召回分数可直接比较
- D.缓存与降级保障在线稳定← 正确答案
答案:ABD。A 准确概括了召回与排序的分工;B 正确,高流量场景必须用粗排衔接,否则精排扛不住;D 正确,缓存和降级是稳定性的基石。C 错误,各路召回打分尺度不同,必须先融合统一再进入排序。