数据二分法:重新思考我们对待数据和服务的方式

title

如果你偶然发现整个微服务的事情,没有任何先前的背景,你会认为它有点奇怪。将应用程序拆分为由网络分隔的片段,不可避免地意味着注入分布式系统的复杂故障模式。

然而,虽然该方法肯定涉及许多独立服务,但目标比仅仅在不同的机器上运行它们更广泛。它是关于面对一个本身就是固有分布的世界。不是在某种狭隘的技术意义上,而是由许多人,许多团队和许多程序组成的广泛的生态系统,所有这些都需要在某种程度上做自己的事情。

例如,公司是不同系统的集合,这些系统共同进一步促进了一些共同目标。几十年来,我们在很大程度上忽略了这一事实,将它们与FTP文件传输或企业集成工具一起修补,同时专注于我们自己的一些孤立主义目标。但服务改变了这一点。他们将我们的头抬高到栏杆之上,进入一个协作的,相互依存的计划世界。但要想在这方面取得成功,我们必须认识并设计两个根本不同的世界:外部世界,我们生活在许多其他服务的生态系统中,以及我们私人的内部世界,我们独自统治国王。

但是这个分布式的世界与我们长大的世界略有不同。传统的单片软件工程规则不再以同样的方式存在水。因此,正确使用这样的系统不仅仅是在白板上绘制一个很酷的草图或者是一个性感的概念证明。这是为了让这些东西随着时间的推移成功运作。幸运的是,服务已经存在了很长时间,尽管有几种不同的形式。虽然最近有Docker,Kubernetes和一些稍微过度笨拙的胡须,但SOA的教训仍然存在。

所以今天我们将看看规则是如何变化的,为什么我们应该重新思考我们的服务方法和它们共享的数据,以及为什么我们需要一个不同的工具集来实现这一点。

封装并不总是你的朋友

微服务可独立部署。正是这个属性比任何其他属性更能赋予它们价值。它允许他们扩展。成长。在扩展到数以万计的用户或数PB的数据意义上(尽管他们可能会有所帮助),而不是在人员方面进行扩展,随着您的团队和组织的发展。

但独立本身就是一把双刃剑。这意味着服务可以快速自由地迭代。但是,如果一个服务实现了需要更改其他服务的功能,我们最终必须在同一时间对这两个服务进行更改。虽然这在单片应用程序中很容易,您可以简单地进行更改并执行发布,但在独立服务必须同步的情况下却更加痛苦。团队和发布周期之间的协调会削弱敏捷性。

典型的方法是通过干净地分离服务之间的职责来简单地避免这种讨厌的横切变化。单点登录服务就是一个很好的例子。它具有明确定义的角色,可以与其他服务所扮演的角色完全分开。这种清晰的分离意味着,即使面对周围服务的快速需求流失,SSO服务也不太可能需要改变。它存在于一个紧密有界的环境中

问题在于,在现实世界中,商业服务通常不能保持相同,清晰,分离的关注点。例如,商业服务不可避免地更多地依赖彼此的数据。如果您是在线零售商,订单流,产品目录或客户信息可能会发现它可以满足您的许多服务需求。这些服务中的每一项都需要广泛访问这些数据集才能完成工作。

大多数商业服务共享相同的事实流。这使得他们的未来不可避免地交织在一起。

所以这是一个值得注意的重点,虽然服务对于基础设施组件很有效,而这些组件的生活很大程度上是孤立的,但大多数商业服务的未来都紧密地交织在一起。

数据二分法

基于服务的方法可能已存在一段时间,但它们仍然对如何在服务之间共享重要数据集提供相对较少的见解。

潜在的问题是数据和服务不能太融合在一起。一方面,封装鼓励我们隐藏数据; 将服务彼此分离,以便他们可以继续改变和发展。这是关于未来的规划。但另一方面,我们需要像任何其他数据集一样自由切割和切割共享数据。这是关于我们现在的工作,与其他任何数据系统具有相同的自由。

