一条支付请求从前端发起,到最终返回“成功”或“拒绝”,中间要经过多少层风控计算?这个问题的答案,直接决定了一个风控系统的质量和一家公司面对黑产时的生存能力。我见过太多团队把风控当成“一个算法模型”来做,上线一个评分卡就觉得万事大吉,结果线上被薅羊毛薅到崩溃;也见过公司盲目堆砌规则,上千条if-else写得比业务代码还复杂,最后误杀率居高不下,用户投诉把客服都打爆了。
做风控这些年,我最深的体会是:风控从来不是一个点,而是一条完整的链路。从你接收流量那一刻起,到决策引擎做判断,再到模型训练、特征计算、人工审核,每一个环节都缺一不可。单纯谈算法,没有架构支撑,跑不起来;单纯建架构,没有算法填充,只是个空壳。这篇文章我就想彻底聊聊,一个真正能打的风控系统,从架构到算法到底应该怎么搭。不是什么高深理论,全是我自己实打实的项目经验和踩坑记录,希望对正在做风控或者准备做风控的同学有点帮助。
1. 风控系统的整体架构设计思路
很多人一上来就问我:“你用的什么模型?XGBoost还是深度学习?”我的回答通常是:“先别急着选模型,你先告诉我你的架构长什么样。”模型再强,如果架构支撑不了毫秒级的实时决策,一切都是白谈。风控架构不是简单的“前端 + 后端 + 数据库”,它是一整套围绕“风险决策时效性”和“数据闭环”设计的体系。
1.1 一条请求要经过多少层风控
假设一个用户在我们的平台上发起了一笔转账交易,这个请求从进入我们系统到返回风控结果,经历了一条完整的链路。我用实际例子拆解一下。
第一层是流量接入层,也可以叫风控网关。所有请求统一从这里进入,不管是来自App、H5、小程序还是开放API,都会先经过这个网关。网关做了几件事:解析请求头、提取设备指纹、获取IP归属地、识别用户唯一标识。这一层不做什么复杂判断,但它承担了一个重要职责——标准化。把所有来源的请求数据统一成一套规范格式,让下游的规则引擎和模型引擎不需要关心请求到底来自哪个端。
第二层是决策层,这是风控的核心,通常由规则引擎、模型引擎和人工审核模块组成。规则引擎里跑的是我们沉淀下来的规则,比如“24小时内同一设备关联超过5个账号,命中高危名单”“转账金额大于1万且IP属于风险地区,触发二次验证”。模型引擎则加载训练好的模型,实时计算出风险分数。决策引擎把规则命中的结果和模型分数结合起来,给出最终决策:放行、拒绝、转人工审核或者追加验证码。
第三层是数据层,这一层负责支撑上面两层。在线部分需要访问Redis缓存中的黑名单、白名单、历史行为特征;离线部分则需要从数据仓库读取历史数据做分析和模型训练。数据层还要解决一个关键问题——特征计算。比如“用户近5分钟操作频率”这种特征,必须在请求时实时算出来,延迟不能超过几十毫秒。
第四层是处置层,也就是决策之后的执行动作。比如调用验证码服务、触发短信通知、拉起人脸识别,或者直接拒绝并把账号加入灰名单。处置层还要把每一次决策结果记录下来,方便后续分析、回放、建模。
这四层环环相扣,缺一环都不行。我见过一些初创团队,风控逻辑直接写在业务代码里,散布在各个微服务中,结果出了问题根本没法统一排查。后来我们把所有风控逻辑收敛到独立的风控平台,统一走网关,维护成本一下子降下来了。
1.2 实时决策与离线分析的双链路
风控里有一个非常核心的矛盾:在线要求毫秒级响应,离线要求海量数据全量计算。这两件事本质上无法在同一套技术栈里完成,所以架构上必须拆成两条链路。
实时链路解决的是“当前这笔请求是不是有问题”,它要求低延迟、高可用。通常我们用Flink做实时计算,消费业务系统的行为日志,滑动窗口计算用户短时间内的行为频次;用Redis缓存特征和名单数据,保证单笔请求的查询时间可控;决策引擎本身也要尽量做到无状态,方便水平扩容。这一链路是7×24小时不间断运行的,任何抖动都可能导致线上交易大面积受影响。
离线链路解决的是“风险趋势是什么、模型怎么迭代、策略效果如何”。这里用的是批处理架构,每天凌晨跑数仓任务,把前一天的交易数据、风险数据、行为数据汇总成宽表,喂给特征平台做批量特征计算,再用于训练模型、回测策略、生成监控报表。离线链路不需要极致速度,但要求数据准确、口径一致。
两条链路必须协同。比如我们在实时链路上计算“用户近30分钟下单频次”,这个特征的定义必须和离线链路完全一致,否则训练模型时用A口径的特征,线上推理时用B口径的特征,模型效果会直线下降。我后面会详细讲这个“线上线下特征一致性”的坑,这是所有风控团队几乎都会踩的坑。
1.3 高可用与容灾设计的几个关键点
风控是旁路系统也好,是必经链路也罢,一旦它出故障,业务不能跟着挂。所以风控系统的高可用设计有一些独特的思路。
首先要做好降级预案。决策引擎依赖Redis、数据库、外部数据服务,如果这些依赖挂了,风控不能一直卡住交易。我们的做法是设计分级降级策略:第一级,核心黑名单规则缓存到本地内存,即使Redis挂了也还能命中高危名单;第二级,模型引擎超时后走快速规则兜底,直接放行高风险值在安全范围以内的请求;第三级,无法判断时默认转人工审核,宁可慢也不放高危风险通过。
其次是限流与熔断。风控网关自己也会被攻击,尤其是大促场景下流量瞬间暴涨。网关需要按接口维度限流,一旦某个后端模块响应超时率达到阈值,就触发熔断,把流量切到备用模块。
最后是流量影子与压测。每次风控规则或者模型上线前,我们都会把真实流量复制一份到影子环境,用旧策略放行但记录新策略的结果,观察两者差异。这样就算新策略有严重问题,也不会影响线上真实决策。这个习惯帮我避开过无数次事故,强烈推荐每个团队都建立这样的机制。
2. 特征工程:风控算法的地基
如果说架构是风控的骨架,那特征就是风控的血肉。我见过不少团队在模型选型上花了很多心思,却对特征工程草草了事,最后模型效果平平,还找不出原因。特征工程决定了模型效果的上限,算法只是在逼近这个上限。风控特征是一个极其庞杂的体系,如果不做好分类设计,很容易陷入“特征爆炸”的困境。
2.1 特征怎么分类才不乱
做特征一年后你会发现,最头疼的不是没有特征,而是特征多到不知道怎么管理。我建议按以下维度把特征分层分类,每个维度都有清晰的责任归属。
按照数据实体分,特征可以分为四类:用户特征、设备特征、行为特征、关系特征。用户特征包括注册时长、历史交易金额、绑定手机时长等,描述“这个人是谁”;设备特征包括设备型号、是否越狱、是否是模拟器、设备关联账号数等,描述“他用什么设备”;行为特征包括点按频率、操作时长、交易间隔、凌晨操作次数等,描述“他怎么做这件事”;关系特征则包括一度联系人数量、二度关联密度、是否处于异常社群等,描述“他身边都是谁”。四类特征不是孤立的,通常在最终特征拼接时会把它们合并到一张大宽表里。
按照计算时效分,特征又可以分为实时特征、准实时特征和离线特征。实时特征毫秒级算出,比如“当前设备IP是否为代理”;准实时特征分钟级更新,比如“用户最近5分钟登录失败次数”;离线特征按天更新,比如“用户过去30天平均下单金额”。三类特征的存储位置和计算方式完全不同——实时特征主要在Redis和Flink中,准实时特征通常用近线计算任务,离线特征则依赖数仓。
分类设计最大的好处是方便排障。线上如果出现“模型分数异常升高”,我们可以按特征分类快速定位是设备特征异常、行为特征缺失还是关系特征算错了,不用一头扎进几千列特征里大海捞针。
2.2 实时特征计算的延迟与一致性
实时特征计算是风控里工程难度最高的部分之一。延迟要求苛刻不说,还要求计算逻辑与离线保持严格一致。
举个例子,我们要计算“用户过去10分钟在该设备上的支付失败次数”。实时计算时,设备支付失败事件会作为数据流进入Flink,Flink开启一个10分钟的滚动窗口,统计窗口内的计数。但是这里有个细节——事件时间和处理时间。如果我们用处理时间计算,那么当数据流延迟到达时,窗口统计会不准确。我们会为每类事件打上事件时间戳,在Flink内部使用事件时间语义,同时配置允许迟到的数据落进侧输出流,再由下游定时合并。这样能最大程度保证“10分钟内”是用户真正经历的10分钟,而不是服务端处理流程的10分钟。
还有更麻烦的一致性问题是跨系统字段对齐。同一个“设备指纹”字段,前端采集时可能叫device_id,服务端风控日志里叫dev_id,数仓表里叫device_uuid。三个名字,如果映射关系没理清,训练数据里出现的字段和线上模型推理时的字段就对不上。解决这个问题没有捷径,只能建立元数据管理规范,规定每个字段只能有一个标准名称和一个权威来源,所有系统必须走API获取字段定义。
我的经验是:每个月选一天,把线上抽样请求的特征值打出来,和离线重算的特征值做一次全字段对比。偏差超过阈值的字段立刻排查。这个小习惯能拦住90%的特征对齐问题,省下来的排障时间非常可观。
2.3 特征稳定性和有效性监控
特征不是建好就一劳永逸的。外部环境在变,用户行为在变,黑产手法也在变,特征的分布会漂移,有效性会衰减。如果你不监测,等到模型效果崩了才发现特征早就失效了,那就被动了。
针对每个特征,我们都会建立一个稳定性监控看板,核心指标包括:覆盖率(非空值比例)、均值漂移幅度、分位数变化、与目标变量的相关性系数变化。特征是单维的,模型是多维的,但特征本身也必须有自己的监控。
我建议重点监控以下几类特征:一是设备相关特征,黑产会频繁更换设备伪装手段,比如模拟器特征、设备指纹唯一性,一旦覆盖率出现异常变化,要警惕黑产换了新工具;二是行为频次特征,大促前后用户行为分布会剧烈波动,这种波动是正常的,但模型需要重新适配;三是关系网络特征,社群结构一旦发生变化,很多基于密度的异常检测特征都会失效。
特征生命周期管理上,我们给每个特征设定了“过期观察期”。如果连续14天重要性排名在末尾且PSI高于阈值,就会进入下线评审流程。新特征上线则必须经过样本外验证,确保它不是只在训练集上有效。
3. 规则、模型和图算法的选型组合
到了算法层面,很多人会陷入一个误区:觉得规则引擎是传统风控的老古董,机器学习模型才是未来的方向。我做了多年风控后反而觉得,规则和模型从来不是替代关系,而是配合关系。规则解决“确定性风险”,模型解决“概率性风险”,两者结合使用,才是性价比最高的方案。
3.1 规则引擎依然不可替代
规则的最大优势是可解释性。当风控拒绝了一笔交易,我们需要向用户解释原因,客服需要知道为什么触发拦截;当监管检查和内部审计时,我们需要清清楚楚说明每一笔决策的依据。模型能给你一个分数,但很难告诉你“到底是因为哪几条证据”。规则可以。
规则引擎的第二优势是即时性。数据出现新型欺诈苗头时,模型需要样本积累、训练、验证、上线,周期太长。而规则可以当天发现、当天上线。比如我们发现某个新上线的活动被一批固定IP地址疯狂刷量,直接加一条规则“该IP段参与活动必须通过短信验证”,立刻就能止血。
但规则引擎也最需要管理。我见过最离谱的情况是,团队里一位同事离职后留下了2000多条无人维护的规则,很多规则互相矛盾,决策逻辑根本无法梳理。后来我们引入规则管理系统,每条规则必须有负责人、生效时间、失效时间、关联业务场景,每次命中都要记录;规则之间设置优先级,避免冲突。规则不是写得越多越好,而是越精准越好。
3.2 主流机器学习模型怎么选
风控场景中,主流的模型无非几类,各有各的适用边界,我按实际使用频率排序讲讲。
**评分卡模型(逻辑回归)**是风控最经典的模型。它本质是逻辑回归基础上做了特征分箱和评分转换,输出一个分数而非概率。评分卡最大的优点是极强的可解释性和稳定性。每一个分数区间对应一个明确的风险等级,配合规则使用非常顺手。我们在信贷风控和账户风险评估中大量使用评分卡。缺点是学习能力有限,很难捕捉特征间的高阶非线性关系。
**梯度提升树(XGBoost、LightGBM)**是当前风控建模的主力。它对非线性关系的拟合能力很强,能自动处理缺失值,训练效率也高。我们在反欺诈模型中大量使用XGBoost。但它的可解释性比评分卡弱,一般我们用它输出风险分,再配合SHAP值做特征归因。要注意的是,树模型在特征分布变化剧烈时,效果衰减会比线性模型更快,因此要格外关注特征稳定性监控。
隔离森林等无监督模型也有独特价值。风控里最难的是未知风险——黑产手法日新月异,没有标签数据让你去训练一个有监督模型。隔离森林基于“异常点容易被孤立”的思路做无监督异常检测,我们用它做额度欺诈团伙挖掘和新增设备异常行为发现。缺点是误报率偏高,通常我们只把它当成一种“可疑发现器”,输出结果转人工审核。
**图算法(知识图谱、社区发现)**在链路欺诈、团伙欺诈识别上能力非常突出。黑产从来不是单兵作战,他们会用一批账号互相转账、共享设备、批量操作。普通特征模型很难发现这种群体性风险,但图算法可以。构建用户-设备-IP-银行卡的多层次关系图谱,用社区发现算法找密集子图,就能锁定一个疑似团伙。
3.3 关系网络:被低估的风控利器
我特意把关系网络拿出来单独讲,因为这是很多团队忽略却极其有效的风控手段。
很多欺诈行为单独看每一条交易都是“正常”的:一个账号转给另一个账号,金额不大,频率不高,行为正常。但如果把数据拉到关系网络视角,你会发现这个看似正常的账号,和另外9个账号共享同一台设备,而那9个账号又共同给同一批新注册的手机号转过钱。这种关系密度在正常用户中几乎不可能出现。
我们实际项目里,用关系网络成功识别过一整个刷单团伙。当时某活动平台上出现一批高频领取优惠券后立即下单的用户,单看每个用户的特征都没有明显异常。后来我们构建了一张“注册手机号-设备ID-收货地址-支付账号”的关系图谱,发现这批用户的设备ID高度重合,形成了一个明显的聚簇结构。用标签传播算法打了团伙标记后,再回查历史订单,发现近一个月的损失几乎都和这个聚簇有关。
搭建关系网络没有想象中那么重。Gephi、igraph、NetworkX都能做图分析,真正复杂的是图谱的更新时效。离线图适合做团伙挖掘和回溯分析,每天凌晨更新一次就够用了;如果要做在线实时图查询(比如判断当前交易的关联用户是否处于某个风险社群),就要引入图数据库,同时配合缓存和索引优化。我们目前采用的方案是:Neo4j存储全量图谱用于离线分析,图特征(如K-core值、PageRank值、社区ID)通过离线任务计算后同步到Redis,在线决策时直接读取这些预计算特征。这比在线实时遍历图谱要快得多,完全能满足线上毫秒级决策的需求。
3.4 策略编排与分数融合
有了规则、模型、图算法之后,你会面临一个新的问题:这些乱七八糟的决策信号,怎么编排成一套有序的决策流程?
我的建议是:分层决策,逐级过滤。第一层用快速规则做粗过滤,把高确定性风险直接拦截掉;第二层用评分卡做风险分层,低分直接放行,中分段进入更复杂的模型做二次判断;第三层用图算法、复杂模型处理中高分段;最后无法自动决策的才转人工审核。
具体到分数融合上,我们常用两种方法。一种是分数卡分段组合:比如XGBoost输出风险概率0-1,评分卡输出300-900分,我们设定规则,当XGBoost风险概率大于0.7且评分卡分数低于500时,直接拒绝;当概率在0.4到0.7之间但评分卡高于600时,追加验证码;其他情况放行。另一种是加权融合:给不同模型分配不同权重,人工设定或者用Stacking方式学习最优权重。加权融合的风险在于权重不易解释,我们一般只用于内部风控决策,不用于对外解释。
编排还有一个重要原则:策略之间要留“逃生通道”。每一层策略的拦截结果都要有一个可以发起的申诉和复核机制。黑产会被策略误伤,但正常用户也会。一套完全没有容错机制的风控策略,长远来看一定会让用户体验受损。
4. 模型从开发到上线的完整链路
很多算法工程师会把大部分精力花在训练模型上,但我得说句实话:在真实风控项目里,模型训练只占20%的工作量,剩下80%的工作是数据准备、特征验证、上线部署、监控运维。这80%才是最考验功底的地方。
4.1 样本选择与标签确定
模型的本质是从历史数据中学习规律,如果历史数据的标签本身就有问题,那模型再强也白搭。
以反欺诈模型为例。我们要定义什么是“坏样本”。最直观的定义是“被确认欺诈的交易”,但这有一个问题——确认欺诈是有滞后性的。一笔交易可能过了一周才被用户投诉举报,如果我们用当天的样本做标签,那么后几天的交易都还没来得及暴露风险,就会被误判为“好样本”。这种“未到期样本”会严重污染训练数据。
实际中我们一般这么设计:设定一个观察期和一个表现期。观察期是特征窗口,比如取过去30天的用户行为特征;表现期是结果窗口,比如给这笔交易留出60天的“观察时间”,60天内被确认为欺诈的标记为坏样本,否则标记为好样本。这样做虽然会损失一部分近期数据的时效性,但能避免标签错配。每类模型都要提前设计好这一套时间逻辑。
还有样本权重的问题。风控场景里好样本和坏样本比例通常严重失衡,坏样本可能只占万分之几。如果不做处理,模型会倾向于把所有人都预测为“好”。我们通常会采用下采样(保留全部坏样本,随机抽取部分好样本)结合样本权重调整的方式,同时在使用AUC等指标评估时,要根据调整前的真实分布重新加权计算。
4.2 训练集、验证集与时间序列问题
风控领域建模型时最常见的一个错误,就是随机划分训练集和测试集。
为什么不能随机划分?因为时间序列数据有很强的先后依赖关系。黑产手法会随季节、活动节奏、风控策略的变化而变化。你在8月训练的模型,跑去预测3月的交易,这本身就是逻辑错误;同样,随机划分会让训练集和测试集互相“泄漏”时间信息,模型在测试集上的表现虚高。
正确做法是按时间顺序划分:前70%的时间段作为训练集,后30%作为验证集/测试集。如果数据跨度长,最好再用最近一段“未见时间窗口”做最后的压测,观察模型上线后会不会因时间漂移而失效。
我们项目中有一次深刻教训:当时在随机划分下AUC达到0.92,表现非常好。上线后发现实际效果远低于预期。排查后才发现,训练集里包含了过去几个月的大量样本,测试集是从同一时期随机抽的,时间上重叠,导致模型“记住了”当时的一些数据规律。改成时间序列划分后,AUC降到了0.83,这个数字才更接近线上真实表现。
4.3 上线前的回测、影子测试与灰度发布
模型做好后,不要直接一把梭上线。风控模型影响面太大,一旦误杀面扩大,投诉会直接淹没客服团队。
第一步是历史回测。把模型应用到过去N天的历史样本上,计算如果当时用的是这个新模型,决策结果会怎样。这一步主要关注两个指标:一是在保证原有召回率不变的前提下,误杀率是否上升;二是对坏样本的捕获率是否提升。回测结果会做成详细报表,所有相关决策者确认后才进入下一步。
第二步是影子发布(Shadow Mode)。新模型部署到线上环境,但它只记录决策,不真正影响线上交易处理。影子模式期间,我们每天对比老策略和新模型的输出差异,重点观察“被新模型拒绝但被老策略放行”的样本中,有多少真实风险、有多少被误伤的。这个验证周期一般持续一周到两周。
第三步是灰度发布。先让新模型只处理5%的流量,观察效果稳定后逐步扩大到10%、30%、50%、100%。灰度期间一旦触达告警阈值(比如人工审核通过率出现异常波动),立即回滚到上一版本。灰度发布依赖前面说的流量接入层能灵活做流量分配,所以架构上的能力是预先准备。
5. 风控项目里我踩过的那些坑
每一个做风控超过一年的人,肚子里都攒着一堆血泪教训。有些坑是文档里不会写的,只有亲身踩过才知道有多疼。我把这几年遇到的典型问题整理了一下,希望能帮后来者少走弯路。
5.1 线上线下特征不一致的“灵异事件”
第一次遇到这个问题时,我们排查了整整一周,最后差点以为是模型“见鬼了”。现象是:模型在离线测试集上AUC达到0.90,上线后各项实时监控指标却一直不达标,风控分数分布与离线差异巨大。
排查到最后发现,原因竟然是一个特征的取值区间不同。离线训练时,“用户近7天登录次数”这个特征,数据是从数仓清洗后拿到的,缺失值被填充为0;而线上实时计算时,这个特征如果用户近7天没有登录记录,从Redis里查不到,逻辑走了另一个分支,填充的是-1。这一字之差,模型在线上看到的所有缺失值样本,特征分布完全变了。
这以后我们立了一条铁律:每一个特征都必须有明确的“缺失值处理策略”,线上和线下使用完全相同的处理规则,并且用自动化测试保证线上特征计算代码和离线特征清洗代码走的是同一套逻辑标准。具体落地方式是把所有特征定义写成配置文件,离线和在线共用这份配置,从源头上杜绝差异。
5.2 冷启动和长尾攻击
冷启动是风控永远的痛点。新用户没有任何历史数据,新设备没有任何指纹记录,新绑定的银行卡没有交易流水。面对这种“三无”身份,规则和模型都很难做出准确判断。
我的经验是,冷启动场景不能指望一个“全能模型”解决所有问题,而是要为冷启动单独设计策略。常用的手段:对无历史数据的新用户,提高首次交易的验证门槛;利用设备指纹和IP的关联信息作为替代信号;对小型新设备群体做聚合分析,识别他们之间是否存在异常的相似性。
长尾攻击是另一个让人头疼的问题。黑产也在做“数据分析”,他们知道风控规则和模型的阈值,会刻意设计绕过策略的流量。比如模型判断风险概率超过0.7拒付,他们就专门做那些分数卡在0.5~0.65之间的操作。对付长尾攻击,没有一劳永逸的办法,只能靠监控异常或不断迭代。当发现决策边界附近的样本量异常增多时,就要警惕是否有人在对你的模型做对抗性探测。这时可以考虑引入随机化因子,让决策边界变得不那么容易被摸清。
5.3 模型效果衰减与人工介入
再好的模型,上线三个月后效果也会肉眼可见地下降,因为用户行为在变,黑产手法也在变。这不是模型写错了,而是现实世界的数据分布已经发生了漂移。
我们建立了模型生命周期管理机制:模型上线后每日监控特征分布、分数分布、误杀率、召回率。一旦模型的关键指标连续多日偏离基线,就触发重训流程。重训的质量取决于数据沉淀,所以最开始搭建架构时的“决策全程留痕”能力就体现出来了——只有你每一次决策都被完整记录,重训时才有足够覆盖各种风险场景的数据。
人工审核环节一定不要取消。模型再聪明,也会有判断不了的情况。给审核团队提供足够丰富的上下文:用户历史行为轨迹、关联设备信息、关系网络提示、风险项解释。一个好的风控系统,不是用模型取代人,而是用模型把人的精力聚焦在最核心的可疑样本上。
还有一个容易忽视的地方:人工审核的结论要反哺模型。每一次人工确认的风险样本,都应该进入训练数据,成为下一次迭代的养料。没有这个反馈闭环,你的模型就一直在吃老本,效果自然会慢慢变成“僵尸模型”。
做风控做得越久,我越觉得这个领域真正的门槛不是算法本身,而是把工程、数据和业务串起来的系统能力。算法工程师再强,光会调参也没用;架构师再强,不懂业务风险场景也白搭。从架构到算法,再到数据和运营,每一层都咬合紧密。如果你正准备从零搭建一套风控体系,我建议你先别急着追求复杂的模型和花哨的算法,从架构的稳定性、特征的一致性、规则的可维护性做起,这些东西做好了,哪怕只用一个评分卡也能撑起一大片天。反之,根基不稳,模型就算训出花来,上线也是被现实毒打一顿。