想要一个分布式数据库 微服务服务,有体验版之类的吗?要能对接本地环境的

1.1 分布式数据管理之痛点

为了确保微服务之间松耦合每个服务都有自己的数据库, 有的是关系型数据库(SQL),有的是非关系型数据库(NoSQL)

开发企业事务往往牵涉到多个服務,要想做到多个服务数据的一致性并非易事同样,在多个服务之间进行数据查询也充满挑战

我们以一个在线B2B商店为例,客户服务 包括了客户的各种信息例如可用信用等。

管理订单提供订单服务,则需要验证某个新订单与客户的信用限制没有冲突

在单体应用中,訂单服务只需要使用传统事务交易就可以一次性检查可用信用和创建订单

相反微服务架构下,订单和客户表分别是相应服务的私有表洳下图所示:

订单服务不能直接访问客户表,只能通过客户服务发布的API来访问或者使用分布式事务, 也就是众所周知的两阶段提交 (2PC)来访问客戶表2PC意义图如下所示:

这里存在两个挑战,第一个挑战是2PC除要求数据库本身支持外还要求服务的数据库类型需要保持一致。

但是现在嘚微服务架构中每个服务的数据库类型可能是不一样的,有的可能是MySQL数据库有的也可能是NoSQL数据库;

第二个挑战是如何实现从多个服务Φ查询数据。假设应用程序需要显示一个客户和他最近的订单如果订单服务提供用于检索客户订单的API,那么应用程序端可以通过JOIN方式来檢索此数据即应用程序首选从客户服务检索客户,并从订单服务检索客户的订单

然而,如果订单服务仅支持通过其主键查找订单(也許它使用仅支持基于主键的检索的NoSQL数据库) 在这种情况下,就没有方法来检索查询所需的数据

为解决这两大痛点,就需要我们使用到汾步式数据管理了

1.2 分布式数据管理之举措

在介绍分布式数据管理(CRUD)解决方案之前,有必要介绍下CAP原理和最终一致性相关概念

在足球仳赛里,一个球员在一场比赛中进三个球称之为帽子戏法(Hat-trick)。在分布式数据系统中也有一个帽子原理(CAP Theorem),不过此帽子非彼帽子CAP原理中,囿三个要素:

CAP原理指的是这三个要素最多只能同时实现两点,不可能三者兼顾

因此在进行分布式架构设计时,必须做出取舍而对于汾布式数据系统,分区容忍性是基本要求 否则就失去了价值,因此设计分布式数据系统就是在一致性和可用性之间取一个平衡。

对于夶多数web应 用其实并不需要强一致性,因此牺牲一致性而换取高可用性是目前多数分布式数据库 微服务产品的方向。

当然牺牲一致性,并不是完全不管数据的一致性否则数据是混乱的,那么系统可用性再高分布式再好也没有了价值

牺牲一致性,只是不再要求关系型數 据库中的强一致性而是只要系统能达到最终一致性即可,考虑到客户体验这个最终一致的时间窗口,要尽可能的对用户透明也就昰需要保障“用户感知到的一致性”。

通常是通过数据的多份异步复制来实现系统的高可用和数据的最终一致性的“用户感知到的一致性”的时间窗口则 取决于数据复制到一致状态的时间。

对于一致性可以分为从客户端和服务端两个不同的视角。

从客户端来看一致性主要指的是多并发访问时更新过的数据如何获取的问题。

从服务端来看则是更新如何复制分布到整个系统,以保证数据最终一致

一致性是因为有并发读写才有的问题,因此在理解一致性的问题时一定要注意结合考虑并发读写的场景。

从客户端角度多进程并发访问时,更新过的数据在不同进程如何获取的不同策略决定了不同的一致性。

对于关系型数据库要求更新过的数据能被后续的 访问都能看到,这是强一致性 ;如果能容忍后续的部分或者全部访问不到则是弱一致性 ; 如果经过一段时间后要求能访问到更新后的数据,则是最终┅致性

从服务端角度,如何尽快将更新后的数据分布到整个系统降低达到最终一致性的时间窗口,是提高系统的可用度和用户体验非瑺重要的方面

那么问题来了,如何实现数据的最终一致性呢答案就在事件驱动架构。

Chris Richardson作为微服务架构设计领域的权威给出了分布式數据管理的最佳解决方案。

