4. 规则引擎架构设计:整体架构图、规则编译层、规则执行层、规则存储层、规则缓存层
规则引擎是风控系统的核心决策组件,其架构设计直接决定了规则的可维护性、执行性能与扩展能力。本章从分层架构视角出发,拆解规则引擎的四个关键层次:编译层、执行层、存储层与缓存层,并给出整体架构图与各层内部设计要点。
4.1 整体架构图
规则引擎采用经典的分层架构,上层依赖下层接口,下层对上层屏蔽实现细节。整体分为四层:
- 编译层:将文本规则(DSL/JSON/XML)编译为可执行的规则对象(AST、表达式树、字节码)。
- 执行层:接收请求上下文,按优先级/命中策略执行规则,输出决策结果。
- 存储层:持久化规则定义、版本、元数据,支持热加载与灰度发布。
- 缓存层:缓存编译后的规则对象、频繁访问的规则元数据,降低存储层压力。
架构原则:各层之间通过接口隔离,编译层输出不可变规则对象,执行层不感知存储细节,缓存层可独立扩缩容。这种分层在风控场景中支持单机每秒数千次规则评估,且规则变更无需重启服务。
4.2 规则编译层
编译层是规则引擎的“翻译官”,负责将运维人员编写的规则文本转化为执行引擎可理解的内存对象。编译过程通常包含以下阶段:
| 阶段 | 输入 | 输出 | 关键职责 |
|---|---|---|---|
| 词法分析 | 规则文本(DSL/JSON) | Token 序列 | 识别关键字、操作符、变量名、字面量 |
| 语法分析 | Token 序列 | 抽象语法树(AST) | 构建树形结构,验证语法正确性 |
| 语义校验 | AST | 校验后的 AST | 类型检查、变量存在性、函数签名匹配 |
| 表达式编译 | 校验后 AST | 可执行表达式(如 SpEL、MVEL、自研) | 将条件/动作表达式编译为字节码或解释器对象 |
| 规则对象组装 | 表达式 + 元数据 | Rule 对象(含优先级、标签、命中策略) | 封装为执行层可直接调用的不可变对象 |
编译层设计要点:
- 支持增量编译:仅重新编译变更的规则,避免全量编译带来的性能抖动。
- 编译结果缓存:编译后的 Rule 对象放入缓存层,下次直接命中。
- 编译异常隔离:单条规则编译失败不影响其他规则,返回具体错误行号与原因。
4.3 规则执行层
执行层是规则引擎的“决策大脑”,接收实时风控请求,按既定策略执行规则并返回决策结果。执行流程可概括为以下步骤:
- 上下文注入:将请求参数、设备指纹、用户画像等数据封装为 EvaluationContext。
- 规则筛选:根据请求中的场景标签(如“登录”、“支付”)过滤出待执行规则集。
- 优先级排序:按规则配置的优先级(数字越小越优先)排序,支持同优先级随机/轮询。
- 规则匹配:依次评估每条规则的条件表达式,条件为 true 则执行动作。
- 命中策略:支持“命中即终止”、“全量评估”、“加权投票”等策略。
- 结果聚合:将命中规则的决策动作(拒绝/人工/通过/加验)合并为最终决策。
性能红线:执行层必须设置超时熔断机制。单条规则执行时间超过阈值(如 50ms)时,自动跳过并记录告警,防止慢规则拖垮整个引擎。
4.4 规则存储层
存储层负责规则数据的持久化与版本管理,是规则引擎的“记忆库”。生产环境通常采用关系数据库 + 对象存储的组合方案。
| 存储对象 | 推荐存储方案 | 核心字段 |
|---|---|---|
| 规则定义 | MySQL / PostgreSQL | rule_id, rule_name, scene_tag, priority, condition_dsl, action_dsl, status, version |
| 规则版本 | MySQL + 版本表 | version_id, rule_id, content_snapshot, created_at, operator, change_log |
| 灰度标签 | MySQL + 标签表 | rule_id, gray_tag, traffic_percent, start_time, end_time |
| 规则依赖数据 | Redis / 对象存储 | 词库、黑名单、频率配置等外部数据引用 |
存储层设计要点:
- 规则变更必须记录完整变更历史,支持一键回滚到任意历史版本。
- 灰度发布通过标签表控制流量百分比,新规则先在小流量验证,无异常再全量。
- 存储层与编译层之间通过消息队列(如 Kafka)异步同步变更事件,触发增量编译。
4.5 规则缓存层
缓存层是规则引擎的“加速器”,解决存储层 I/O 瓶颈与编译层 CPU 开销。风控场景下,规则变更频率远低于请求频率,缓存命中率通常超过 99%。
缓存策略采用两级缓存架构:
- 一级缓存(本地堆内缓存):使用 Caffeine / Guava Cache,存储最热门的规则对象,TTL 60 秒,容量限制 10000 条。
- 二级缓存(分布式缓存):使用 Redis Cluster,存储全量编译后规则对象,TTL 300 秒,支持跨进程共享。
| 缓存层级 | 存储内容 | 淘汰策略 | 访问延迟 |
|---|---|---|---|
| 一级(本地) | 编译后的 Rule 对象、表达式树 | LRU + 过期时间 | < 1ms |
| 二级(Redis) | 序列化的 Rule 对象、元数据 | TTL + 主动失效 | 1-5ms |
缓存一致性:规则变更时,通过消息广播通知所有引擎节点失效本地缓存,同时删除 Redis 中的对应 key。采用“先更新数据库,再删除缓存”的模式,避免并发脏读。
4.6 各层交互时序
一次完整的规则评估请求,各层交互时序如下:
1. 客户端发起风控请求(含场景标签、上下文数据)
2. 执行层接收请求,组装 EvaluationContext
3. 执行层查询缓存层,获取该场景下的规则列表
├─ 缓存命中 → 直接返回编译后规则对象
└─ 缓存未命中 → 查询存储层获取规则定义
→ 编译层执行编译
→ 结果写入缓存层
4. 执行层按优先级逐条评估规则
5. 命中策略判断,聚合最终决策
6. 返回决策结果给客户端
避坑指南:缓存层不要缓存规则的全部历史版本,只缓存当前生效版本。历史版本回滚时,通过存储层重新加载并刷新缓存,避免缓存与数据库版本不一致。