分布式和集群相关的东西,已经是未来系统发展的趋势。

分布式

为什么会有分布式?

  • 可以很好的减少依赖(每个服务都只要开发测试自己的逻辑数据)
  • 可以简单的进行扩展,(分布式存储这种)
  • 能够很简单的支持高可用(负载均衡到多实例)
  • 容错性(将数据以备份的信息存储多分)

单系统

单块系统就是所有的代码都在一个工程里,最多可能就是通过maven等构件工具拆分了一下代码工程模块,不同的模块可以放在不同的工程代码里。

很多流量很小的企业内部系统,比如OA、CRM、财务等系统,甚至可能就直接在一台机器的tomcat下部署一下。

然后直接配置一下域名解析,就可以让这个系统的可能几十个,或者几百个用户通过访问域名来使用这个软件了。

你哪怕就部署一台机器,这个系统也可以运行,只不过为了所谓的“高可用”,可能一般会部署两台机器,前面加一层负载均衡设备,这样其中一个机器挂了,另外一个机器上还有一个系统可以用。

分布式系统

分布式的主要特点就是分而治之,实现解耦,高性能的解决问题。比如把一个大的系统拆分为很多小的系统,甚至很多小的服务,然后几个人组成一个小组就专门维护其中一个小系统,或者每个人维护一个小服务。这样就可以分而治之,这样每个人可以专注维护自己的代码。不同的子系统之间,就是通过接口互相来回调用,每个子系统都有自己的数据库。

下面是一些应用,都是采用了分布式的思想。

  • 比如在load balance后面的web server,就是一种基本的分布式处理请求的模式,他可以并行处理请求,提高响应效率,也就提高了性能
  • 比如hadoop中的hdfs它就是在不同节点上存储不同的数据,这就是一种扩大容量的分布式存储。一份数据三副本也实现分布式的数据存储,实现来分布式数据的容错能力
  • 比如redis在不同的节点上分布不同的slot来完成分布式的存储。但是每个实例的m/s的最终一致性也实现分布式的数据容错能力。
  • 比如etcd的分布式存储,实现强一致性,在各个节点的数据时刻一致,实现高可用。
  • 比如ceph一样实现各个节点上数据一致的分布式共享。

这些都是分布式的应用,分布式只是一种可以使不同资源共同去完成一个目标的方法。分布式让不同的节点完成着不同的或者相同的任务,来提高能力,可以是计算,可以是存储,可以是容错。其实分布式更多的是一种思想。当然这种思想可以实现不同的事情,比如上面提到的,提高性能,提高存储能力,提高可用能力,提高容错能力,实现数据共享等等。

通过分布式思想实现的系统,也就是我们常说的分布式系统,分布式系统相对于单系统来说,更加的复杂,很多传统的问题都需要分布式的解决方案。

分布式系统所带来的技术问题

那么大家这个时候可以思考一下,如果你的公司是采用这种分布式系统的方式来构建公司的一个大规模系统的,那么这个时候会涉及到哪些技术问题?

分布式服务框架

你如果要让不同的子系统或者服务之间互相通信,首先必须有一套分布式服务框架。主要是做服务发现和服务间通信,也就是各个服务可以互相感知到对方在哪里,可以发送请求过去,可以通过HTTP或者RPC的方式。最常见的技术就是dubbo以及spring cloud,当然大厂一般都是自己有服务框架。基本上在这个领域目前还是阿里的java写框架一家独大, 我所使用的c/c++,golang都是使用标准库自己来实现这些服务发现通信的问题,所以也没有什么比较好的框架。目前在容器领域,随着k8s的模式的趋势发展,下一代的分布式框架开始衍生,出现了k8s的相关解决方案-微服务

分布式事务

一旦你的系统拆分为了多个子系统之后,那么一个贯穿全局的分布式事务应该怎么来实现?

这个你需要了解TCC、最终一致性、2PC等分布式事务的实现方案和开源技术

分布式锁

不同的系统之间如果需要在全局加锁获取某个资源的锁定,此时应该怎么来做?毕竟大家不是在一个JVM里了,不可能用synchronized来在多个子系统之间实现锁吧,是不是?

所以这个时候就需要使用分布式锁来解决这些问题。

分布式存储

