将单体系统拆分为微服务时,需要为数据(表)指定所有者——哪个服务对数据(表)具有所有权。正常理解,具有写操作的服务才会涉及到所有权,这样就可以划分为三种情形:

  • Single Ownership
  • Joint Ownership
  • Common Ownership

Single Ownership

如果一张表只有一个服务在写,就认为服务拥有这张表,可以毫无负担地把这张表分拆给服务,组成一个独立的微服务。

Joint Ownership

如果一张表被部分服务写,此时这部分服务对表具有联合所有权,需要进一步明确数据所有权,有 4 种处理方法:

  • Table Split
  • Data Domain
  • Delegate
  • Service Consolidation

1. Table Split

如果多个服务的写表操作是分散在不同的字段,那么可以将一张表打散为几张表,每张表包含不同服务写到的字段,通过表 id 进行关联。

伴随而来的问题是需要在不同的表之间(至少)进行增/删同步,并且因为对分拆后的其他表没有所有权,还需要通过服务间调用来同步,这就涉及到 CAP 理论中阐述的问题,是选择可用性优先(服务间调用失败,系统整体状态不一致时,仍然可用),还是一致性优先(服务间调用失败则不可用,保障系统整体状态的一致性)。

2. Data Domain

当被多个服务共享时,可以将共享的表放到同一个 Schema 或 Database 里,此时共享数据不归属于任一服务,而被所有相关服务共享。

带来两个问题:

  • (共享)表结构的变更会引发若干共享服务变更。
  • 某些特定数据的写操作仍然需要控制写方,需要做额外的工作去应用相关的控制规则。

3. Deletegate

可以将写操作委托给某一个服务,由它统一做。如何选择委托,有两种方式:

  • Primary Domain Priority,CRUD 操作最多的成为委托。(analogy:企业里工作量最多的组负责项目牵头)
  • Operational Characteristics Priority,拥有更高运维特性(performance、scalability、availability、throughput)要求的成为委托。尽量减少它的依赖复杂度。(analogy:企业里最着急的组负责项目牵头)

委托的主要问题是:它也是一个服务,但干了职责外的事情。同时,委托导致了服务间耦合和通信。因此它适用于不要求原子性事务、接受通过异步通信方式来达到最终一致性要求的情形。

4. Service Consolidation

这种方式其实是转换思路,如果数据不能分开,就把服务合起来。所谓山不过来,我就过去。

缺点是服务的粒度变粗了,测试范围变大、部署风险增大、容错性降低等问题随之而来。

Common Ownership

如果一张表被所有服务写,此时所有服务对表具有公共所有权,如果服务数量变得很大,将带来诸多问题(变更控制、连接饿死、可扩展性、容错)。

一种常用方法是指定一个默认服务作为数据所有者,只有它能直接写数据,其他服务通过调用默认服务来写数据。服务间调用可以使用 REST、gRPC、消息队列等通用技术。

最后

一个大致的全局视野


0 条评论

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注