服务B依赖于服务A中的数据:重复数据还是按需检索?

时间:2018-11-29 17:02:55

标签: database design-patterns service architecture microservices

这是一个微服务设计问题,是我想解决的现实生活问题的简化。

服务A的实体可以处于活动状态,也可以处于非活动状态。

[
    {
       id: "a46e6cc7-97ca-4570-b3f3-2be00ca9dab5",
       name: "foo",
       active: true
    },
    {
       id: "eb1ced31-eccc-4ad6-a695-5c6c76cab7a5",
       name: "bar",
       active: false
    },
    {
       id: "ef332044-9e66-4a0b-91ed-c16a2537e848",
       name: "baz",
       active: true
    }
]

服务B具有与服务A的实体相关的作业,并且仅在实体处于活动状态时才运行(根据业务规则)。

选项1: 。服务B不存储是否应运行作业。

[
    {
       id: "39cf3321-34d1-4557-b1c4-ca628c191b92",
       entityId: ""a46e6cc7-97ca-4570-b3f3-2be00ca9dab5",
       start: "Thu Nov 29 2018 08:40:27 GMT-0800 (Pacific Standard Time)",
       ended: null,
       recurrence: "hourly"
    },
    {
       id: "77296d22-564f-4289-8327-f23bceb1d400",
       entityId: "a46e6cc7-97ca-4570-b3f3-2be00ca9dab5",
       start: "Tu Nov 27 2018 15:56:01 GMT-0800 (Pacific Standard Time)",
       ended: null,
       recurrence: "hourly"
    },
    {
       id: "2916a920-13a3-46f6-9ffd-d7629163924a",
       entityId: "eb1ced31-eccc-4ad6-a695-5c6c76cab7a5",
       start: "Wed April 01 2018 00:00:00 GMT-0800 (Pacific Standard Time)",
       ended: Thu April 01 2019 00:00:00 GMT-0800 (Pacific Standard Time),
       recurrence: "daily"
    },
]

计划作业运行时进行检查

if Service A has j.entityId = true
   run j

使用服务A的API。

选项2: :服务B存储是否应运行作业

[
    {
       id: "39cf3321-34d1-4557-b1c4-ca628c191b92",
       entityId: ""a46e6cc7-97ca-4570-b3f3-2be00ca9dab5",
       active: true,
       start: "Thu Nov 29 2018 08:40:27 GMT-0800 (Pacific Standard Time)",
       ended: null,
       recurrence: "hourly"
    },
    {
       id: "77296d22-564f-4289-8327-f23bceb1d400",
       entityId: "a46e6cc7-97ca-4570-b3f3-2be00ca9dab5",
       active: true,
       start: "Tu Nov 27 2018 15:56:01 GMT-0800 (Pacific Standard Time)",
       ended: null,
       recurrence: "hourly"
    },
    {
       id: "2916a920-13a3-46f6-9ffd-d7629163924a",
       entityId: "eb1ced31-eccc-4ad6-a695-5c6c76cab7a5",
       active: false,
       start: "Wed April 01 2018 00:00:00 GMT-0800 (Pacific Standard Time)",
       ended: Thu April 01 2019 00:00:00 GMT-0800 (Pacific Standard Time),
       recurrence: "daily"
    },
]

它的存储通过服务A的通知保持最新状态:

Entity e changes => publish e => Service B updates accordingly

以下是我赞成每个选项的论点。

选项1参数:

  • 由于不重复数据,因此存储成本较低
  • 计划作业运行时,它始终具有有关是否应处于活动状态的最新信息(更多“一致性”?)
  • 不必处理跨服务同步数据的复杂性。在此示例中,只有服务B依赖于来自A的数据,但是想象一下,如果有服务X0,...,X1000,那么所有服务都需要知道一个实体是否处于活动状态。

选项2参数:

  • 服务是真正独立的:如果A没有运行,B仍然可以运行
  • 较少的聊天服务(较少的网络传输费用)
  • 虽然可能更复杂,但是复制/传播数据的复杂性迫使服务什么也不共享

2 个答案:

答案 0 :(得分:1)

这应该取决于您的需求以及通话的频率,但是在此之前,我想纠正一下。

存储成本真的不应该成为问题,要保持数据同步并避免后果。 聊天还不错,它可能会使事情复杂化,但是可以通过一些方法使事件驱动的系统产生奇迹并保持可维护性。

服务必须独立,一致,但这并不意味着它们不应该尊重边界。订单服务需要用户数据,但这不能证明将所有用户数据都保留在订单服务中是合理的。它并不能使它独立,而只是使服务blo肿,并使订单担心它不应该真正关心的事情。

因此,在您的情况下,我将更喜欢进行api调用(并为服务A设置SLA以快速响应,缓存或进行其他操作),但我会避免在系统中缓存其他一些数据。 但是,有时您的服务B被调用,每分钟说n次,而n越来越大,那么您可能倾向于使用方法b(但是它仍然是灰色区域,请谨慎操作,这可能会使您的生活变得困难取决于serviceA随时间变化的方式

答案 1 :(得分:0)

让我们尝试创造一些现实生活的情况以更好地理解:

我们正在开发youtube。

  1. 服务A管理作为用户的实体
  2. 服务B为每个用户运行一个作业-如果用户处于活动状态,则使用AI更新用户首选项。

在这种情况下,简单地从服务A中读取数据是很有意义的(即使存储并不昂贵)。

我们应该这样做,因为它很容易执行。同样,如果服务A关闭,则暂时不运行该作业对企业来说也可以。

现在在另一个业务案例中:

让我们尝试创造一些现实生活的情况以更好地理解:

我们正在开发youtube。

  1. 服务A管理作为用户的实体
  2. 服务B-如果用户不活动,请发送电子邮件通知。

这当然是我想使用事件来实现的。

现在,我的主要观点通常是在需要响应时执行一些操作,而相关性较低。 否则,从主服务中读取数据非常简单,并且在另一个服务中管理数据(很快将成为多个服务B的数据)将在管理上造成问题