通用的Delta差量化机制

1,534 阅读6分钟

任何一种动态更新(扩展)技术本质上都是在定义一种Delta差量空间以及这个空间中可行的结构合成运算。仔细思考一下就知道,一般人眼中所谓的动态更新无非就是在已经构造好的结构上定义扩展点,然后将符合接口规范的结构插入到扩展点中。实现动态的差量化更新的复杂性体现在如下三点:

  1. 如何设计扩展点才能保证满足未知的差量更新需求?

  2. 如何实现外部引入的差量结构与原有的结构无缝融合?

  3. 如何保证差量化更新前后运行时状态的一致性?

除了以上三点,我们还可以问自己一个问题:既然所有的业务逻辑结构都存在潜在的动态更新需求,为什么每一个特定的结构都要单独定制自己的差量更新方案?能否通过一种统一的技术方案一举解决上面三个技术难题?

关系模型的成功经验

为了回答上面的问题,我们可以参考关系模型的发家历史。在关系数据库一统江湖之前,数据存储的方式可谓是五花八门,八仙过海各显神通。但是关系数据库模型之所以能够标准化存储机制,是它选择后退一步海阔天空。在关系模型中我们放弃了数据之间天然存在的各种关联关系,将关注的重点完全集中在原子化的无冗余的数据上,把它们按照规范处理好之后,再通过各种衍生运算动态计算得到最终需要的数据。特别的,所有数据间原有的指针强关联都被打破,所有的关系都被分解(所谓的关系数据库中无关系),仅保留id和ref_id这种关联字段信息,在运行时(实际需要使用数据的时候),我们再使用join语句,通过即时的计算(索引查找或者表扫描),在内存中重建数据之间的关系。再次强调一下,关系模型的强大依赖于它将即时计算引入标准化结构数据的存取过程,在运行时重建关系,而ORM引擎的作用是将关系模型中被分解掉的关系重新捡回来,内置在对象模型中,避免在业务表达时总是频繁重复表达主外键关联关系。

为了实现无歧义、标准化的差量更新,可逆计算理论的选择与关系模型一样,同样是后退一步,在标准化的无冗余的结构层进行操作,而不是在按照类型出现分化的对象层上进行操作。Nop平台中的差量合并机制统一定义在XDSL层面,它是一种标准化的、可以采用XML或者JSON格式表达的信息结构,通过元模型XDefinition进行结构约束。

关系模型理论可逆计算理论
Schema定义XDefinition元模型规范
无冗余的表格数据无信息冗余的树形信息结构:XDSL
在标准化数据结构基础上的即时计算:SQL在通用的XNode数据结构基础上的编译期计算:XLang

Nop平台的XLang相当于是发展了一整套系统化的对Tree结构的定义、解析、转换、分析的工具集。Nop平台之所以能够实现标准化的、与业务无关的差量合并运算,原因在于它是在通用的XDSL结构层定义差量运算,而不是在XDSL解析得到的模型对象层。

回顾一下Nop平台中的模型加载过程

DslModel = ResourceComponentManager.instance().loadComponentModel(modelPath)

如果采用函数式语言的抽象表达形式,它对应于

   modelPath => XDSL => DslModel 

XDSL是无冗余的、标准化的、面向信息存储和传递的结构化信息表达形式,而DslModel是经过编译优化、提供大量衍生数据的、面向对外使用的信息表达形式。它们两者之间通过一个动态的响应式计算过程联系起来:一旦DSL文件被修改,DslModel就自动重新解析。

微服务架构的成功经验

差量化更新时如何保证运行时状态在更新前后的一致性?对于这个问题的回答,我们可以参考一下微服务架构的解决方案。

微服务架构之所以能够实现动态滚动更新,依赖于所谓的无状态设计。面向对象的传统做法是函数和它所处理的函数封装到所谓的对象中,最后函数和数据相互纠缠,形成意大利面条般盘根错解的混乱结构,难以进行拆解,自然也难以做到局部更新。理想的情况下,最好形成类似千层饼的切片结构,随时可以一层层的叠加或者削减。 无状态设计的本质是实现逻辑处理结构和运行时状态空间的解耦。清气上升,浊气下沉,运行时的动态状态数据从静态的纯逻辑处理结构中被排挤出去,一部分成为被传递的参数数据,另一部分成为保存在共享存储中的持久化数据,这样微服务本身的运行时结构中就不再明确包含状态数据,因此它的动态更新也就不和状态空间的数据迁移纠缠在一起,成为一个可以被独立解决的问题。

访问微服务的时候我们会先访问服务注册中心,通过服务名动态查找得到服务实例,然后再向它发送输入参数,服务实例根据输入参数再自动加载持久化状态数据。如果采用函数式语言的抽象表达形式,微服务的处理过程对应于

  serviceName => Service => input => state => Result

类似的,在Nop平台中,所有模型的处理过程都采用同样的逻辑结构

  modelPath => XDSL => DslModel => arguments => scope => Result

类似于微服务,DSL模型的动态更新同样可以独立于状态空间中的数据迁移。

基于可逆计算理论设计的低代码平台NopPlatform已开源: