分布式 分布式系统入门

1.分布式系统的意义

1.1 分布式系统产生的原因

  • 升级单机处理能力的性价比越来越低
  • 单机处理能力存在瓶颈
  • 出于稳定性和可用性的考虑

2.分布式系统的基础知识

2.1 组成计算机的五要素

分布式 分布式系统入门

如图所示,分别是输入和输出设备,运算器,控制器和存储器。其中存储器又分成了内存和外存,在计算机断电时内存中存储的数据会丢失,但是外存可以保持存储的数据。

2.2 线程和进程

2.2.1 Amadal定律

分布式 分布式系统入门

这个公式告诉我们,程序中可并行代码的比例决定增加处理器(总核心数)所能带来的速度提升的上限。
公式中的P指的是程序中可以并行运行部分的程序在单核上执行时间的占比,N表示处理器的个数(总核心数)。S(N)是指程序在N个处理器(总核心数)相对在单个处理器(单核)中的速度提升比。

当P=0.5时,可以算出速度提升上限就是2.如果P=0.2,速度提升上限就是1.25

2.2.2 互不通信的多线程模式

首先看不进行交互的模式,在多线程程序中,多个线程在系统中会并发执行。如果线程之间不需要处理共享的数据,也不用进行动作协调就会非常简单,也就是多个独立的线程各自完成自己线程中的工作。

分布式 分布式系统入门

2.2.3 基于共享容器协同的多线程模式

在需要多个线程之间对共享数据进行处理的场景下,例如生产者和消费者的例子,有一个队列用于生产和消费,那么这个队列就是多个线程会共享的一个容器或者是数据对象,多个线程会并发的访问这个队列

分布式 分布式系统入门

在多线程环境下对临界数据的访问,需要保证数据的一致性。对于存储数据的容器或者对象,有线程安全和不安全两种。

对于线程不安全的,可以通过加锁或者Copy On Write的方式来控制并发控制。使用加锁的方式时,如果数据的读写比例很高,一般会使用读写锁来优化。

对于线程安全的容器或者对象,可以直接在多线程的环境下使用,有些支持并发的类的效率会比直接加互斥锁的实现更好,最典型的就是JUC包下的类。

2.2.3 基于事件协同的多线程模式

除了并发访问的控制,线程间会存在着协调的需求,比如A,B两个线程,B到等到某个状态或者事件发生后才能继续工作,而这个状态或者事件和A线程有关,此时就需要线程间的协调。

如下图所示,右边线程在某个步骤时一直阻塞直到事件通知到达后才继续自己的执行。

需要注意的是要调整对多个锁的获取顺序,避免死锁。

分布式 分布式系统入门

2.2.4 多进程模式

多进程和多线程有相同和不同的地方。

1.对于之前多线程存在的问题,多进程也有类似的场景,只是具体的实现方式不同。
造成不同的最大原因是:线程是属于进程的,一个进程内的多个线程共享了进行的内存空间。而多个之间的内存空间是独立的,因此多个进程间通过内存共享、交换数据的方式和多线程不同。
此外,进程间的通信,协调,事件通知和互斥锁的应用和多线程也不一样。

2.多进程比单进程和多线程来说,资源控制会更容易实现。

3.多进程中单个进程的问题,不会造成整体的不可用。

4。多进程比多线程复杂,可以共享数据,但是代价比多线程高(涉及到序列化和反序列化的开销)。

3.网络通信基础知识

在分布式系统中,组件分布在网络上的多个节点中,通过消息的传递来通信并且进行动作的协调,因此网络通信在分布式系统中非常重要。

3.1 OSI和TCP/IP网络模型

分布式 分布式系统入门

分布式 分布式系统入门

每层的应用之前有博客总结归纳了 OSI 七层模型详解

3.2 网络IO实现方式

实践中接触比较多的网络模型主要是以太网和TCP/IP协议栈,UDP在一些场景中也会用到。下面介绍三种使用Socket套接字进行网络通信开发的实现方式

