2. 规则基础概念

在进入规则优先级、互斥与依赖检测之前,必须先建立一套统一的术语坐标系。很多团队在讨论“规则冲突”时各说各话,根源往往不是算法问题,而是对规则、条件、动作、事实、工作内存这些基础概念的理解不一致。本节将把这些概念逐一拆解,并说明它们在规则引擎中的位置与关系。

一、核心原理:规则引擎的最小认知模型

一条规则最朴素的形式可以概括为:当满足某些条件时,执行某些动作。用工程语言表达,就是“条件—动作”对。规则引擎的作用,是把这些“条件—动作”对从业务代码中抽离出来,交给一个独立的推理组件去匹配和执行。

围绕这个核心,规则引擎通常包含以下基本组成:

  • 规则(Rule):一条独立的业务判断单元,由条件部分和动作部分组成,通常还带有名称、优先级、生效范围等元数据。
  • 条件(Condition / LHS):规则被触发所需满足的断言集合,也叫左部(Left-Hand Side)。条件通常写成模式匹配表达式,例如“客户等级为金卡且订单金额大于1000”。
  • 动作(Action / RHS):条件满足后执行的逻辑,也叫右部(Right-Hand Side)。动作可以修改事实、输出结论、调用外部服务或产生新事实。
  • 事实(Fact):被规则系统处理的数据对象。一个事实可以是订单、用户、设备状态、风控事件等。事实是规则匹配的输入,也是动作可能修改的对象。
  • 工作内存(Working Memory):规则引擎运行时存放所有事实的容器。引擎通过工作内存中的事实与规则条件进行匹配,匹配成功后触发动作,动作又可能改变工作内存,形成推理循环。
  • 规则引擎(Rule Engine):负责加载规则、维护工作内存、执行模式匹配、调度规则执行顺序的核心组件。它通常还包含规则库、推理机、议程(Agenda)等子模块。

这些概念之间的关系可以用一句话概括:规则引擎读取规则库,将事实放入工作内存,通过条件匹配形成议程,再按调度策略执行动作,动作可能产生新事实或修改旧事实,从而驱动下一轮匹配。

二、方法流程:一条规则从定义到执行的完整链路

理解概念之后,需要把它们串成一条可运行的链路。下面以典型的规则引擎执行流程为例:

  1. 规则定义:业务人员或开发人员用规则语言或配置描述规则,包括条件、动作、优先级、互斥组等。
  2. 规则加载:引擎启动或热更新时,将规则解析为内部可执行结构,放入规则库。
  3. 事实插入:外部系统将待处理数据作为事实插入工作内存,例如一笔订单、一个用户画像。
  4. 模式匹配:引擎将工作内存中的事实与所有规则的条件进行匹配,找出当前可触发的规则集合。
  5. 议程生成:匹配成功的规则进入议程,议程是一个待执行规则的集合,可能包含多条规则。
  6. 冲突消解:当议程中有多条规则同时满足时,引擎根据优先级、互斥关系、依赖关系等策略决定执行顺序或选择执行哪一条。
  7. 动作执行:按消解结果执行规则动作,动作可能修改事实、插入新事实或删除事实。
  8. 循环推理:如果动作改变了工作内存,引擎会重新匹配,直到没有新规则可触发或达到终止条件。

关键点:规则引擎不是“一次性匹配”,而是“匹配—执行—再匹配”的循环。工作内存的变化会驱动新一轮推理,这也是规则依赖和优先级问题产生的根源。

三、案例/场景:用一段伪代码看清术语的落地形态

下面用一段简化的规则定义片段,展示条件、动作、事实和工作内存在实际代码中的对应关系。这里不依赖具体引擎语法,重点看结构。

rule "金卡客户大额订单折扣"
  priority: 10
  when
    $order: Order(amount > 1000)
    $user: User(level == "GOLD", id == $order.userId)
  then
    $order.discount = 0.9;
    update($order);
    insert(new Notification($user.id, "已享受金卡折扣"));
end

在这段规则中:

  • 事实:Order 和 User 是事实类型,具体的一笔订单和一个用户是事实实例。
  • 条件:amount > 1000、level == "GOLD"、id == $order.userId 共同构成左部条件。
  • 动作:设置折扣、更新订单、插入通知,构成右部动作。
  • 工作内存:$order、$user 以及新插入的 Notification 都存在于工作内存中。
  • 优先级:priority: 10 是规则元数据,用于冲突消解。

当引擎执行时,它会先在工作内存中查找满足条件的 Order 和 User 组合。如果找到,规则进入议程;如果同时有其他规则也匹配,就需要根据优先级和互斥策略决定先执行谁。动作执行后,Notification 被插入工作内存,可能触发另一条“发送通知”的规则,形成链式推理。

四、常见术语对照与误区复盘

为了便于后续章节讨论优先级、互斥和依赖,这里用一张表把常见术语及其易混淆点集中列出。

术语 含义 常见误区
规则 条件与动作的封装单元 把规则等同于 if-else 分支,忽略其元数据和调度属性
条件(LHS) 规则触发的断言集合 认为条件只是简单布尔表达式,忽略模式匹配和变量绑定
动作(RHS) 条件满足后执行的逻辑 在动作中写复杂业务逻辑,导致规则难以维护和测试
事实 被规则处理的数据对象 把事实当成静态数据,忽略动作可以修改或插入事实
工作内存 运行时存放事实的容器 认为工作内存只是数据库缓存,忽略其驱动推理循环的作用
议程 当前可触发规则的集合 认为议程顺序就是规则定义顺序,忽略冲突消解策略
冲突消解 决定多条可触发规则执行顺序的机制 只关注优先级,忽略互斥和依赖对执行结果的影响

最常见的误区是:把“规则匹配成功”等同于“规则一定会执行”。实际上,匹配成功只意味着规则进入议程;是否执行、何时执行、执行哪一条,取决于冲突消解策略。优先级、互斥和依赖检测,正是围绕议程调度展开的。

学习建议:在后续章节中遇到“规则冲突”时,先回到本节的概念模型,确认是条件匹配问题、动作副作用问题,还是议程调度问题。大多数所谓“规则不生效”,本质是事实没有正确插入工作内存,或者动作修改事实后没有触发重新匹配。

掌握这些基础概念后,就可以进一步讨论:当多条规则同时满足时,优先级如何定义;当规则之间不能同时执行时,互斥如何表达;当一条规则的执行依赖另一条规则的结果时,依赖关系如何检测。这些问题的答案,都建立在“规则—条件—动作—事实—工作内存—议程”这条完整链路上。