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网络。

规则引擎核心架构(Rete算法模式) 交易事实输入 Alpha网络(单条件匹配) 金额>10000 | 交易时间=夜间 | 交易对手黑名单 Beta网络(条件组合与连接) 金额>10000 AND 夜间交易 | 黑名单 AND 大额转账 冲突集(匹配成功的规则实例) 规则执行引擎(冲突解决) Alpha节点1: 金额条件 Alpha节点2: 时间条件 Alpha节点3: 黑名单条件 Beta节点: 组合条件 Beta节点: 跨事实连接

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