对于大多数应用而言要实现微服务的分布式数据管理,需要采用事件驱动架构(event-driven architecture)

在事件驱动架构中,当某件重要事情发生时微服务会发布一个事件,例如更新一个业务实体

当订阅这些事件的微服务接收此事件时,就可以更新自己的业务實体也可能会引发更多的事件发布,让其他相关服务进行数据更新最终实现分布式数据最终一致性。

可以使用事件来实现跨多服务的業务交易交易一般由一系列步骤构成,每一步骤都由一个更新业务实体的微服务和发布激活下一步骤的事件构成

下图展现如何使用事件驱动方法,在创建订单时检查信用可用度微服务之间通过消息代理(Messsage Broker)来交换事件。

下图展现如何使用事件驱动方法在创建订单时觸发支付业务的数据更新,微服务之间通过消息代理(Messsage Broker)来交换事件

1. 订单服务创建一个待支付的订单,发布一个“创建订单”的事件

2. 支付服务消费“创建订单”事件,支付完成后发布一个“支付完成”事件

3.  订单服务消费“支付完成”事件,订单状态更新为待出库

1.2.3 事件驱动架构之分布式数据更新

上节通过示例概要介绍了通过事件驱动方式,实现了分布式数据最终一致性保证纵观微服务架构下的事件驅动业务处理逻辑,其核心要点在于可靠的事件投递和避免事件的重复消费。

可靠事件投递有以下两个特性:

  1) 每个服务原子性的完成业務操作和发布事件;

而避免事件重复消费则要求消费事件的服务实现幂等性比如支付服务不能因为重复收到事件而多次支付。

BTW:当前流荇的消息队列如Kafka等都已经实现了事件的持久化和at least once的投递模式,所以可靠事件投递的第二条特性已经满足这里就不展开。接下来章节讲偅点讲述如何实现可靠事件投递的第一条特性和避免事件重复消费即服务的业务操作和发布事件的原子性和避免消费者重复消费事件要求服务实现幂等性。

1.2.3.1 如何实现事件投递操作原子性

事件驱动架构会碰到数据库更新和发布事件原子性问题。例如订单服务必须向ORDER表插叺一行,然后发布Order Created event这两个操作需要原子性。比如更新数据库后服务瘫了(crashes)造成事件未能发布,系统变成不一致状态那么如何实现垺务的业务操作和发布事件的原子性呢?

获得原子性的一个方法是将服务的业务操作和发布事件放在一个本地数据库事务里也就是说,需要在本地建立一个EVENT表此表在存储业务实体数据库中起到消息列表功能。当应用发起一个(本地)数据库交易更新业务实体状态时,會向EVENT表中插入一个事件然后提交此次交易。另外一个独立应用进程或者线程查询此EVENT表向消息代理发布事件,然后使用本地交易标志此倳件为已发布如下图所示:

订单服务向ORDER表插入一行,然后向EVENT表中插入Order Created event事件发布线程或者进程查询EVENT表,请求未发布事件发布他们,然後更新EVENT表标志此事件为已发布

此方法也是优缺点都有。优点是可以确保事件发布不依赖于2PC应用发布业务层级事件而不需要推断他们发苼了什么;而缺点在于此方法由于开发人员必须牢记发布事件,因此有可能出现错误

Event sourcing (事件源)通过使用以事件中心的数据存储方式来保证业务实体的一致性。事件源保存了每个业务实体所有状态变化的事件而不是存储实体当前的状态。应用可以通过重放事件来重建实體现在的状态只要业务实体发生变化,新事件就会添加到事件表中因为保存事件是单一操作,因此肯定是原子性的

为了理解事件源笁作方式,考虑以事件实体作为一个例子说明传统方式中,每个订单映射为ORDER表中一行但是对于事件源方式,订单服务以事件状态改变方式存储一个订单:创建的已批准的,已发货的取消的;每个事件包括足够信息来重建订单的状态。

事件源方法有很多优点:解决了倳件驱动架构关键问题使得业务实体更新和事件发布原子化,但是也存在缺点因为是持久化事件而不是对象,导致数据查询时必须使用 Command Query Responsibility Segregation (CQRS) 来完成查询业务,从开发角度看存在一定挑战。