3.2.1 BIO方式

BIO:Blocking IO 采用阻塞的方式实现,一个Socket套接字需要一个进程来处理。在建立连接、读数据、写数据的时候,都可能会产生阻塞。好处就是简单咯~

可能出现的问题就是,由于一个线程只处理一个Socket,那么在服务器端就会产生很多线程。这块一般使用线程池来优化

分布式 分布式系统入门

3.2.2 NIO方式

NIO:Nonblocking IO 基于事件驱动思想,采用的是Reactor模式。这种方式在服务端使用的比较多,好处是不需要为每个Socket套接字分配一个线程,可以在一个线程中处理多个套接字相关的工作。

分布式 分布式系统入门

Reactor会管理所有的Handler,把出现的事件交给相应的Handler去处理。

也就是通过Reactor对所有客户端的Socket套接字的事件做处理,然后派发到不同的线程中。

分布式 分布式系统入门

3.2.3 AIO方式

AIO:Asynchronous IO 异步IO 采用的是Proactor模式,在进行读写操作的时候,只要调用对应的read/write方法,并且需要传入CompletionHandler动作完成的处理器,动作完成之后,会调用CompletionHandler

分布式 分布式系统入门

AIO在JDK7才引入的,在NIO的一个最大区别就是,NIO在有通知时可以进行相关操作,而AIO在有通知时表示相关操作已经完成。

客户端和服务端使用的模型不要求一致,其他的区别见 JAVA BIO NIO和AIO的区别

4.如何把应用从单机扩展到分布式

从单机变化到分布式时,构成计算机的5个要素的变化。

4.1 输入设备的变化

分布式系统由通过网络连接的多个节点组成,输入设备分为:

  • 互相连接的多个节点。在接受其他节点传来的消息时,该节点可以看做是输入设备
  • 传统意义的人机交互的输入设备

4.2 输出设备的变化

也有两种

  • 系统中的节点在其他节点传递消息时,该节点可以看做是输出设备
  • 传统意义的人机交互的输出设备(用户屏幕)

4.3 控制器的变化

分布式系统是由多个节点通过网络连接在一起的,并通过消息的传递进行协调。控制器的主要作用就是协调或者控制节点之间的动作和行为。

第一种是使用硬件负载均衡的方式

分布式 分布式系统入门

在请求发起方和请求处理方中间有一个硬件负载均衡设备,所有的请求都要经过这个负载均衡设备来完成请求转发的控制。

第二种是使用LVS的方式

差别是中间的硬件负载均衡设备被替换成了LVS,主要特点是代价低,可控性强,可以相对自由的按照自己的需求去增加负载均衡的策略。

分布式 分布式系统入门

一般称这种方式为透明代理。在集群中,对于发起请求和处理请求的一方来说都是透明的。

发起请求的一方不用关心多少台机器提供服务,也不需要直接知道这些提供服务的机器的地址,只要知道中间透明代理的地址就可以了。但是不足的地方一个是会增加网络的开销(流量和延迟)。

流量方面:如果使用LVS的TUN或者DR模式,那么从处理请求的服务器上返回的结果会直接到请求服务的机器,不会再通过中间的代理,只有请求的数据包多了一次代理的转发。在请求数据包小返回结果数据包大的情况下区别不是很大,但是如果请求数据包很大的话,那么流量增加还是比较明显的。

另一个不足是如果代理出现问题,所有的请求就会收到影响,因此要考虑服务器的热备份。

第三种是采用名称服务的直连方式

分布式 分布式系统入门

和LVS区别是请求和处理之间不存在代理设备,而且请求方和处理方有一个直接的连接。在外部有一个”名称服务”的角色。主要是为了收集提供请求处理的服务器的地址信息和提供这个地址信息给请求发送方,只是起到地址交换的作用。原来在透明代理上做的工作被拆分到了名称服务和发起请求的机器上了。

