4. 规则引擎设计:规则引擎架构模式、规则定义语言与冲突解决
规则引擎,说白了就是交易合规系统的“大脑”。
我做了这么多年金融系统,最深的体会就是:业务规则永远在变。今天监管出一个新政策,明天业务部门要加一个风控条件。如果每次都要改代码,那运维团队得疯掉。规则引擎就是为了解决这个痛点——把业务逻辑从代码里抽出来,变成可配置、可热加载的规则。
4.1 规则引擎的核心架构模式
先聊聊架构。规则引擎不是只有一种玩法,我见过三种主流模式。
4.1.1 顺序匹配模式
最简单粗暴的方式。规则排好队,一条一条匹配。匹配上了就执行,执行完继续下一条。
优点是什么?实现简单,调试方便。缺点也很明显——性能差。规则多了以后,每条都要全量扫描,效率直线下降。
我在早期的一个小项目里用过这种模式。当时只有几十条规则,跑起来还行。后来业务扩张到上千条规则,系统直接卡成PPT。嗯,从那以后我再也不敢小看规则引擎的性能问题了。
4.1.2 Rete算法模式
这才是工业级规则引擎的标配。Rete算法,拉丁语里是“网络”的意思。
它的核心思想是什么?避免重复计算。
你想想看,传统模式里,每条规则都要重新匹配所有条件。但Rete算法会构建一个条件网络,把规则拆成最小的条件单元。当新的事实(比如一笔交易)进来时,它只在网络里传播变化的部分,而不是全量重算。
Rete算法的三个关键组件:
- Alpha网络:处理单个条件的匹配,比如“金额 > 10000”
- Beta网络:处理条件之间的组合,比如“金额 > 10000 AND 交易时间在夜间”
- 冲突集:存储所有匹配成功的规则实例,等待执行
我建议你在设计合规系统时,优先考虑Rete算法。Drools、Jess这些主流规则引擎,底层都是它。虽然实现复杂,但性能提升是数量级的。
4.1.3 基于决策表的模式
这种模式适合规则结构非常规整的场景。比如“如果A且B,则C”。
决策表本质上是一个二维矩阵,行是规则,列是条件。每个单元格标记匹配结果。这种模式的好处是可视化强,业务人员也能看懂。但灵活性差,不适合复杂逻辑。
我个人习惯把决策表作为Rete算法的补充。简单规则用决策表,复杂规则走Rete网络。
4.2 规则定义语言
规则写在哪?怎么读?这就涉及到规则定义语言了。我主要用两种:DRL和JSON规则。
4.2.1 DRL(Drools Rule Language)
DRL是Drools规则引擎的原生语言。语法有点像Java,但更简洁。
// DRL规则示例:大额夜间交易告警
rule "HighAmountNightTransaction"
salience 100
when
$txn: Transaction(amount > 100000)
$time: CurrentTime(hour >= 22 || hour <= 6)
then
System.out.println("告警:大额夜间交易,金额=" + $txn.getAmount());
$txn.setRiskLevel("HIGH");
update($txn);
end
注意那个salience字段。它代表规则的优先级,数值越大优先级越高。我习惯把核心风控规则设成高优先级,普通规则放低优先级。
我的经验:DRL虽然强大,但业务人员学起来有门槛。我建议让开发人员维护DRL规则,业务人员用更友好的方式(比如JSON或决策表)来定义规则,然后由系统自动转换成DRL。
4.2.2 JSON规则
JSON规则的好处是跨平台、易解析。适合微服务架构下的规则分发。
{
"ruleId": "R001",
"name": "大额夜间交易告警",
"priority": 100,
"conditions": {
"all": [
{"field": "amount", "operator": "gt", "value": 100000},
{"field": "hour", "operator": "gte", "value": 22},
{"field": "hour", "operator": "lte", "value": 6}
]
},
"actions": [
{"type": "setRiskLevel", "value": "HIGH"},
{"type": "sendAlert", "channel": "email"}
]
}
JSON规则的可读性比DRL差一些,但胜在灵活。我曾在项目中用JSON规则配合规则引擎的REST API,实现了规则的热加载——改完JSON,系统不用重启,规则立刻生效。
4.3 规则优先级与冲突解决
规则多了,冲突是必然的。比如一条规则说“金额大于10万就告警”,另一条说“白名单用户不告警”。两条都匹配上了,听谁的?
4.3.1 优先级机制
最直接的解决方案就是给规则排优先级。
| 优先级值 | 含义 | 典型场景 |
|---|---|---|
| 100-999 | 最高优先级 | 监管强制规则、反洗钱规则 |
| 50-99 | 高优先级 | 风控核心规则、大额交易规则 |
| 10-49 | 中优先级 | 业务规则、限额规则 |
| 1-9 | 低优先级 | 通知规则、日志规则 |
我建议把优先级设计成可配置的。别写死在代码里。因为业务部门经常调整规则的优先级,今天这个规则重要,明天那个规则紧急。可配置的优先级能省去很多麻烦。
4.3.2 冲突解决策略
光有优先级还不够。当两条规则优先级相同时,怎么选?
常用的策略有几种:
- 最新优先:后加载的规则覆盖先加载的。适合规则频繁更新的场景。
- 最具体优先:条件更具体的规则优先执行。比如“金额>10万且交易对手在黑名单”比单纯的“金额>10万”更具体。
- 指定策略:人工指定冲突时的处理方式。比如“两条规则都执行,但按顺序”。
避坑指南:我曾经在一个项目中,没有设计冲突解决策略。结果两条优先级相同的规则同时匹配,系统随机选了一条执行。线上出了好几次误报。后来我加上了“最新优先”策略,并强制要求每条规则必须指定优先级。从那以后,冲突问题再没出现过。
4.3.3 规则链与规则流
当规则数量超过几百条时,光靠优先级已经不够了。这时候需要引入规则链或规则流的概念。
规则链就是把规则按业务逻辑分组。比如“反洗钱规则链”、“限额规则链”、“通知规则链”。每个链内部有自己的优先级和冲突解决策略。链与链之间可以串行或并行执行。
我习惯用规则流来编排复杂的合规流程。比如:先执行反洗钱规则链,如果触发了告警,再执行人工审核规则链;如果没触发,直接进入限额规则链。这种编排方式,业务人员用拖拽的方式就能完成,非常直观。
4.4 规则引擎的性能优化
最后聊点实战经验。规则引擎用不好,性能会很难看。
第一,控制规则数量。别把规则引擎当成万能药。超过5000条规则,Rete算法也会吃力。我建议把规则按业务域拆分到不同的规则引擎实例中。
第二,合理使用缓存。规则引擎的编译结果可以缓存。特别是DRL规则,编译一次能省很多时间。我在项目中用Guava Cache缓存编译后的规则包,命中率能达到90%以上。
第三,异步执行。合规审查不一定要同步返回。对于非核心的规则(比如通知类规则),可以异步执行。这样主流程不会被阻塞。
嗯,规则引擎设计这块,水挺深的。但核心就三点:选对架构模式、定义好规则语言、处理好冲突。把这三点拿捏住,你的合规系统就稳了。
公众号:蓝海资料掘金营,微信deep3321