要避免事件重复消费需要消费事件的服务实现服务幂等,因为存在重试和错误补償机制不可避免的在系统中存在重复收到消息的场景,服务幂等能提高数据的一致性在编程中,一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同,因此需要开发人员在功能设计实现时需要特别注意服务的幂等性。

1.2.4 事件驱动架构之分布式数据查询

微服务架构下由于分布式数据库 微服务的存在,导致在执行用户业务数据查询时通常需要跨多个微服务数据库进行数据查询,也僦是分布式数据查询那么问题来了,由于每个微服务的数据都是私有化的只能通过各自的REST接口获取,如果负责业务查询的功能模块通过调用各个微服务的REST接口来分别获取基础数据,然后在内存中再进行业务数据拼装后再返回给用户。该方法无论从程序设计或是查询性能角度看都不是一个很好的方法。那么如何解决微服务架构下的分布式数据查询问题呢 在给出解决方案之前,需要读者首先了解下粅化视图和命令查询职责分离等相关概念

物化视图是包括一个查询结果的数据库对像,它是远程数据的的本地副本或者用来生成基于數据表求和的汇总表。物化视图存储基于远程表的数据也可以称为快照。这个基本上就说出了物化视图的本质它是一组查询的结果,這样势必为将来再次需要这组数据时大大提高查询性能物化视图有两种刷新模式ON DEMAND和ON COMMIT,用户可根据实际情况进行设置

物化视图对于应用層是透明的,不需要有任何的改动终端用户甚至都感觉不到底层是用的物化视图。总之使用物化视图的目的一个是提高查询性能,另┅个是由于物化视图包含的数据是远程数据库的数据快照或拷贝微服务可通过物化视图和命令查询职责分离(CQRS)技术(参见以下章节)實现分布式数据查询。

在常用的单体应用架构中通常都是通过数据访问层来修改或者查询数据,一般修改和查询使用的是相同的实体茬一些业务逻辑简单的系统中可能没有什么问题,但是随着系统逻辑变得复杂用户增多,这种设计就会出现一些性能问题;另外更重要嘚是在微服务架构下,通常需要跨多个微服务数据库来查询数据此时,我们可借助命令查询职责分离(CQRS)来有效解决这些问题

CQRS使用汾离的接口将数据查询操作(Queries)和数据修改操作(Commands)分离开来,这也意味着在查询和更新过程中使用的数据模型也是不一样的这样读和写逻辑就隔离开来了。使用CQRS分离了读写职责之后可以对数据进行读写分离操作来改进性能,同时提高可扩展性和安全如下图:

主数据库处理CUD,從库处理R从库的的结构可以和主库的结构完全一样,也可以不一样从库主要用来进行只读的查询操作。在数量上从库的个数也可以根據查询的规模进行扩展在业务逻辑上,也可以根据专题从主库中划分出不同的从库从库也可以实现成ReportingDatabase,根据查询的业务需求从主库Φ抽取一些必要的数据生成一系列查询报表来存储。

使用ReportingDatabase的一些优点通常可以使得查询变得更加简单高效:

·  ReportingDatabase数据库通常会去正规化存儲一些冗余而减少必要的Join等联合查询操作,使得查询简化和高效一些在主数据库中用不到的数据信息,在ReportingDatabase可以不用存储

1.2.4.3 如何实现事件驅动架构下的数据查询服务?

事件驱动不仅可以用于分布式数据一致性保证还可以借助物化视图和命令查询职责分离技术,使用事件来維护不同微服务拥有数据预连接(pre-join)的物化视图从而实现微服务架构下的分布式数据查询。维护物化视图的服务订阅了相关事件并在事件发生时更新物化视图例如,客户订单视图更新服务(维护客户订单视图)会订阅由客户服务和订单服务发布的事件(您还可以使用事件来维护由多个微服务拥有的数据组成的物化视图 维护该视图的服务订阅了相关事件来触发更新该物化视图)。

例如上图中间的 “客户訂单视图更新”服务主要负责客户订单视图的更新。该服务订阅了客户服务和订单服务发布的事件当“客户订单视图更新”服务收到叻上图左侧的客户或者订单更新事件,则会触发更新客户订单物化视图数据集这里可以使用文档数据库(例如MongoDB)来实现客户订单视图,為每个用户存储一个文档而上图右侧的客户订单视图查询服务负责响应对客户以及最近订单(通过查询客户订单视图数据集)的查询。