但数据系统与封装几乎没有关系。事实上,恰恰相反。数据库尽其所能来公开它们所拥有的数据。它们具有非常强大的声明性界面,可以将数据扭曲成您可能想要的任何形状。正是你需要进行探索性调查,但对于管理新兴服务区的复杂性并不是那么好。

所以我们发现自己面临着一个难题。矛盾。二分法:数据系统是关于暴露数据。服务是关于隐藏它。

这两种力量是根本的。它们构成了我们所做的大部分工作的基础,巧妙地在我们构建的系统中争夺至高无上的地位。

随着我们不断发展和发展基于服务的系统,我们看到这种数据二分法的效果以几种不同的方式发挥作用。服务接口将增长,暴露越来越多的功能,使其开始看起来像某种形式的kookie,自行开发的数据库。或者,挫折将会起作用,我们会添加一些从整个服务到服务的整个数据集的提取和移动方式。

现在创建看起来像kookie的东西,共享数据库可能会导致一系列问题。我们不会在这里涉及共享数据库的危险,但足以说它们代表了尝试它们的公司的重大且昂贵的工程和运营挑战

更糟糕的是,数据量实际上放大了这个服务边界问题。隐藏在服务边界内的共享数据越多,接口可能变得越复杂,并且跨越不同服务加入数据集的难度就越大。

然而,替代方案 - 提取和移动整个数据集 - 也存在问题。一种常见的方法是简单地提取并保存整个数据集,然后将其存储在每个消费服务内的本地数据库中。

问题是不同的服务对它们消耗的数据做出不同的解释。他们保留这些数据。数据在本地被更改和修复。很快它根本不代表源数据集。

可变拷贝越多,随着时间的推移,数据就会越多。

更糟糕的是,不同的数据在回顾过程中很难修复(MDM实际上是一个粘性物质)。实际上,企业遇到的一些最棘手的技术问题来自于从应用程序到应用程序的不同数据集。

为了解决这个问题,我们需要以稍微不同的方式考虑共享数据。我们需要将其视为我们构建的架构的一等公民。Pat Helland称这种数据为内部,这是一个有用的区别。我们需要封装,因此我们不会暴露服务的内部状态。但我们需要让服务轻松访问共享数据,以便他们可以继续工作并完成工作。

问题是,现在没有一种可用的方法,服务接口,消息传递或共享数据库,为处理外部数据提供了一个很好的解决方案。服务接口不适合以任何规模级别共享数据。消息传递移动数据,但不提供历史参考,这会导致数据随时间而损坏。共享数据库集中在一个地方,扼杀了进步。因此,我们不可避免地陷入数据不足的循环中:

数据不足的循环

流:分散的数据和服务方法

因此,理想情况下,我们希望重新调整服务处理共享数据的方式。现在任何这样的方法都必须面对上面提到的二分法,没有任何技术上的仙尘我们可以随意撒上并将其魔法化。但我们可以重新定义问题,并选择一个微妙的不同妥协。

这种特殊的妥协涉及一定程度的集中化。我们可以使用分布式日志,因为它提供了保持性,可扩展的流。现在我们需要我们的服务能够加入和操作这些共享流,但我们希望避免执行此类处理的复杂,集中的“上帝服务”。因此,更好的方法是将流处理嵌入到每个消费服务中。这意味着服务可以将各种共享数据集连接在一起,并按照自己的进度迭代它们。

实现此目的的一种方法是使用流式平台。有很多选项,但在这里我们会考虑Kafka,因为它使用有状态流处理使它特别适合这个问题。

使用分布式日志将我们推向一条相当完善的路径,一条使用消息传递来实现服务事件驱动的路径。这些方法通常被认为提供了比其请求 - 响应兄弟更好的可扩展性和更好的解耦,因为它们将流控制从发送方移动到接收方。这增加了每项服务的自主权。公平地说它是有代价的:你需要一个经纪人。但是对于重要的系统来说,这通常是一个值得做出的权衡(对于普通的Web应用程序来说更少)

现在,如果代理是分布式日志,而不是传统的消息传递系统,则可以利用一些其他属性。传输可以与分布式文件系统大致相同的方式线性扩展。数据也可以长期保留在日志中。所以这是消息,但它也是存储。存储可扩展,没有共享,可变状态的危险。

