2. 规则基础概念
在进入规则优先级、互斥与依赖检测之前,必须先建立一套统一的术语坐标系。很多团队在讨论“规则冲突”时各说各话,根源往往不是算法问题,而是对规则、条件、动作、事实、工作内存这些基础概念的理解不一致。本节将把这些概念逐一拆解,并说明它们在规则引擎中的位置与关系。
一、核心原理:规则引擎的最小认知模型
一条规则最朴素的形式可以概括为:当满足某些条件时,执行某些动作。用工程语言表达,就是“条件—动作”对。规则引擎的作用,是把这些“条件—动作”对从业务代码中抽离出来,交给一个独立的推理组件去匹配和执行。
围绕这个核心,规则引擎通常包含以下基本组成:
- 规则(Rule):一条独立的业务判断单元,由条件部分和动作部分组成,通常还带有名称、优先级、生效范围等元数据。
- 条件(Condition / LHS):规则被触发所需满足的断言集合,也叫左部(Left-Hand Side)。条件通常写成模式匹配表达式,例如“客户等级为金卡且订单金额大于1000”。
- 动作(Action / RHS):条件满足后执行的逻辑,也叫右部(Right-Hand Side)。动作可以修改事实、输出结论、调用外部服务或产生新事实。
- 事实(Fact):被规则系统处理的数据对象。一个事实可以是订单、用户、设备状态、风控事件等。事实是规则匹配的输入,也是动作可能修改的对象。
- 工作内存(Working Memory):规则引擎运行时存放所有事实的容器。引擎通过工作内存中的事实与规则条件进行匹配,匹配成功后触发动作,动作又可能改变工作内存,形成推理循环。
- 规则引擎(Rule Engine):负责加载规则、维护工作内存、执行模式匹配、调度规则执行顺序的核心组件。它通常还包含规则库、推理机、议程(Agenda)等子模块。
这些概念之间的关系可以用一句话概括:规则引擎读取规则库,将事实放入工作内存,通过条件匹配形成议程,再按调度策略执行动作,动作可能产生新事实或修改旧事实,从而驱动下一轮匹配。
二、方法流程:一条规则从定义到执行的完整链路
理解概念之后,需要把它们串成一条可运行的链路。下面以典型的规则引擎执行流程为例:
- 规则定义:业务人员或开发人员用规则语言或配置描述规则,包括条件、动作、优先级、互斥组等。
- 规则加载:引擎启动或热更新时,将规则解析为内部可执行结构,放入规则库。
- 事实插入:外部系统将待处理数据作为事实插入工作内存,例如一笔订单、一个用户画像。
- 模式匹配:引擎将工作内存中的事实与所有规则的条件进行匹配,找出当前可触发的规则集合。
- 议程生成:匹配成功的规则进入议程,议程是一个待执行规则的集合,可能包含多条规则。
- 冲突消解:当议程中有多条规则同时满足时,引擎根据优先级、互斥关系、依赖关系等策略决定执行顺序或选择执行哪一条。
- 动作执行:按消解结果执行规则动作,动作可能修改事实、插入新事实或删除事实。
- 循环推理:如果动作改变了工作内存,引擎会重新匹配,直到没有新规则可触发或达到终止条件。
关键点:规则引擎不是“一次性匹配”,而是“匹配—执行—再匹配”的循环。工作内存的变化会驱动新一轮推理,这也是规则依赖和优先级问题产生的根源。
三、案例/场景:用一段伪代码看清术语的落地形态
下面用一段简化的规则定义片段,展示条件、动作、事实和工作内存在实际代码中的对应关系。这里不依赖具体引擎语法,重点看结构。
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) | 条件满足后执行的逻辑 | 在动作中写复杂业务逻辑,导致规则难以维护和测试 |
| 事实 | 被规则处理的数据对象 | 把事实当成静态数据,忽略动作可以修改或插入事实 |
| 工作内存 | 运行时存放事实的容器 | 认为工作内存只是数据库缓存,忽略其驱动推理循环的作用 |
| 议程 | 当前可触发规则的集合 | 认为议程顺序就是规则定义顺序,忽略冲突消解策略 |
| 冲突消解 | 决定多条可触发规则执行顺序的机制 | 只关注优先级,忽略互斥和依赖对执行结果的影响 |
最常见的误区是:把“规则匹配成功”等同于“规则一定会执行”。实际上,匹配成功只意味着规则进入议程;是否执行、何时执行、执行哪一条,取决于冲突消解策略。优先级、互斥和依赖检测,正是围绕议程调度展开的。
学习建议:在后续章节中遇到“规则冲突”时,先回到本节的概念模型,确认是条件匹配问题、动作副作用问题,还是议程调度问题。大多数所谓“规则不生效”,本质是事实没有正确插入工作内存,或者动作修改事实后没有触发重新匹配。
掌握这些基础概念后,就可以进一步讨论:当多条规则同时满足时,优先级如何定义;当规则之间不能同时执行时,互斥如何表达;当一条规则的执行依赖另一条规则的结果时,依赖关系如何检测。这些问题的答案,都建立在“规则—条件—动作—事实—工作内存—议程”这条完整链路上。