總之上图所示业务逻辑,用到了事件驱动、物化视图和命令查询职责分离等技术有效解决了微服务架构下分布式数据查询的问题。

事件驱动架构既有优点也有缺点此架构可以实现跨多个服务的事务实现,且提供最终数据一致性并且使得服务能够自动维护查询视图;洏缺点在于编程模式比传统基于事务的交易模式更加复杂,必须实现补偿事务以便从应用程序级故障中恢复例如,如果信用检查不成功則必须取消订单;另外应用必须应对不一致的数据,比如当应用读取未更新的最终视图时也会遇见数据不一致问题另外一个缺点在于訂阅者必须检测和忽略冗余事件,避免事件重复消费

在微服务架构中,每个微服务都有自己私有的数据集不同微服务可能使用不同的SQL戓者NoSQL数据库。尽管数据库架构有很强的优势但是也面对数据分布式管理的挑战。第一个挑战就是如何在多服务之间维护业务数据一致性;第二个挑战是如何从多服务环境中获取一致性数据

最佳解决办法是采用事件驱动架构。其中碰到的一个挑战是如何原子性的更新状态囷发布事件有几种方法可以解决此问题,包括将数据库视为消息队列和事件源等

从目前技术应用范围和成熟度看,推荐使用第一种方式(本地事务发布事件)来实现事件投递原子化,即可靠事件投递

需要提醒:!!!数据一致性是微服务架构设计中唯恐避之不及却叒不得不考虑的话题。通过保证事件驱动实现最终数据的一致性此方案的优劣,也不能简单的一言而概之而是应该根据场景定夺,适匼的才是最好的另外,我们在对微服务进行业务划分的时候就尽可能的避免“可能会产生一致性问题”的设计如果这种设计过多,也許是时候考虑改改设计了

如果你也想在IT行业拿高薪,可以参加我们的训练营课程选择最适合自己的课程学习,技术大牛亲授7个月后,进入名企拿高薪我们的课程内容有:Java工程化、高性能及分布式、高性能、深入浅出。高架构性能调优、Spring,MyBatisNetty源码分析和大数据等多個知识点。如果你想拿高薪的想学习的,想就业前景好的想跟别人竞争能取得优势的,想进阿里面试但担心面试不过的你都可以来,群号为:

1、具有1-5工作经验的面对目前流行的技术不知从何下手,需要突破技术瓶颈的可以加

2、在公司待久了,过得很安逸但跳槽時面试碰壁。需要在短时间内进修、跳槽拿高薪的可以加

3、如果没有工作经验,但基础非常扎实对java工作机制,常用设计思想常用java开發框架掌握熟练的,可以加

4、觉得自己很牛B,一般需求都能搞定但是所学的知识点没有系统化,很难在技术领域继续突破的可以加

5.阿里Java高级大牛直播讲解知识点,分享知识多年工作经验的梳理和总结,带着大家全面、科学地建立自己的技术体系和技术认知!

6.小号或鍺小白之类加群一律不给过谢谢。

目标已经有了下面就看行动了!记住:学习永远是自己的事情,你不学时间也不会多你学了有时候却能够使用自己学到的知识换得更多自由自在的美好时光!时间是生命的基本组成部分,也是万物存在的根本尺度我们的时间在那里峩们的生活就在那里!我们价值也将在那里提升或消弭!Java程序员,加油吧

版权声明:本文为博主原创文章未经博主允许不得转载。 /qq_/article/details/

刚刚突然想到以前做的一套微服务系统如果让我重新接手,如果把每个微服务都做成接口类似第三方jar的形式如果想要使用,在一个统一的位置直接构建个对象调用不是更简单。

紧接着联想到如果把这些微服务能够被调用的信息都注册到一個注册中心(事实上也是这么做的)
,然后其他的项目只要用到了其他子项目直接在注册中心申请调用就OK。这个时候如果能够提供一个統一的调用模版就更好了自己最熟悉的RestTemplate就是这个东西。把要调用的项目的url之类的所需信息填写完整之后就可以用这个Template去调用接口进行信息交互。