然后,状态流处理引擎,可以用来嵌入数据库的声明工具,直接在消费服务。这一点很重要。虽然数据存储在共享流中,但是所有服务都可以访问,但是服务的连接和处理是私有的。智慧在每个有限的上下文中被隔离。

通过共享不可变的状态流来解决数据二分法。然后使用有状态流处理引擎将该功能推送到每个服务中。

因此,如果您的服务需要在公司的订单,产品目录或库存上运行,则它具有完全访问权限: 您决定应合并哪些数据集,您决定 执行的位置,并决定何时以及如何随着时间的推移而发展它。这意味着,虽然数据本身是共享的,但对该共享数据的操作是完全 分散的。它完全位于每个服务边界内,在一个你独自统治国王的世界里。

以一种使其忠实于源的方式共享数据。封装功能,不是在源头,而是在需要它的每个服务中。

现在事实证明,有时数据必须集中移动。有时,服务需要在他们选择的数据库引擎中使用本地历史数据集。这里的技巧是确保通过返回分布式日志,可以随意从源重新生成副本。Kafka中的连接器有助于此。

因此这种方法有一些特定的优点:

  • 数据作为流共享,可以长期驻留在日志中,但操作共享数据的机制嵌入到每个有界上下文中,从而可以轻松快速地自由迭代。这平衡了数据的二分法。
  • 数据集可以轻松地在不同的服务中实时连接。这样可以更轻松地与共享数据进行交互,从而无需在数据库中维护本地数据集。
  • 有状态流处理仅缓存数据,“黄金源”是共享日志,因此数据随时间发散的问题远没那么普遍。
  • 服务本质上是事件驱动的,这意味着随着数据集的增长,服务仍然可以对业务事件做出快速反应。
  • 可伸缩性问题从服务转移到代理。这使得构建更简单的服务变得更加容易,而不需要担心规模。
  • 添加新服务不需要更改上游服务。这样可以更轻松地插入新服务。

所以这不仅仅是REST。它是一个以分散的方式包含共享数据的工具集。

这篇文章真的只是一个品尝者,掩盖了许多细节。我们仍然需要深入研究如何平衡请求 - 响应和事件驱动的范例。我们将在下一篇文章中这样做。还有一些我们需要更好理解的主题,比如为什么有状态流处理如此有价值。第三篇文章将着眼于此。如果我们选择这条路径,还有其他一些我们可以利用的强大构造,例如确切地一次处理。这是分布式业务系统的游戏规则改变者,因为它以可扩展的形式提供XA的事务保证。第四篇文章将进入那个。最后,我们需要贯彻执行这些事情的细节。

但就目前而言,请记住这一点:数据二分法描述了我们在构建业务服务时必须面对的紧张局势。我们应该注意这个事实。诀窍是改变方法:将共享数据视为一等公民。我们设计的东西。有状态流处理为此提供了独特的折衷方案。它避免了通常会扼杀进步的核心“上帝组成部分”。而且,它带来了流数据流水线的即时性,可扩展性和容错性,并将它们嵌入到每个服务中。因此,我们专注于整体意识流,任何服务都可以通过这种意识流来做出决策。这使服务更具可扩展性,可互换性和自主性。因此,它们不仅在白板和POC上看起来很好,它们还能继续存活并发展数十年。

原文地址

第1部分:数据二分法:重新思考我们对待数据和服务的方式
第2部分:在事件的主干上构建服务
第3部分:使用Apache Kafka作为可伸缩的、事件驱动的服务架构主干(请参阅下一部分)
第4部分:具有一次保证的连锁服务
第5部分:信息作为真理的单一来源
第6部分:利用未绑定数据库的强大功能
第7部分:使用Kafka流和KSQL构建微服务生态系统

Powered by Hexo and Hexo-theme-hiker

Copyright © 2013 - 2021 朝着牛逼的道路一路狂奔 All Rights Reserved.

访客数 : | 访问量 :