数据工程中的三种数据创建方式比较


所有成功的数据驱动组织都有一个共同点;他们有一个高质量和高效的数据创建过程。数据创建通常是数据团队成功与失败之间的区别。

数据创建的架构模式在数据创建中,有三种类型的架构模式:

  1. 事件溯源EventSourcing
  2. 变更数据捕获[CDC]
  3. 发件箱模式

现代数字时代的任何企业都可以被视为一个工作流程引擎。一个业务流程或工作流程引擎是一个软件系统,使企业能够执行定义明确的步骤来完成用户的意图。它既可以是预订出租车,也可以是订购午餐;一切都属于工作流程引擎。  

案例
让我们来看看Uber的共享汽车的简化业务流程。现实世界的情况比这要复杂得多,但就本博客的范围而言,让我们把共享汽车的业务流程简化为三个简单的步骤。

  • 乘客要求乘坐新车。
  • 共享单车应用程序找到最近的司机,并要求接受乘坐。
  • 一旦接受,骑手和司机连接起来,完成旅程。

数据工程通过在业务流程的每一步捕获事件,开始为业务增加价值。然后,这些事件被进一步丰富和分析,为业务运营带来可见性。

从事件建模的角度来看,在共享汽车的例子中,骑手和司机被称为实体,而乘车请求和司机请求被称为事件。实体和事件是数据创建的两个功能单元,而你的数据组织的成功取决于实体和事件创建架构的稳定性。

1.事件源EventSourcing
事件源是一种系统设计模式,它将业务流程的当前状态写进记录日志。记录日志将是不可改变的,是一种仅有附录的格式。记录日志通常是一个HTTP服务器,传输给下游的消费者来处理。

在骑手业务流程中,当骑手要求乘坐新车时,后台系统会验证该请求的真实性并估算价格。在找到司机之前,它写了一个格式如下的日志事件。

{

  "event_timestamp": "2023-03-24T14:30:00Z",

 
"event_type": "ride_request",

 
"event_id": "1234567890",

 
"rider_id": "987654321",

 
"pickup_location": {

   
"latitude": 37.7749,

   
"longitude": -122.4194,

   
"address": "123 Main St, San Francisco, CA"

  },

 
"destination_location": {

   
"latitude": 37.7749,

   
"longitude": -122.4113,

   
"address": "456 Broadway, San Francisco, CA"

  },

 
"ride_options": {

   
"uber_x": {

       
"price_estimate": "$10-15",

       
"wait_time": "5 minutes"

    },

   
"uber_pool": {

         
"price_estimate": "$5-8",

         
"wait_time": "10 minutes"

      }

  }

}

事件是一种结构化的数据交换格式。它将所有的业务背景带到下游的消费者那里,并使他们能够运行多种分析过程。

然而,事件源有几个主要的限制。

限制#1:事件质量不可预知
在复杂的应用程序中,乘车请求可以通过合作伙伴网络或后台系统发生,在那里乘客打电话预订出租车或任何其他可能的渠道。这导致了一个需求,即开发者应该利用多个代码路径来生成共享汽车事件。由于开发人员经常改变代码,它可能会在数据生成代码中引入各种错误。该事件可能不会触发,有较差的shema质量,或有模式不兼容。

限制#2:缺乏事务性保证
改变代码路径的应用逻辑和事件源系统不会被绑定到同一个事务边界。所以会有这样的情况,一个事件可能会触发一个骑行请求,但事务性数据库可能会使请求失败,反之亦然。这导致了下游系统和事务性数据库之间的状态不一致。

2.变更数据捕获[CDC]
变更数据捕获(CDC)是一种技术,CDC系统监测并记录数据的修改,如事务存储中的插入、更新和删除,并通过管道进入下游系统,而不是应用程序对事件进行检测。

CDC系统减少了事件的不可预测的质量和完整性,因为这里没有应用人工介入。

然而,CDC也出现了自己的一系列问题。

缺点#1:昂贵的商业逻辑的重新创建
CDC反映了交易型数据模型,对于下游的分析型消费者来说,这是一种非理想的数据建模格式。让我们以同样的共享汽车事件为例。交易型数据库的可能的表模型:

  • 乘坐者
  • 地点[接机/目的地]
  • 价格
  • 服务

CDC系统监控并持续流转每个表的变化数据。下游的流媒体中间件应该连接所有需要的流,并为下游的分析消费创建骑行事件。Stream-stream流-流,结合重复的业务逻辑实现,是任何公司都想避免的解决方案。

CDC的其他挑战包括在操作存储上引入系统性负载。有足够的优化技术,比如从孤立的复制中读取等等,来优化基础设施的复杂性。

发件箱模式
当CDC试图解决事件的不可预测的质量问题时,Outbox模式试图解决事件的交易事务性保证问题。

outbox模式使应用开发者在修改事务性数据库的同时,可以将事件作为事务的一部分来写。因此,它保证了记录修改系统和事件维护之间的一致性。

发件箱模式也有助于解决事件的因果关系。我们可以重复使用发件箱表的时间戳作为事件的时间戳。因此,源系统中任何破坏事件来源方法中因果关系的时钟漂移,都可以通过发件箱模式来避免。

一个典型的发件箱表将看起来如下:
id:唯一标识
aggregate_id:聚合根标识
aggregate_type:聚合根实体类型,对路由有用
event_type:发生的事件类型,如created updated或deleted,接收者能够明白数据改变的原因
payload:事件的数据
timestamp:事件插入outbox表的时间
status(可选):每条记录状态,如pengding、in_progress、sent或failed

缺点 #1:不是每个数据库都支持事务
关系型数据库支持多个突变语句的交易。然而,如果你使用像DynamoDB这样的系统,事务支持就属于应用程序或数据访问层。在应用层维护事务支持是昂贵而复杂的。

缺点2:不是每个事件都需要事务性的保证
缓存失效;分布式金融交易、搜索索引和类似的应用集成模式需要分布式交易事务性支持。

在许多情况下,对分析性事件的交易支持可能不是更优先的,因为完成业务交易对一个应用来说是至关重要的。

缺点#3:Outbox模式仍然受到事件质量不可预测的影响
我们讨论的关于事件源模式中事件质量不可预测的所有问题仍然适用于发件箱模式。

数据创建的模式化方法--建模优先和合同驱动的方法
基本问题仍然是,什么是事件创建的有效策略?是事件溯源还是CDC,或者是Outbox模式?

与其从技术角度考虑问题,不如从业务影响角度考虑。我最近进行了这项调查,以了解事件源技术的首要痛点。

数据工程师们说,这些是数据创建过程中的首要关注点。

  • 缺少数据建模
  • schema模式的破坏性改变
  • 数据质量

Schemata是一个以数据建模为先,以数据契约为驱动的平台。Schemata实现了面向领域的数据建模技术,并以一种编程的方式来衡量你的数据模型是如何相互连接的。

Schemata建议采用CDC+(事件源/发件箱模式)的组合。

捕获实体及其生命周期事件,如新骑手注册和地址变更,更容易从CDC管道中获取。一个实体的变化往往发生在操作系统的一个表中。因此,使用CDC模式的来源相对更简单和可靠。

另一方面,复杂的业务交易事务可能会影响到多个表。任何来自CDC的重新创建过程都是昂贵的。因此,Schemata推荐使用事件源或Outbox模式来创建事件。