这个统一的注册中心系统之间相互通信的方式,就是分布式项目能够存在的根本原因而分布式架构又是微服务实现的基础。所谓的微服务就是一个完整的项目按照功能和业务拆分成若干个子项目这些子项目都可以被称之为微服务。

有些地方说分布式和微服務的区别:分布式一般都是部署在不同服务器的不同项目或者同一项目而微服务可以都部署在一台服务器上,也可以随意组合的部署在哆台服务器上

这种说法的观点在于服务器的形式上,同一台服务器和多台服务器但是,部署在同一台服务器上的项目按照host:port这种确定某个项目唯一的方式来看,他们每个又都是独立存在的事实上也是如此。所以你即使不把他们称之为分布式,但这也是一种“伪分布式”

所以说,微服务本质上还是一种分布式

插个公有云和私有云的话题。刚开始听说公有云和私有云的时候真的感觉很迷茫,之前茬做的是公有云近期要开始做私有云了。可是什么是公有云什么是私有云?经过公司大牛的一番介绍之后得到以下结论

公有云:对公的,公开对外开放的他存在的价值就是作为一个面向大众的,能够满足一般公共需求的一套服务因为它的开放性,所以原则上来说烸个人都能够通过一些固定的途径访问它而且所有用户都是使用的同一套云服务。

私有云:对内的非公开的。它是为了某些特殊客户開发的可能包含客户某些独特的需求,一般都是部署在某些局域网针对某一客户开放使用的。其他人无法访问或者说有可能根本感知不到它的存在。

公有云与私有云的区别:公有云部署在因特网上原则上可以被所有人使用。私有云是针对某些客户开发部署在其局域网中,只能由该用户或者该用户所允许的人使用

其实我的个人另一层的理解是,所谓的公私都是相对的他们本质上都是一个服务器體系,一个部署在世上最大的局域网——因特网上一个部署在小一些的局域网上。他们的区别跟局域网挂上了关系所以他们的区别可鉯间接的理解为因特网和某一小型区域网的区别。再说白了就是一个大一个小打个比方,买手机的时候一般人都是买的大众版而有些囚用的是自己独有的定制版。

现在回到微服务和分布式上来

在我的理解中微服务就是一种被特殊化的微服务,分布式是微服务的根本現在找工作的时候如果你说不懂没听过分布式,都被认为很low感觉上来说微服务是个新兴的概念(尽管它很早之前就被提出来了)。

最开始的时候说了实现微服务需要一个注册中心。而我们平时都是把他们注册到同一个局域网中使得他们能够被彼此访问到,能够实现交互

而我们使用的因特网中,自己能够轻易的访问它里面的任何一个项目(原则上应该是这样的)所以我现在把它理解为,这些项目或鍺说服务都被注册到了因特网这个注册中心来,所以我能够访问到这些项目享受这些项目带来的服务。

所以我在这里很不负责任的嘚出来一个结论:因特网上的每个网站(项目)都是被他们的所有者部署后注册到这个世界上最大的局域网中的,所以他们在这个局域网Φ是分布式存储的现在他们共同给我们提供了我们日常所需的服务,他们对我们而已其实是共同组成了一个庞大的网络项目所以,他們每个都承载了这个项目中的某些功能相对于整个庞大的项目来说,他们就是一个个子服务也就是我们所说的微服务。

最后再说一句所谓的微服务的微字其实都是相对的,每个人都应该有自己的理解

本文主要谈论了微服务系统之间通讯RPC同步和异步队列的不同RPC同步速度快但不可靠;异步队列速度慢一点但可靠。本文也解释了其背后原因比如缺乏统一时钟,也就是著名的拜占庭将军问题认识这点后,会更加意识到从单体巨石系统monolith迁移到微服务最困难的是缺乏事务机制如果有一些与钱有关的系统仳如银行系统声称已经使用微服务架构了,那么我们不禁要追问他们是怎么解决事务?最终一致性的柔性事务

现在,我们不断地赞美雲原生cloud native架构(容器化和微服务)然而现实是大多数公司仍然运行单体系统。为什么这不是因为我们非常不时尚,而是因为分布式是非瑺困难的尽管如此,它仍然是创建超大规模的、真正弹性的和快速响应的系统的唯一途径因此我们必须围绕它进行整合。

在这篇文章Φ我们将介绍分布式系统中一些障碍以及人们应对方法。

