Activiti——从表名前缀看工作流引擎的数据架构设计
1. Activiti表名前缀的奥秘
第一次接触Activiti数据库表结构时,我盯着那些以ACT_开头的表名发了半天呆。直到某次排查流程历史数据问题时,突然意识到这些看似随意的前缀字母组合,其实是设计者埋下的精妙彩蛋。每个双字母后缀都对应着工作流引擎的一个核心模块,就像乐高积木的卡扣设计,通过标准化接口实现模块间的无缝衔接。
以ACT_RE_开头的表让我栽过跟头。有次客户要求查询三个月前的流程定义版本,我直接去运行时表ACT_RU_里翻了个底朝天。后来才明白RE代表Repository(存储库),这类表专门存放流程定义、规则文件等"静态资产",就像图书馆的书架,而RU(Runtime)表则是读者正在翻阅的书本,流程结束后就会物归原处。这种设计使得生产环境的运行时表始终保持轻量,实测在万级流程实例并发时,查询响应仍能控制在200ms内。
2. 通用数据表(ACT_GE_)的设计哲学
ACT_GE_BYTEARRAY表堪称Activiti的"瑞士军刀",它用LONGBLOB字段统一存储各种二进制资源。有次我们需要扩展流程附件功能,发现用户上传的PDF合同和系统生成的签章图片都被转化byte数组存于此表。这种设计虽然增加了读取时的反序列化开销,但换来的是无与伦比的扩展性——我们甚至曾临时存放过音频校验文件。
ACT_GE_PROPERTY表则是引擎的"控制面板"。记得升级Activiti 5到6时,schema.version字段值从5.*变成6.*引发启动报错。更精妙的是next.dbid机制,采用预分配ID区间的方式避免分布式环境下的主键冲突。某次性能测试显示,这种设计使主键生成效率比传统自增ID提升近40%。
3. 流程存储表(ACT_RE_)的版本智慧
ACT_RE_DEPLOYMENT和ACT_RE_PROCDEF这对黄金组合解决了流程定义的版本管理难题。我们电商系统每次大促前都会部署新版订单流程,PROCDEF表中的VERSION_字段自动递增,形成清晰的版本链。最绝的是KEY_+VERSION_的唯一约束,既保留了流程的业务标识,又支持多版本并行。曾有个紧急修复版本,我们直接修改流程定义后重新部署,系统自动将旧版本标记为挂起状态(SUSPENSION_STATE_=2),实现热切换零停机。
流程图片存储也暗藏玄机。DGRM_RESOURCE_NAME_字段不仅存储流程图PNG,还与ACT_GE_BYTEARRAY表的BYTES_字段形成"文件名-内容"的分离式存储。这种设计在我们需要导出流程文档时大放异彩——直接按图索骥就能组装完整的流程定义包。
4. 运行时数据表(ACT_RU_)的瞬时艺术
ACT_RU_TASK表的设计充分体现" ephemeral "(瞬时)理念。当审批人点击完成任务时,引擎会闪电般完成三件事:将当前任务移入历史表、删除运行时记录、创建新任务记录。这种"流水不腐"的特性使得该表行数始终保持在活跃任务量级,实测在500并发时查询性能仍能保持线性增长。
ACT_RU_VARIABLE表的类型自适应设计更令人叫绝。它用TYPE_字段区分变量类型,同时在DOUBLE_、LONG_、TEXT_等字段中选配存储。我们曾需要存储JSON格式的订单快照,直接使用TEXT_字段就能搞定。但要注意VAR_TYPE_为serializable时,会触发Java序列化存入BYTEARRAY_ID_关联的资源表,这种操作在频繁访问时可能成为性能瓶颈。
5. 历史数据表(ACT_HI_)的审计之道
ACT_HI_PROCINST表的DURATION_字段藏着流程优化的金矿。通过分析这个记录流程耗时(毫秒)的字段,我们定位到报销流程在财务审核节点平均停留48小时,进而优化了审批提醒机制。而DELETE_REASON_字段则像黑匣子记录着流程异常终止的原因,有次系统崩溃后正是靠它区分出正常完成与异常终止的实例。
ACT_HI_ACTINST表是流程运行的"逐帧录像"。某次客户投诉说流程卡住,我们通过该表的ACT_ID_字段序列,发现流程实际是在服务节点等待第三方回调,完美还原真相。但要注意历史级别设置:当设置为none时这些表都为空,而full级别会记录每个变量变更,可能使数据量暴涨10倍。
6. 身份数据表(ACT_ID_)的扩展空间
ACT_ID_USER表的字段设计体现了西方命名习惯(FIRST_/LAST_),我们在国内项目中使用时增加了工号映射字段。而ACT_ID_MEMBERSHIP的极简设计(仅USER_ID_+GROUP_ID_)反而提供了灵活性,曾通过扩展TYPE_字段实现了"临时负责人"这种特殊关系。
最容易被忽视的是ACT_ID_INFO表,它原本设计用于存储用户额外属性。我们在实现OA系统集成时,巧妙利用它的KEY_/VALUE_字段存储了AD账号信息。但这种用法要注意与PASSWORD_字段的隔离,避免敏感信息泄露风险。
7. 表关联背后的流程引擎机理
流程实例的完整生命周期会在各表间留下关联痕迹。以采购审批流程为例:
- 部署时:ACT_RE_DEPLOYMENT记录部署包,ACT_RE_PROCDEF解析出流程定义
- 启动时:ACT_RU_EXECUTION创建执行实例,ACT_HI_PROCINST记录历史
- 运行时:ACT_RU_TASK生成审批任务,ACT_RU_VARIABLE存储表单数据
- 结束时:ACT_HI_ACTINST补全活动记录,运行时表数据自动清除
这种环环相扣的设计使得Activiti在保持内核精简的同时,能通过历史服务完整追溯流程轨迹。但要注意RU表与HI表的数据一致性,我们曾因事务配置不当导致历史记录缺失,后来通过添加双重校验机制解决。