如果你原来就是个单块系统,那么你其实是可以在单个JVM里进行本地缓存就可以了,比如搞一个HashMap来缓存一些数据。但是现在你有很多个子系统,他们如果要共享一个缓存,你应该怎么办?是不是需要引入Redis等缓存系统,实现数据缓存共享。

还有很多的数据共享存储的实例,我们都需要使用到分布式存储

分布式消息系统

在单块系统内,就一个JVM进程内部,你可以用类似LinkedList之类的数据结构作为一个本地内存里的队列。

但是多个子系统之间要进行消息队列的传递呢?那是不是要引入类似RabbitMQ之类的分布式消息队列中间件

分布式搜索系统

如果在单块系统内,你可以比如在本地就基于Lucene(支持全文索引的数据库系统)来开发一个全文检索模块,但是如果是分布式系统下的很多子系统,你还能直接基于Lucene吗?

明显不行,你需要在系统里引入一个外部的分布式搜索系统,比如Elasticsearch

其他很多的技术

比如说分布式配置中心、分布式日志中心、分布式监控告警中心、分布式会话,等等,都是分布式系统场景下你需要使用和了解的一些技术。

一致性问题

一致性问题其实也是分布式事务中的,但是这个问题比较突出,单独说一下,一致性又可以分为强一致性与弱一致性。

强一致性可以理解为在任意时刻,所有节点中的数据是一样的。同一时间点,你在节点A中获取到key1的值与在节点B中获取到key1的值应该都是一样的。

弱一致性包含很多种不同的实现,目前分布式系统中广泛实现的是最终一致性。所谓最终一致性,就是不保证在任意时刻任意节点上的同一份数据都是相同的,但是随着时间的迁移,不同节点上的同一份数据总是在向趋同的方向变化。也可以简单的理解为在一段时间后,节点间的数据会最终达到一致状态。

所以对于一致性,一致的程度不同大体可以分为强、弱、最终一致性三类。

  • 强一致性 对于关系型数据库,要求更新过的数据能被后续的访问都能看到,这是强一致性。比如小明更新V0到V1,那么小华读取的时候也应该是V1。
  • 弱一致性 如果能容忍后续的部分或者全部访问不到,则是弱一致性。比如小明更新VO到V1,可以容忍那么小华读取的时候是V0。
  • 最终一致性 如果经过一段时间后要求能访问到更新后的数据,则是最终一致性。比如小明更新VO到V1,可以使得小华在一段时间之后读取的时候是V0。

分布式的难点是一致性,基本解决方案

CAP理论

CAP理论指的是一个分布式系统最多只能同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance)这三项中的两项。其中分区容错性(Partition tolerance)是分布式的根本,是必须要实现的,所以一般都是实现AP和CP。

  • Consistency (一致性): “all nodes see the same data at the same time”,即更新操作成功并返回客户端后,所有节点在同一时间的数据完全一致,这就是分布式的一致性。一致性的问题在并发系统中不可避免,对于客户端来说,一致性指的是并发访问时更新过的数据如何获取的问题。从服务端来看,则是更新如何复制分布到整个系统,以保证数据最终一致。
  • Availability (可用性): 可用性指“Reads and writes always succeed”,即服务一直可用,而且是正常响应时间。好的可用性主要是指系统能够很好的为用户服务,不出现用户操作失败或者访问超时等用户体验不好的情况。
  • Partition Tolerance (分区容错性): 即分布式系统在遇到某节点或网络分区故障的时候,仍然能够对外提供满足一致性或可用性的服务。这个是必须要保障的,不然都没有分布式的意义了。 分区容错性要求能够使应用虽然是一个分布式系统,而看上去却好像是在一个可以运转正常的整体。比如现在的分布式系统中有某一个或者几个机器宕掉了,其他剩下的机器还能够正常运转满足系统需求,对于用户而言并没有什么体验上的影响。

实例

假设N1和N2之间通信的时候网络突然出现故障,有用户向N1发送数据更新请求,那N1中的数据DB0将被更新为DB1,由于网络是断开的,N2中的数据库仍旧是DB0;

如果这个时候,有用户向N2发送数据读取请求,由于数据还没有进行同步,应用程序没办法立即给用户返回最新的数据DB1,怎么办呢?有二种选择,第一,牺牲数据一致性,响应旧的数据DB0给用户;第二,牺牲可用性,阻塞等待,直到网络连接恢复,数据更新操作完成之后,再给用户响应最新的数据DB1。