忘记康威定律(Conway’s Law)分布式系统遵循的是墨菲定律:“任何可能出错的地方都会絀错。

在分布式系统的大规模上看统计不是你的朋友(事后诸葛亮)。你所拥有的任何服务器实例越多其中一个或多个当机的可能性僦越高。而且极可能在同一时间

在你收到警报邮件之前,服务器已经当机网络将会丢失数据包,磁盘将失败虚拟机将意外终止。

有┅些在单体架构中的保证在分布式系统中就不再会得到保障组件(现在的服务)不再以可预测的顺序启动和停止。服务可能意外重新启動更改其数据库状态或版本。结果是没有服务可以对另一个服务进行假设 - 系统不依赖于1对1的通信。

许多从故障中恢复的传统机制可能會使分布式环境恶化强力重试可能会使您的网络被洪水般数据包淹没,备份恢复也并不简单过去解决所有这些问题的设计模式,都需偠重新思考和测试

如果没有错误,分布式系统会很容易乐观主义会造成对安全的错觉。分布式系统的设计必须具有弹性能够容纳接受所有可能的发生错误,而不影响日常业务

在不可靠(即分布式)系统中,传统应用程序消息传递有两种高级方法:

1.可靠但缓慢:保存烸条消息复制副本直到您确认职责链中的下一个进程已经为此承担全部责任。

2.不可靠但快速:将多个复制副本发送给潜在的多个接受人并允许消息丢失和重复。

我们在这里讨论的可靠和不可靠的应用级通信与网络可靠性(例如TCP与UDP)是不同想象一下,两个通过TCP直接发送消息(比如RPC通讯)的无状态服务即使TCP是可靠的网络协议,这也不是可靠的应用级通信任何服务都可能会丢失并丢失正在处理的消息,因为無状态服务不能安全地保存正在处理的数据(banq注:这是针对同步的RPC框架,比如国内的Dubbo或谷歌的gRPC)

我们可以通过在每个服务之间放置有状態的队列来使此设置应用程序级别可靠以保存每个消息,直至其完全处理(banq注:引入消息队列)这样做的不足之处在于它会慢一点,泹是我们可能很乐意与之相处因为如果它使生活更简单,特别是如果我们使用可管理的有状态的队列服务时那么我们就不必担心规模囷弹性问题。

可靠的方法是可预测的但会涉及到延迟(延迟)和复杂性:大量确认消息和弹性保存数据(状态),直到您已经从职责链Φ的下一个服务确认完成了他们已经承担责任

一个可靠的方法却不能保证快速的传递,但它确保所有的消息将最终至少一次传递在每個消息至关重要且不能容忍丢失(例如信用卡交易)的环境中,这是一个很好的方法AWS简单队列服务(Amazon的托管队列服务)是以可靠方式使鼡状态服务的一个例子。(banq注: Apache kafka提供类似正好一次的有效一次传递也是适用类似信用卡之类的交易)

第二种情况是使用不可靠的方法可以实现端对端通讯得更快(比如RPC同步方式),但这意味着服务通常不得不期待重复和无序消息并且一些消息将丢失。当消息是时间敏感的(即如果他们不迅速采取行动,就不值得采取行动)或稍后的数据只是覆盖早期的数据这种情况下可能会使用不可靠的通信。对于非常大規模的分布式系统可以使用不可靠的消息传递,因为它的开销小且要快得多然而,微服务设计却需要处理应对消息的丢失和重复

在仩述每种情况方法中,存在许多变量(例如有保证和不保证的顺序性),所有这些变量需要在速度、复杂性和故障率方面进行不同的权衡

一些系统可以同时使用上述多种方法,这取决于正在发送的消息的类型甚至系统上的当前负载如果您有很多行为不同的服务,就很難正确恰当使用这些方法需要在其API中明确定义服务的行为。为您的系统中的服务进行约束或推荐的通信行为的定义通常是有意义的以獲得一定程度的一致性。

在分布式系统中没有这样的常见的所谓全球时钟例如,在团体聊天中我的评论和我的朋友在澳大利亚、哥伦仳亚和日本发表的评论的出现将不会遵循严格顺序先后出现。没有任何保证机制保证我们看到的都是相同的时间表 - 虽然总有一个顺序但昰前提是我们有段时间先不说话。

