3. 规则引擎架构:从整体到细节
聊规则引擎,我习惯先画一张大图。你想想看,一个实时风控系统每天要处理几百万甚至上千万次请求,规则引擎就是它的“大脑”。这个大脑长什么样?核心模块有哪些?设计时要注意什么?今天咱们一次性说清楚。
3.1 总体架构:三层两通道
我参与过的几个风控项目,架构上大同小异。说白了,就是“三层两通道”的格局。
- 接入层:接收外部请求,做协议转换、参数校验。我见过不少团队在这一层栽跟头——请求量一上来,接入层先挂了。
- 引擎层:核心中的核心。规则库、推理引擎、工作内存都在这一层。后面我会详细拆解。
- 存储层:存放规则定义、历史数据、模型参数。注意,实时风控的存储和离线分析不一样,对读写延迟极其敏感。
两通道指的是:实时通道和异步通道。实时通道处理同步请求,毫秒级返回;异步通道处理批量计算、模型更新等非实时任务。嗯,这里要注意,千万别把异步任务塞进实时通道,否则延迟会爆炸。
核心原则:实时通道只做“轻计算”,所有重量级操作都扔给异步通道。我曾经见过一个项目,把规则编译放在实时通道里,结果每次上线都卡死——这就是典型的架构设计失误。
3.2 核心模块拆解
3.2.1 规则库:规则的“家”
规则库不只是存规则的地方。它要解决三个问题:怎么存、怎么查、怎么管。
- 存储结构:我习惯用树形结构组织规则。比如按业务线分一级节点,按风险类型分二级节点。这样查找效率高,也方便权限控制。
- 索引机制:规则多了以后,全量扫描就是灾难。必须建立索引——按规则ID、优先级、生效时间等字段建索引。我在项目中遇到过,规则数量超过5000条时,没有索引的查询延迟从2ms飙升到200ms。
- 版本管理:规则是会变的。今天上线一条规则,明天可能就要回滚。没有版本管理,你连“刚才那条规则是什么”都说不清楚。
避坑指南:我曾经把规则库直接放在关系型数据库里,结果每次规则变更都要重启引擎。后来改用内存数据库+定期同步的方式,才解决了热加载的问题。记住,规则库要支持热更新,不能停服。
3.2.2 推理引擎:真正的“大脑”
推理引擎负责执行规则。它拿到一条请求,从工作内存里取出事实数据,然后匹配规则、执行动作。这里面有几个关键点:
- 匹配算法:Rete算法是经典选择。它用网络结构缓存规则条件,避免重复计算。我刚开始做规则引擎时,自己手写过Rete算法——嗯,那真是痛并快乐着。
- 执行顺序:规则有优先级,也有依赖关系。推理引擎要保证高优先级规则先执行,同时处理好规则间的冲突。我建议用冲突集来管理——把所有可执行的规则放进一个集合,按优先级排序后依次执行。
- 终止条件:规则引擎不能无限循环。必须设置最大执行轮次或超时时间。我曾经遇到过,一条规则触发了另一条规则,结果形成了死循环——从那以后,我强制要求所有规则必须标注“是否允许递归触发”。
# 推理引擎核心逻辑(伪代码)
def execute_engine(facts, rules):
agenda = [] # 冲突集
for rule in rules:
if rule.matches(facts):
agenda.append(rule)
# 按优先级排序
agenda.sort(key=lambda r: r.priority, reverse=True)
for rule in agenda:
rule.execute(facts)
# 检查终止条件
if facts.get('max_rounds_reached'):
break
3.2.3 工作内存:事实的“暂存区”
工作内存存的是“当前请求相关的所有数据”。包括用户信息、设备指纹、历史行为、外部接口返回等。它有几个特点:
- 临时性:一次请求处理完,工作内存就清空。别把持久化数据放进来。
- 共享性:所有规则都能访问工作内存。但要注意并发安全——我见过一个bug,两条规则同时修改同一个事实,结果数据乱了。
- 高效性:工作内存的读写必须快。我建议用键值对结构,底层用哈希表实现。别用关系型数据库做工作内存,那太慢了。
警告:工作内存不是数据库!别把大量历史数据塞进去。我见过有人把用户过去三年的所有交易记录都加载到工作内存里——结果一次请求就占了几百兆内存,系统直接OOM。工作内存只放“当前决策需要的数据”,其他数据走外部存储。
3.3 架构设计原则
做了这么多年风控架构,我总结了几条铁律:
| 原则 | 说明 | 我的经验 |
|---|---|---|
| 高内聚低耦合 | 每个模块职责单一,模块间通过接口通信 | 我曾经把规则解析和规则执行写在一起,结果改一个bug引出三个新bug |
| 无状态设计 | 引擎实例不保存状态,方便水平扩展 | 状态都扔给工作内存和外部存储,引擎只管算 |
| 可观测性 | 每个环节都要有日志和指标 | 没有可观测性,线上出问题你只能靠猜 |
| 优雅降级 | 某个模块挂了,不能拖垮整个系统 | 规则库挂了,至少还能用缓存里的规则继续跑 |
3.4 一张图看懂规则引擎架构
下面这张SVG图,是我自己画的。它展示了规则引擎的核心模块和数据流向。你仔细看,会发现每个模块之间都有明确的边界和接口。
这张图里,你注意看箭头方向。实时请求从接入层进入引擎层,推理引擎从规则库加载规则,从工作内存读写事实,最后把结果返回接入层。异步通道负责把数据持久化到存储层。各司其职,互不干扰。
我的建议:刚开始设计架构时,别追求大而全。先把核心链路跑通——接入层接收请求、推理引擎执行规则、工作内存暂存事实、存储层持久化。其他功能(比如规则热加载、监控告警)可以后续迭代。我见过太多人一开始就想做“完美架构”,结果半年了还没上线。