本文是 买侧竞价链路 系列的第 6 篇(频控 · 配置)。 全系列 9 篇:
- Bidder 竞价服务架构
- OpenRTB 协议精讲
- Bidder 解析层
- Bidder 定向过滤
- RTA 竞价前过滤
- Bidder 频次控制:五维配置与身份降级
- Bidder 频次控制工程篇
- Bidder 预算 Pacing
- Pacing 目标曲线
一句话定位:运营在 DSP 后台能拧的频控旋钮是层级、窗口、事件、抑制和身份口径;设备 ID 缺失时,还要有一条不会把频控整体打穿的降级路径。
定向过滤篇的第六节探讨了频次控制在竞价漏斗中的执行层级,但并未深入探讨实际的运营配置。本篇旨在填补这一空白:系统梳理运营人员在 DSP 后台可调节的维度,并剖析当设备 ID 缺失或被置零时,需求方平台(DSP)该如何设计稳健的身份降级机制。至于这些配置如何映射到分布式计数与工程链路,请参阅姊妹篇频次控制工程篇。
一提起频次控制(Frequency Capping),很多人会简单地将其概括为「限制同一用户每天观看某广告的最高次数」。事实上,这句话里的每一个词都对应着一个关键维度:「同一用户」界定了身份口径,「某广告」锚定了控制层级,「每天」划定了时间窗口,「观看」定义了计数事件,而「最高次数」则决定了超出限制后的抑制规则。只有将这五个维度拆开来看,我们才能真正看清频控的全貌。
然而,在这五个维度之中,最容易引发生产事故的并非前四维的配置,而是第五维的身份口径。在程序化广告的真实场景里,「同一用户」这个前提往往并不牢靠。尤其是苹果实施 ATT 框架之后,大量流量失去了有效的 IDFA,设备 ID 经常是一串全 0,或者用户主动开启了限制追踪(lmt=1)。面对这种情况,频控被迫退化为一项「尽力而为(best-effort)」的任务;如何巧妙地设计降级策略,将直接决定这些无 ID 流量是惨遭批量丢弃,还是能够被合理、可控地投放。正因如此,本篇的最后两节将专门针对这一痛点进行拆解。
运营在后台配置的每一条频控规则,本质上都是由层级、窗口、计数事件、抑制规则以及身份口径共同构成的五维组合。其中,前四维属于后台的常规配置,而第五维的身份口径才是决定频控精准度的命门。
TL;DR
- 一条频控即五维组合:
[层级] × [窗口] × [计数事件] × [抑制规则] × [身份口径]。前四维是系统旋钮,而第五维的身份识别则是核心命门。 - 层级维度取最严:当 Advertiser、Campaign、Ad Group 与 Creative 多级 cap 同时生效时,任何一级的计数超限都会导致该候选广告直接 no-bid;同时,素材组的合并计数能有效防止通过更换尺寸来绕过限制。
- 时间窗口的权衡:常见的窗口包括 hour、day、week 以及 lifetime。自然窗口(tumbling)实现极简但边界容易产生突刺;相比之下,滑动窗口(sliding)更为精准,但需要付出更高的存储成本。此外,recency 机制常用于控制两次曝光的最小时间间隔。
- 计数事件与延迟:事件维度涵盖 impression、viewable impression 与 click。在工程口径上,基于 Win 计数响应快但容易高估,而基于 Impression 回传计数更准确却会引入延迟;生产中常采用「Win 预扣 + Impression 对账」的折中方案。
- 抑制规则的应用:点击后抑制、转化后排除以及已购人群排除,本质上都是「频次上限为 0」的特殊频控场景。
- 硬 cap 与频次衰减:与其在触达上限时一刀切地终止投放(硬 cap),不如让出价随曝光次数的增加而平滑递减(频次衰减)。这种将边际效用交给实时竞价(RTB)来判断的策略,通常能带来更优的投资回报率(ROI)。
- 身份口径尽力而为:鉴于程序化身份的碎片化特征,需求方(Buy Side)通常需要依赖 Cookie Matching、UID2、RampID 或 PPID 将各 Exchange 的 ID 归一化;需要强调的是,匹配率永远无法达到 100%。
- 全 0 标识的灾难:如果将全 0 或缺失的设备 ID 错误地合并为一个用户,合并计数会在瞬间打满 cap,导致整批无 ID 流量被全部 no-bid。
- 身份越弱,频控越软:在身份降级链条中(统一 ID → 设备 ID → 概率指纹 → IP 网段),身份的可靠性越弱,频控的约束就应越宽松。针对无 ID 流量,必须分配独立的命名空间,同时采取更宽松的 cap 和更保守的出价策略,并且对于
lmt=1的流量坚决不进行用户级追踪。
Table of contents
Open Table of contents
一、先建立框架:运营配的是一个五维组合
打开任何一个成熟的需求方平台(DSP)后台,你会发现频次控制从来都不是一个孤零零的输入框。它散落在不同层级的设置页面中,由一系列下拉框和数字框拼凑而成。为了厘清这些配置,我们需要将其归纳为五个核心维度:
| 维度 | 回答的问题 | 典型取值 |
|---|---|---|
| ① 层级 | 对哪一级广告主体进行限频 | Advertiser / Campaign / Ad Group / Creative |
| ② 时间窗口 | 在多长时间周期内进行计数 | hour / day / week / month / lifetime |
| ③ 计数事件 | 什么样的行为算作一次有效计次 | impression / viewable / click |
| ④ 抑制规则 | 超限或特定事件发生后如何处理 | 硬 cap / 点击后抑制 / 转化后排除 |
| ⑤ 身份口径 | 同一个用户到底是谁 | 统一 ID / 设备 ID / 概率指纹 / IP 网段 |
在实际应用中,一条完整的频控规则就是这五个维度的笛卡尔组合。例如:
DeviceID × Creative × (1h≤1, 1d≤3) × Impression × 硬 cap
UID2 × Campaign × lifetime≤20 × Viewable × 频次衰减
需要注意的是,运营在后台能够灵活调节的往往只有前四维;而对于第五维的「身份口径」,运营通常只能控制如「是否跨设备」这类开关。然而,这背后的底层身份可靠性,才是决定频次控制究竟准不准的真正主因。
二、层级维度:cap 树与「取最严」原则
我们首先来看第一个维度:对谁限频。在广告系统中,主体是严格分层的,从上至下依次为 Advertiser(广告主)、Campaign(订单)、Ad Group(广告组)以及 Creative(素材)。通常情况下,DSP 后台允许在这四个层级分别设置 cap,并且它们会同时生效。
多级 cap 之间是严格的「与」关系。当 Advertiser、Campaign、Ad Group 和 Creative 任意一层的计数触达上限时,该广告的竞价请求就会被直接 no-bid,最终的实际触达次数由最严格的那一层约束决定。
在这里,有几个配置要点需要格外关注:
- 多级取最严(AND 逻辑):假设我们同时设置了 Campaign 级别每天最多 10 次,以及 Creative 级别每天最多 3 次。那么,针对单条素材,用户最多只会看到 3 次;而该 Campaign 下的所有素材加起来,一天内最多曝光 10 次。这两个约束条件必须同时成立。
- 素材层防疲劳机制:由于同一个 Campaign 往往会挂载多条创意,如果仅仅设置 Campaign 级别的 cap,用户极有可能会被同一批素材反复轰炸。因此,引入 Creative 级别的 cap 才能有效保证用户不会对单条素材产生视觉疲劳。
- 素材组(Creative Concept)的合并计数:在实际投放中,同一创意通常会适配多个不同的尺寸或版本。如果简单地按照单个 Creative ID 进行计数,一旦用户在其他版位看到另一个尺寸的同款创意,系统就会「重新计数」,这实质上等同于绕过了频控限制。为了解决这个问题,成熟的 DSP 均支持将这些变体归拢到一个 Concept 层级进行统一的合并计数。
- Advertiser 级别的全局封顶:该机制用于控制某个广告主旗下所有 Campaign 的总触达上限。通过这一全局约束,可以防止同一广告主的不同 Campaign 产生叠加效应,进而避免将同一个用户打爆。
接下来,我们看看这些层级维度是如何映射到主流 DSP 的具体配置中的:
| DSP | 频控配置位置 / 叫法 |
|---|---|
| DV360(Google) | Line Item / Insertion Order 层 Frequency cap,支持按天、周、月或生命周期设置,且可实现跨设备频控 |
| The Trade Desk | Ad Group 层 Frequency 模块,支持多条 cap 并行,同时提供 Impression frequency 优化选项 |
| Amazon DSP | Line item 层 Frequency cap,支持多种时间窗口组合配置 |
三、时间窗口维度:自然窗口与滑动窗口的取舍
第二个维度探讨的是「在多长时间周期内进行计数」。这正是 DSP 后台里常见的按小时、按天、按周或按生命周期(lifetime)配置的下拉选项。在实际应用中,多条窗口规则常常会并存:
至多 1 次 / 小时
至多 3 次 / 天
至多 10 次 / 周
至多 20 次 / Campaign 生命周期
其中,lifetime cap 在品牌广告投放中尤为常见。它的核心诉求是在整个投放周期内控制对单用户的总触达次数,以达成「有效触达而不构成骚扰」的微妙平衡。当然,这种方式对系统的存储能力提出了极高的要求,因为它的窗口跨度贯穿了整个 Campaign 的生命周期。
深入到底层实现,窗口维度的工程分歧主要集中在如何定义和实现这个「窗口」:
- 自然窗口(Tumbling / Calendar Window):这种模式按自然时间边界(例如每日凌晨 0 点)准点清零。它的工程实现极其简练,通常只需一个附带 TTL(Time To Live)的计数器 Key,如
fc:{user}:{ad}:{yyyymmdd}。然而,这种方案的硬伤在于边界突刺问题:如果用户在 23:59 看到一次广告,紧接着在次日 00:01 又看到一次,虽然从系统层面看分属两天且均未超限,但用户的实际体感却是「连续被砸了两次」。 - 滑动窗口(Sliding Window):这种模式强制要求在过去 24 小时内总曝光不超过 N 次,显然更贴合用户的真实体感。但为了实现这一点,系统要么需要完整存储每次广告曝光的具体时间戳(成本极其高昂),要么只能采用如 Count-Min Sketch 或分桶计数等近似数据结构,以牺牲部分精度来换取存储空间的节省。
考虑到程序化广告生态中极高的并发请求量(单 DSP 节点往往面临十万至百万级别的 QPS),严苛的存储成本约束迫使大多数系统默认采用「自然窗口结合短 TTL」的方案,仅在极少数高净值场景中才会启用昂贵的滑动窗口机制。
除了控制总量,还有一个控制展示节奏的关键旋钮常常被忽略:
- Recency(最小间隔控制):该机制强制要求距离上一次曝光至少间隔特定时长后,才允许进行下一次展示。它并不限制总次数,而是通过拉开两次曝光的时间跨度,有效避免了「用户在五分钟内被同一广告连续轰炸三次」这种恶劣体验,即使这并未触碰当天的总 cap。
四、计数事件与抑制规则
4.1 计数什么事件
第三个维度聚焦于「什么样的行为算作一次有效计次」:
- Impression(广告曝光):这是最基础也是最普遍的默认计数方式。
- Viewable Impression(可见曝光):只有当广告真正进入用户屏幕的可见区域(满足 viewability 标准)时才计入频次。这种方式显然更符合「用户确实看到了」的业务初衷。
- Click(点击):这类事件通常作为点击后抑制策略的触发条件。
这里隐藏着一个困扰需求方已久的口径难题:究竟是应该在赢得竞价(Win)时就立刻计数,还是等待真实的 Impression 回传后再进行累加?
- 按 Win 计数:只要赢下竞价就立即加 1。这种方式响应极其及时且工程实现简单,但由于赢得竞价并不等同于真实曝光(广告可能最终未渲染或未进入可见区域),往往会导致系统高估实际频次,进而引发严重的投放不足(under-delivery)。
- 按 Impression 回传计数:只有接收到真实的曝光回调才进行加 1 累加,数据绝对精准。但代价是网络回传存在秒级延迟,在高并发窗口下,极易导致实际曝光超出预设上限。
正因如此,生产环境中普遍采用了一种折中方案:在赢得竞价时预扣(reserve)一个名额以防止并发超投,待收到 Impression 回传时再进行最终确认与对账。这套依赖「本地预扣加异步回灌」的分布式一致性机制,在本质上与预算控制的超投问题属于同一类工程挑战;我们在竞价架构总览一文中对此有过详尽的剖析。
4.2 抑制规则:频次为 0 的特殊形态
除了正向设置「最多允许 N 次展示」,运营人员还常常需要配置「绝对不再投放」的反向抑制规则:
- 点击后抑制:当用户点击过某条广告后,在未来的 X 天内将不再向其展示。既然用户已经表达了明确兴趣甚至已经到达了落地页,继续投放无疑是对预算的无谓浪费。
- 转化后排除:对于已经完成转化的用户,系统应立即停止投放。既然用户已经完成购买,再花钱进行触达显然毫无意义;这通常通过对接转化像素并结合排除人群(suppression audience)来实现。
- 已购 / 已注册人群排除:通过上传第一方数据或对接外部人群包,将特定用户直接加入黑名单(exclusion list)。
透过五维框架来看,这些规则本质上都是「频次上限强制为 0」的特殊场景,只是其触发条件从单纯的「曝光次数」转变为了「发生了某个关键的下游事件」。
五、策略维度:硬 cap 与频次衰减的博弈
第四个维度决定了当用户的曝光次数接近或达到上限时,系统该如何应对。这也是频控策略中最具优化空间的一环。
与硬 cap 简单粗暴的阶跃式阻断不同,频次衰减策略通过出价折让,将边际效用递减的判断权巧妙地交给了实时竞价机制。在程序化买方的实践中,这种柔性策略往往能带来更优的 ROI。
5.1 硬 cap
硬 cap 的逻辑最为直接:一旦计数达到上限,后续请求直接 no-bid。这种方案胜在简单直白、极易解释且绝对可控。但它的致命弱点在于「一刀切」:用户的第 3 次与第 4 次曝光之间,其商业价值绝不会突然归零。直接砍断投放,往往会白白流失掉一部分原本极具性价比的触达机会。
5.2 频次衰减(Frequency Decay)
对比前一种方案,频次衰减策略摒弃了生硬的阻断,转而随着同一用户累计曝光次数 n 的攀升,对预估点击率(pCTR)、预估转化率(pCVR)或基础出价(bid)施加一个递减的折扣系数:
bid_n = bid_0 · e^(-λ(n-1)) # n=1 时为全价,随后依指数曲线平滑衰减,λ 用于调节衰减速率
由于同一用户反复观看同一广告的边际转化效用必然呈现递减趋势(第 5 次曝光促成转化的概率远低于第 1 次),让出价随之同步下调,就能将「是否还值得继续投放」的艰难抉择顺理成章地交给实时竞价网络(RTB)。如果折让后的出价依然划算,就能继续赢下竞价;反之,自然会在拍卖中败给其他出价更高的竞争者。尽管这种方案在调参和效果解释上颇具挑战,但它无疑更加平滑、更节省预算,且能显著提升整体的 ROI。
5.3 目标频次:追求下限的软控艺术
需要强调的是,在品牌广告的语境下,广告主的终极诉求往往并非「千万别超过 N 次」,而是「必须有效触达至少 N 次」(例如经典的 3+ Reach 理论,即触达三次以上方能形成稳固的品牌记忆)。在这种场景下,DSP 后台通常会提供诸如 Target Frequency 或 Optimize for Reach 的专项优化开关;系统会朝着目标频次全力优化,这堪称频次控制的「反向」高级形态。
更为高阶的玩法则是序列化投放(Sequential Storytelling):通过精细控制多组素材向同一用户的展示次序(例如,先通过品牌故事 A 建立认知,再利用促销信息 B 促成转化)。
六、身份口径维度:程序化频控的命门
正如前文所述,前四维只是系统提供的配置旋钮,而第五维的「身份口径」才是决定频控精准度的核心基石。频次控制的先决条件是识别「这到底是不是同一个人」,而在复杂的程序化广告生态中,这一前提天生就充满了变数与不确定性。
6.1 身份识别的重重困境
- 身份的极度碎片化:同一个真实用户在不同的供给方平台(SSP)和 Exchange 体系中,往往挂载着截然不同的 ID 标识(这归咎于 Cookie 同步机制的割裂),甚至在不同的物理设备上也会对应完全不同的身份标签。
- ID 标识的大面积缺失:自 iOS 强制推行 ATT 隐私框架以来,海量请求中的 IDFA 字段沦为空值;与此同时,第三方 Cookie 的可用性也在持续断崖式下跌,导致大量底层流量根本不携带任何稳定的身份标识。
- 合规红线的刚性约束:一旦用户明确开启了限制追踪功能(例如请求中携带
lmt=1或dnt=1标记),从隐私合规的法理层面讲,系统就必须无条件停止针对该用户个体的追踪与识别行为。
6.2 买方侧的身份归一化突围
当买方(Buy Side)接收到 Bid Request 时,拿到的是 SSP 传递过来的原始 User ID。为了执行跨域频控,买方必须通过 Cookie Matching 或 ID Sync 等机制,将这些碎片化的 Exchange ID 强行映射回自身的内部 UserID 体系。为了彻底摆脱这种低效的映射,行业正加速向统一 ID 标准靠拢:
- UID2(Unified ID 2.0):这一开源标准以用户的哈希化邮箱或手机号作为核心种子,经过 Operator 节点的加盐与重度加密处理后,生成一个具备高确定性且支持跨设备追踪的全局 ID。
- RampID(LiveRamp):依托庞大的身份图谱(Identity Graph),该方案能够将「同一个真实人类」散落在各处的异构标识进行深度聚合与假名化处理,并针对不同的生态合作伙伴派生出相互隔离的 ID 变体。
- PPID(Publisher Provided ID):这属于媒体方(Publisher)自主生成且仅限其第一方域内有效的基础 ID。虽然它无法实现跨媒体追踪,但在身份缺失时,常常被用来作为兜底的防波堤。
这些统一 ID 在生成机制上的差异(包括种子来源、加盐策略、加密算法、作用域边界以及隐私保护机制),值得我们在后续专门开辟一篇进行深度剖析。但就当下而言,它们最大的核心价值就在于:能够将「同一个真实用户」在不同 Exchange 和设备终端产生的海量请求,精准归拢到同一个频控 Key 之下,从而让跨域频次控制从理论走向了现实。
6.3 无法回避的现实:匹配率永远无法触及 100%
遗憾的是,无论是依赖传统的 Cookie Matching 还是拥抱先进的统一 ID,匹配率都永远无法达到完美的 100%。在浩如烟海的请求中,总有相当一部分流量面临身份错位,或者干脆彻底失去了任何可用的 ID 标识。这直接导致了程序化频控注定是一项「尽力而为」的工程妥协:对于能够精准识别的部分,必须做到锱铢必较;而对于无法精准识别的模糊地带,则必须设计出一套严密的身份降级口径。
七、无设备 ID 与全 0 标识的灾难与救赎
如何妥善处理那些丢失了 GAID / IDFA,或者设备 ID 被强行抹为 00000000-0000-0000-0000-000000000000(全 0)的残次流量,是买方侧频次控制中最核心也最容易引发大规模生产事故的一环。对此,我们的基本原则是:必须实施分级 Fallback 策略并赋予明确的降级语义,绝不能简单粗暴地予以丢弃,更不能愚蠢地将其强行合并计数。
7.1 第一步:给身份「可用性」进行分类
在接收到 Bid Request 的第一时间,我们必须对设备 ID 的状态进行精准判别,其中的核心底线是:绝不能将「全 0」视作一个真实的独立用户。
| 状态 | 典型特征 | 核心语义 |
|---|---|---|
| 有效 ID | 合规的 IDFA / GAID / OAID | 支持实施精确的用户级频次控制 |
| 全 0 / 缺失 | 呈现为 000000-... 或完全缺省 | 遭遇 ATT 拦截、LAT 开启或采集失败 |
| LAT 标记 | 携带明确的 lmt=1 或 dnt=1 标记 | 用户明确拒绝追踪,触发合规红线 |
| 异常脏数据 | 全 F 字符、固定测试桩或高频重复值 | 归一化逻辑失效,数据严重失真 |
必须再次强调: 绝对不要将所有设备 ID 为全 0 的请求荒唐地归结为同一个「超级用户」去累加频次。一旦这样做,这个虚构的「超级用户」会在毫秒级瞬间被打满 cap,直接导致系统中一整批无 ID 流量惨遭无情 no-bid;而必须正视的是,在某些特定的流量源(尤其是 iOS 生态),无 ID 流量往往占据着惊人的高额比例。全 0 必须被严格界定为「完全丧失用户身份」,绝不允许被合并成一个单一的控制键值。
7.2 分级 Fallback 身份链
在确认身份可用性后,系统需按照优先级从强到弱的顺序依次尝试,一旦命中即立刻采用:
拿到请求后的身份口径决策链严格遵循:统一 ID > 设备 ID > 概率指纹 > IP 网段 > 直接放弃。尤其需要警惕的是,
lmt=1 或全 0 这一分支必须直接跳出用户级追踪,不再参与任何实质性的频次累加;这不仅是不可逾越的合规红线,更是避免发生「全 0 误合并」灾难的工程底线。
① 统一 ID:提取 request 携带的 UID2 / RampID / PPID(优先级最高,支持跨域与跨设备)
② 平台 / 登录 ID:使用 SSP 传递的 hashed email、CTV 的 IFA 或 publisher user id
③ 设备 ID:验证 IDFA / GAID / OAID 是否有效,且必须满足 lmt≠1 的前置条件
④ ─────── 若以上均未命中,系统自动降级进入「无稳定 ID」处理分支 ───────
⑤ 概率指纹:通过哈希 (IP网段 + UA + OS + 设备型号 + 屏幕分辨率 + 语言 + 时区) 组合生成
⑥ 纯上下文:退化至仅依赖 IP 或地理位置进行网段级粗略频控,或彻底放弃用户级频控
7.3 无稳定 ID 时的三种降级策略
策略 A:概率指纹(Fingerprint)。 该策略通过组合 IP + UA + OS + 设备型号 + 屏幕特征 + 语言 + 时区 并进行哈希计算,凭空捏造出一个「准身份」。这使得对无 ID 流量实施近似频控成为可能,但其先天缺陷也极其明显:在 NAT 网络或公共 WiFi 场景下,多用户共享 IP 极易引发误合并(导致过度限频);而一旦 IP 发生动态变更,又会将同一个真实用户错误地拆分为多个个体(导致限频失效)。更为棘手的是,在严苛的 lmt=1 或 GDPR 合规框架下,任何指纹生成行为本身都潜藏着巨大的法律风险。为了缓解这些问题,工程上通常建议将精确 IP 替换为 /24 掩码网段,并辅以更加宽容的 cap 阈值。
策略 B:粗粒度上下文限频。 这是一种彻底放弃「精确追踪到人」的妥协策略,转而对更加宏观的实体进行限频。例如,规定「针对同一 /24 网段每天最多展示 K 次(将 K 适当放大)」,或者直接摒弃绝对总量控制,改用按 App 级别配合广告版位来实施基于 recency 节奏的软性约束。
策略 C:将负担下推至 SSP / 媒体侧。 既然无 ID 流量在买方侧本就难以驾驭,那么一种聪明的做法是在 Deal 交易参数中明确声明期望的频控上限,从而将执行的重任完全推卸给拥有第一方 PPID 优势的媒体侧去完成。买方自己则完全退居二线,仅专注于宏观预算的平滑消耗(Pacing)与上下文维度的精准定向,不再背负用户级精准频控的沉重包袱。
7.4 工程实现的铁律
- 为无 ID 流量开辟独立的命名空间:绝不允许将残次标识与高可信的有 ID 流量混杂在同一个 Key 空间内。
高信度有效 ID: fc:uid2:{token}:{campaign}:{window}
概率指纹软 ID: fc:fp:{soft_id}:{campaign}:{window} # 采用独立前缀,同时放宽 cap 约束
无身份全 0 类: 拒绝计数累加,强制导入上下文或粗粒度策略分支
- 身份置信度越弱,频次控制越软,出价策略越趋于保守:当频控机制的底层支撑不可靠时,宁可主动压低出价,也必须全力避免对潜在用户造成过度打扰。
- 对于
lmt=1、dnt=1及全 0 标识直接判定为「不可追踪」:此类请求严禁卷入用户级别的频次累加逻辑,强制走纯上下文降级策略。这是一道不容触碰的合规红线。 - 将无 ID 流量占比纳入核心监控指标体系:这项数据能够帮助运营团队深刻理解,为什么看起来极其严密的频控报表最终会变得「不再精准」。
在「身份碎片化 + 分布式高并发 + 毫秒级苛刻延迟 + 成本敏感型高 QPS」这四重工程枷锁的严密束缚下,频次控制注定只能是一场「尽力而为」的艰难突围。唯一行之有效的工程解法就是坚决实施分级 Fallback:能精确到人的坚决精确;一旦失去身份支撑,就果断降级至粗粒度控制甚至退化至纯粹的 Pacing 消耗逻辑。身份越弱,频控的颗粒度就必须越软;而对于 全 0 或 lmt=1 的流量,唯一的正确做法就是干脆利落地将其踢出用户级追踪的范畴,这既是对合规红线的敬畏,也是避免「误将万人当一人」这一工程灾难的最有效手段。
八、配置如何落地到执行
运营在后台轻轻拧动的每一个配置旋钮,显然不可能直接生硬地塞进竞价引擎那毫秒必争的关键路径里。在这两者之间,横亘着一条高度精密且历经锤炼的落地链路。接下来,我们不妨剖析一次典型的广告曝光在其生命周期内,究竟需要牵涉哪些核心组件,以及它们之间是如何协同运转的:
限制曝光的核心组件协作全景图:Bidder 负责核心的身份归一与实时判定,频次计数存储(Redis / Aerospike)承载关键路径的极速读取与 Win 预扣,Kafka 充当坚实的异步日志总线,而 Flink 则主导真实曝光的精准对账与最终加 1。其中,读计数被死死嵌在关键路径并附加了严格的超时降级保护;确认加 1 走异步回灌机制,这段时间差不可避免地构成了工程上的 dead time,因此系统在架构设计上就必须容忍一定程度的小幅超投。
- 后台配置到运行时编译的热更新下发:就像复杂的定向规则一样,频控阈值同样需要经过配置中心(例如 Nacos)的实时编译和热更新,通过原子级别的快照切换静默生效,完全摆脱了传统的发版依赖。在这条链路上,必须确保「后台展现的语义」、「配置中心编译定型的结构」以及「Bidder 运行时的匹配逻辑」这三者高度对齐(这与我们在配置落地篇中探讨的核心理念完全一致)。
- 前置粗筛与后置精细频控的楚河汉界:凡是那些与具体候选无关、可以通过本地布尔逻辑直接判断的条件(例如全局用户级频控、或者已经达标必须被整体排除的 Campaign),都应该尽可能地前置到定向过滤阶段,以实现最大限度的流量削峰;相反,对于诸如
per-user × per-campaign这种精细到令人发指的联合封顶逻辑,则必须在产生了具体的候选队列之后逐条进行精细判定。这往往涉及在排序闸门开启的瞬间,对 Redis 发起一次带超时的极其关键的点查。关于这套执行顺序的深层考量,在定向过滤篇的第六节已有透彻论述,不再赘述。 - 直面分布式一致性的挑战:由于计数状态被强行打散在多个独立的实例中,加之真实的物理曝光存在固有的网络延迟,系统发生轻微的超投几乎是无可避免的。这是工程上必须咽下的取舍,其背后的深层逻辑属于竞价服务架构那一篇的内容。
- 存储选型与读写分离的艺术:究竟是采用 Redis 的 String 结构处理自然日,Hash 分割小时桶,还是借助 ZSet 实现毫秒级的滑动窗口?为什么写操作必须剥离到旁路进行异步回灌?读请求又凭什么敢在 Bidder 的关键路径上横冲直撞,甚至要靠本地缓存来硬抗热点突刺?这些工程级别的硬核拷问,都将在频次控制工程篇中找到答案。本篇探讨的所有旋钮一旦拧下,最终都将沉淀到那套复杂精密的存储与执行链路之中。
- 频控与 Pacing 的宿命纠缠:频次控制会冷酷地挥刀砍掉一大批本可参与竞价的合法请求,这不可避免地会直接迟滞预算的整体消耗速度。如果 cap 设置得过于苛刻,可投放流量池就会急剧萎缩,最终导致预算根本花不出去(under-delivery)。因此,在调整频控阈值时,必须时刻兼顾 Budget Pacing 的节奏,绝不能让这两个核心机制在暗中互相倾轧。
九、运营配置常见坑
- cap 设太严导致预算花不完:频次控制和 Pacing 天生就是一对矛盾体。cap 越是严苛,可用于竞价的流量底盘就越小,预算消耗也就越发困难。每次上线新的 cap 阈值后,必须死死盯住最终的 delivery 效果。
- 多级 cap 叠加时的触达计算谬误:由于各级 cap 都是同时生效并严格遵循「取最严」的逻辑,因此最终的实际触达次数完全取决于约束最紧绷的那一层,绝不是简单的层级相加。很多运营人员在预估「用户到底能看几次」时,往往就栽在这个最基本的加法陷阱上。
- 超投是常态,切莫草木皆兵:受制于回传网络延迟和高并发环境,实际曝光量略微超过预设的 cap 上限完全属于正常现象。如果在报表中发现微小幅度的超出,请牢记这是分布式计数架构的固有特征,而不是系统出了什么严重故障。
- 匹配率不足导致频控效果打折:跨设备或跨 Exchange 的频次控制,对于那些根本无法匹配上身份标识的流量必然会彻底失效。如果发现最终的报表数据不够精准,很大概率就是源于这部分无法被有效追踪的受众;日常监控必须牢牢盯住无 ID 流量的整体占比。
- 窗口周期越长,数据漂移越严重:时间窗口越拉越长(如 lifetime cap),底层身份标识的稳定性就越脆弱,随之而来的长周期计数误差就会以几何级数被放大。
- 时区与日型错配的灾难:「一天」这个概念,究竟是指广告主所在的物理时区,还是指最终用户所处的当地时区?在跨国投放的复杂场景中,稍有不慎,这种错位就会让原本规划好的「每日 cap」偏移十几个小时(这与在定向过滤篇中探讨的 dayparting 口径错位问题如出一辙)。
- 全 0 标识被错误合并:正如前文反复强调的,这是最不可饶恕的系统级事故。它会导致系统中整整一批庞大的无 ID 流量惨遭集体封杀(no-bid)。
延伸阅读
- Bidder 频次控制工程篇:多维度限频的存储选型与读写分离:本篇的工程实现姊妹篇——配置旋钮拧下去之后,计数怎么存(String / Hash / ZSet)、写为何走旁路、读为何就近 + 本地缓存兜热点。
- Bidder 定向过滤(Targeting Filter):第六节讲频控在竞价漏斗里的位置——哪半能前置粗筛、哪半必须后置逐条判定,与本篇的「配置维度」互补。
- Bidder 竞价服务架构(总览):第 5 篇「分布式频次控制」讲多实例计数的一致性(本地计数 + 异步回灌 + 容忍超投),是本篇未展开的执行细节。
- Bidder 预算 Pacing:PID 控制与消耗平滑:频控砍流量会影响消耗速度,cap 太严会导致预算花不完——两者必须协同。
- Pacing 目标曲线:时段消耗权重怎么设计:与 pacing 的另一半,理解频控对可竞价流量的影响如何传导到目标曲线。
- 冷启动:程序化栈每一层都在解同一个问题:新 campaign / 新用户缺乏历史时,频控与身份口径如何先保守再收敛。
- 配置如何落地成 Snapshot:后台频控阈值怎么编译定型、热更新下发到 Bidder。
- IAB TCF 与同意管理:
lmt/ consent 的合规背景——为什么lmt=1必须跳出用户级追踪。
一手资料与背景:
- IAB Tech Lab. OpenRTB 2.6 Specification:
device.ifa/device.lmt/device.dnt等字段的定义——它们决定了频控的身份口径从哪来、什么时候必须降级。 - The Trade Desk. Unified ID 2.0:UID2 的开放文档——统一 ID 作为跨域频控 key 的来源之一。
- LiveRamp. RampID:people-based 身份解析与假名化 ID 的商业方案。
附录:术语表
- 频次控制(Frequency Capping):限制同一用户对某广告 / campaign 在某窗口内的曝光次数。
- cap 树 / 取最严:Advertiser / Campaign / Ad Group / Creative 多级 cap 同时生效,任一超限即 no-bid。
- 自然窗口(tumbling):按自然边界(如每天 0 点)清零的计数窗口,省存储但有边界突刺。
- 滑动窗口(sliding):过去 N 小时内计数,更精确但需存时间戳或近似结构。
- recency(最小间隔):两次曝光之间的最小时间间隔,控节奏而非总量。
- Win 计 / Impression 计:按赢价计数(及时但高估)还是按曝光回传计数(准但延迟)。
- 频次衰减(Frequency Decay):随曝光次数递增而降低出价的软频控,
bid_n = bid_0·e^(-λ(n-1))。 - suppression audience(排除人群):已转化 / 已购 / 已注册用户组成的排除名单,相当于频次为 0。
- UID2 / RampID / PPID:三种统一 / 一方 ID,用作跨域或单媒体的频控 key。
- cookie matching / ID sync:把各 exchange 的用户 id 映射到买方内部 UserID 的过程。
- 概率指纹(fingerprint):用 IP+UA+设备属性哈希出的「准身份」,无稳定 ID 时的近似口径。
- 身份可用性分类:把设备 ID 分为有效 / 全 0 空 / lmt 标记 / 脏数据,决定用哪种口径。
- 全 0 设备 ID:
00000000-...,代表无用户身份,绝不能合并成一个用户计数。