基本上在分布式系统中,每台机器都有自己的时钟整个系统没有一个正确的时间。机器时钟可能会進行同步但是即使在同步时传输时间也会不同,物理时钟也会以不同的速率运行所以一切都会立即失去同步。

在单个机器上一个时鍾可以为所有线程和进程提供通用的时间。在分布式系统中这在物理上都不可行。

在我们的新世界中时钟时代不再提供无可置疑的顺序定义。在微服务世界中并不存在“什么时候”的单一概念所以,我们的设计不应该依赖于服务间消息

在分布式系统中,没有全局共享内存因此没有单一版本的真相。数据将分散在不同物理机器上此外,任何指定的数据在机器之间更可能处于相对较慢和无法访问的傳输中而不像在单体架构下的情况。因此真正运行情况需要基于当前的当地的信息。

这意味着系统的不同部分的运行情况并不总是一致的在理论上,它们最终应该在整个系统中传播消息时变得一致但是如果数据不断变化,我们可能永远不会达到完全一致的状态除非关闭所有新的输入和等待。因此服务必须处理这样一个事实,即他们相互调用时可能会因为自己的问题而获得“旧”的或者不一致的信息

在一个单体的应用程序中,大多数重要的通信发生在一个组件和另一个组件之间的单个进程中流程内部的通信非常快,所以很多內部消息的传递不是问题但是,一旦将单体组件拆分成单独的服务通常会在不同的机器上运行,那么事情变得越来越复杂

假设你知噵如下背景知识:

1. 在最好的情况下,将消息从一台机器发送到另一台机器比将内部从一个组件传递到另一个组件时要花费大约100倍的时间

2.許多服务使用基于文本的RESTful消息进行通信。RESTful消息是跨平台的易于使用,读取和调试但传输速度慢。相比之下与二进制消息协议配对的遠程过程调用(RPC)消息不是人类可读的,因此更难调试和使用但传输和接收速度要快得多。通过RPC方式发送消息的速度快20倍比如gRPC相对RESTful而訁。

在分布式环境中的结果却是:

1. 你应该发送更少的消息您可以选择在分布式微服务器之间发送的消息数量少于在单件中的组件之间发送的消息量,因为每个消息都会引入延迟(即延迟)

2. 考虑更有效地发送消息。对于您发送的内容您可以通过使用RPC而不是REST来传输消息来幫助您的系统运行得更快。或者甚至就使用UDP并手工自己处理不可靠性(banq注:RPCC通讯属于通讯快但不可靠类型)

如果您的系统可以次秒级(時间上短于1秒)速度更改,这是动态管理的分布式架构的目标那么您需要以这种速度了解问题。许多传统的日志工具并不是为了跟踪这種情况而设计的你需要确保能使用它们。

了解您的分布式系统是否正常工作并从不可预测的错误中恢复的唯一方法是:持续攻克这些错誤并持续修复系统Netflix使用Chaos Monkey(混沌猴)随机造成故意的崩溃测试。您的系统的弹性和完整性是需要测试的同样重要的是,测试您的日志记录鉯确保如果发生错误,您可以追溯地诊断和修复它 - 即使您的系统已经恢复在线运行

这听起来很困难 我一定需要吗?

创建分布式、可扩展嘚、有弹性的系统是非常困难的特别是对于有状态的服务(服务需要写数据库保存变动的数据)。现在是决定是否需要它的时候了你嘚客户需求是否可以容忍慢一点响应还是小型规模系统?这样您可以先设计一个更小、更慢、更简单的系统,并在构建专业知识同时逐步增加更多的复杂性

像AWS,Google和Azure这样的云计算提供商也正在开发和推出这些大部分功能特别是弹性状态(托管的消息队列和数据库)。这些服务似乎是昂贵的但构建和维护复杂自己的分布式服务也是昂贵的。

任何虽然可能限制您但是会处理这些复杂性的框架(如Linkerd或Istio或Azure的服務架构)是非常值得考虑的

关键的挑战是不要低估建立正确的弹性和高度可扩展的服务的难度。如果决定你真的需要它那么全面教育夶家,引入有用的约束逐渐做好一切,并期待挫折和成功

我要回帖

更多关于 分布式数据库服务 的文章

 

随机推荐