优势首先是名称服务不是在请求的必经路径上,出现问题可以解决不影响,还有一个是因为是直连,减少了中间路径以及可能的额外带宽的消耗。

不足就是代码的升级会很复杂。

第四种是使用规则路由器控制路由的方式

分布式 分布式系统入门

在请求发起的机器上,会有对规则进行处理从而请求处理服务机器选择的代码逻辑。这个方式和名称服务的不同在于,名称服务是通过跟请求处理的机器交互来获得这些机器的地址的,而规则服务器本身并不和请求和请求处理的机器进行交互,只负责把规则提供给请求发起的机器。

第五种是Master+Worker的方式

分布式 分布式系统入门

存在一个Master节点来管理任务,由Master把任务分配给不同的Worker进行处理。

4.4 运算器的变化

在单机系统中,运算器是具体的电子元件。而在分布式系统中,运算器由多个节点组成。单机的运算能力有上限,而分布式系统中的运算器是运用多个节点的计算能力来协同完成整体的计算任务。

分布式 分布式系统入门

当压力增大时需要多台服务器

分布式 分布式系统入门

这是要解决的问题就是应该选择访问哪个服务器。

第一种方法是使用DNS服务器进行调度和控制。在用户解析DNS的时候就会被给予一个服务器的地址。

类似控制器部分的名称服务或者规则服务器的方式,中间没有代理设备,可以直接知道提供服务的服务器的方式。

分布式 分布式系统入门

另外一种方案添加了负载均衡设备,这样DNS返回的就是负载均衡设备的地址

分布式 分布式系统入门

举个栗子,日志的处理

分布式 分布式系统入门

使用一台日志处理器从多台服务器上收集日志并处理,当压力增大时,可以添加日志处理器的个数

分布式 分布式系统入门

分布式 分布式系统入门

使用规则服务器或者Master方式来解决,Master对任务分配处理的更好,不容易导致分配的不均衡。

4.4 存储器的变化

在分布式的环境中,需要把承担存储功能的多个节点组织在一起,使的看起来是一个存储器。一般也需要通过控制器的配合来完成工作

首先是单台的key-value场景,当数据量增大的时候,需要把一台服务器扩展到两台来提供服务。

第一种方案的使用代理服务器

代理服务器作为控制器来转发用应用服务器的请求,一般根据key来进行划分。

分布式 分布式系统入门

第二种方案是使用名称服务

名称服务器用于管理在线的KV存储服务器,并把地址传到应用服务器这边,应用服务器就会和KV存储服务器直接联系。

KV服务器的选择逻辑在应用服务器上完成,实践中有两种经验。

第一个是配合规则服务器,做固定的划分策略

第二个是对等看待多台KV服务器,灵活的使用KV存储服务器的增加和减少(消息中间件的应用)

分布式 分布式系统入门

第三种方案是规则服务器

规则服务器不仅写明了如何对数据做划分,还包含了具体的目标KV服务器的地址。

例如两台KV存储器,规定规则是用户编号为奇数的存在第一台,偶数保存在第二台,那么在服务器中就有规则来描述这个情况。

分布式 分布式系统入门

第四种方案使用Master控制KV服务器

Master根据请求返回目标KV存储服务器的地址,然后应用服务器直接访问对应的KV存储服务器。对比名称服务Master是返回对应的KV存储服务器的地址而不是所有地址。

分布式 分布式系统入门

5.分布式系统的难点

5.1 缺乏全局时钟

可以把这个工作交给一个单独的集群来完成,通过这个集群来完成多个动作的顺序。

5.2 面对故障独立性

5.3 处理单点故障

在分布式系统中,如果某个角色或者功能只有单台机器在支撑,那么这个节点称为单点,其发生故障称为单点故障,也就是SPoF(SIngle Point of Failure)

在系统中应该尽量避免单点,保证功能都是由集群来完成的,如果无法实现就得做好单点的备份和降低单点的影响范围。

5.4 事务的挑战

解决事务问题可以选择2PC,最终一致,BASE,CAP,Paxos等方法