上面的过程比较简单,但也说明了要满足分区容错性的分布式系统,只能在一致性和可用性两者中,选择其中一个。也就是说分布式系统不可能同时满足三个特性。这就需要我们在搭建系统时进行取舍了

我们分析一下既然可以满足两个,那么舍弃哪一个比较好呢?

(1)满足CA舍弃P,也就是满足一致性和可用性,舍弃容错性。但是这也就意味着你的系统不是分布式的了,因为涉及分布式的想法就是把功能分开,部署到不同的机器上。但放弃P的同时也就意味着放弃了系统的扩展性,也就是分布式节点受限,没办法部署子节点,这是违背分布式系统设计的初衷的。

(2)满足CP舍弃A,也就是满足一致性和容错性,舍弃可用性。如果你的系统允许有段时间的访问失效等问题,这个是可以满足的。就好比多个人并发买票,后台网络出现故障,你买的时候系统就崩溃了。设计成CP的系统其实不少,最典型的就是分布式数据库,如Redis、HBase等。对于这些分布式数据库来说,数据的一致性是最基本的要求,因为如果连这个标准都达不到,那么直接采用关系型数据库就好,没必要再浪费资源来部署分布式数据库。

(3)满足AP舍弃C,也就是满足可用性和容错性,舍弃一致性。这也就是意味着你的系统在并发访问的时候可能会出现数据不一致的情况。典型的应用就如某米的抢购手机场景,可能前几秒你浏览商品的时候页面提示是有库存的,当你选择完商品准备下单的时候,系统提示你下单失败,商品已售完。这其实就是先在 A(可用性)方面保证系统可以正常的服务,然后在数据的一致性方面做了些牺牲,虽然多少会影响一些用户体验,但也不至于造成用户购物流程的严重阻塞。

实时证明,大多数都是牺牲了一致性。像12306还有淘宝网,就好比是你买火车票,本来你看到的是还有一张票,其实在这个时刻已经被买走了,你填好了信息准备买的时候发现系统提示你没票了。这就是牺牲了一致性。

所以在牺牲强一致性,使用最终一致性的情况下,eBay 架构师 Dan Pritchett 提出了 BASE 理论,用于解决大规模分布式系统下的数据一致性问题。

BASE 理论告诉我们:可以通过放弃系统在每个时刻的强一致性来换取系统的可扩展性。

BASE 是 Basically Available(基本可用)、Soft state(软状态)和 Eventually consistent (最终一致性)三个短语的缩写。是对CAP中AP的一个扩展

  • 基本可用:分布式系统在出现故障时,允许损失部分可用功能,保证核心功能可用。
  • 软状态:允许系统中存在中间状态,这个状态不影响系统可用性,这里指的是CAP中的不一致。
  • 最终一致:最终一致是指经过一段时间后,所有节点数据都将会达到一致。

但是不是说牺牲一致性一定是最好的。就好比mysql中的事务机制,张三给李四转了100块钱,这时候必须保证张三的账户上少了100,李四的账户多了100。因此需要数据的一致性,而且什么时候转钱都可以,也需要可用性。但是可以转钱失败是可以允许的。

分布式的发展

分布式是单机系统发展到一定时候的产物,其实和微服务的发展是一样的,微服务是分布式发展到一定阶段的概念,两者其实是差不多的,所以微服务的演进也是分布式的发展。

集群

集群就是集中一堆机器来一起做事。

比如上面的webserver可以是一个集群,他们互不干扰,共同的处理着同一种任务。前面的load balance也可以分布式部署,也可以是一个集群,后段的数据库也可以分布式部署,也可以是一个集群,这个几个集群组合在一起可以是一个大的集群。

比如hadoop中的hdfs也是一个集群,但是它们互相通信,能够知道各个节点的情况,同时由中心统一管理调度

比如上面的redis也是一个集群,他们也互相通信,却是存在着无中心化的管理

比如上面的etcd,ceph几个节点也是一个集群,要求节点上数据完全保持一致

这些都是集群,所以集群通俗点说就是一堆节点,当然都是相关的,不相关的不会组合在一起

所以说集群和分布式是不同的概念,好比“分头做事”和“一堆相关的人”。他们也是紧密相连的,由分布式一般都是集群,有集群一般都是分布式的。