一.分布式系统的介绍
1.1初识分布式系统
1.1.1 分布式的定义
一是组件分布在网络计算机上,二是组件之间仅仅通过消息传递来通信并协调行动。
分布式系统一定是由多个节点组成的系统,一般来说一个节点就是我们一台计算机;然后这些节点不是孤立的,而是互相连通的;最后这些连通的节点部署上了我们的组件,并且相互之间的操作会有协同。案例:我们通过浏览器去访问某一个网站,在对浏览器发出请求的背后是一个大型的分布式系统提供服务,整个系统中有的负责请求处理,有的负责存储,有的负责计算,最终通过相互的协同把我们的请求变成了最后的结果返回给浏览器,并呈现给我们。
1.1.2分布式系统的意义
使用分布式的原因:
*升级单机处理能力的性价比越来越低
*单机处理能力存在瓶颈
*出于稳定性和可用性的考虑
1.2分布式系统的基础知识
1.2.1组成计算机的5要素
组成计算机的基本元素:输入设备、输出设备、运算器、控制器和存储器(内存和外存)。计算机断电时,内存中存储的数据会丢失,而外存则仍然能够保持存储的数据。
1.2.2线程与进程的执行模式
在多线程开发中,我们需要处理线程间的通信,需要对线程并发做控制,需要做好线程间的协调工作。
1.2.2.1阿姆达尔定律
S(N)=1/[(1-P)+P/N] P指的是程序中可并行部分的程序在单核上执行时间的占比,N表示处理器的个数(总核心数)。S(N)是指程序在N个处理器(总核心数)相对在单个处理器中的速度提升比。
这个公式告诉我们,程序中可并行代码的比例决定你增加处理器所能带来的速度提升的上限,是否能达到这个上限,还取决于很多其他的因素。当P=0.5时,速度提升的上限就是2。如果P=0.25时,速度提升的上限就是1.25。
并行的代码比例越多,处理的速度提升上限越高,P跟S(N)成正比。
1.2.2.2互不通信的多线程模式
在多线程程序中,多个线程会在系统中并发执行。如果线程之间不需要处理共享的数据,也不需要进行动作协调,就是多个独立的线程各自完成自己线程中的工作。
1.2.2.3基于共享容器协同的多线程模式
多个线程之间对共享的数据进行处理。例如经典的生产者和消费者的例子,我们有一个队列用于生产和消费,那么,这个队列就是多个线程会共享的一个容器或者是数据对象,多个线程会并发地访问这个队列。多线程环境下对同一份数据的访问,我们需要有所保护和控制以保证访问的正确性。对于存储数据的容器或者对象,有线程安全和线程不安全之分,对于线程不安全的容器或对象,一般可以通过加锁或者通过Copy on Write的方式来控制并发访问。使用加锁方式时,如果数据在多线程中的读写比例很高,则一般会采用读写锁而非简单的互斥锁。JDK中的java.util.concurrent包中有很多这样的容器类。
1.2.2.4通过事件协同的多线程模式
线程间会存在着协调的需求,例如A、B两个线程,B线程需要等到某个状态或事件发生后才能继续自己的工作,而这个状态改变或者事件产生A线程相关。
事件协同会出现死锁的现象,能够原子性地获取需要的多个锁,或者注意调整对多个锁的获取顺序,就会比较好地避免死锁。
死锁现象:
T1
A.lock();
B.lock();
T2
B.lock();
A.lock();
T1等不到B,而T2也等不到A。
T1
A.lock();
B.lock();
T2
A.lock();
B.lock();
T2线程的获取锁的顺序发生变化,都是先获取A,再获取B,避免死锁。
1.2.3网络通信基础知识
在分布式系统中,组件分布在网络上的多个节点中,通过消息的传递来通信并且进行动作的协调。因此网络通信在分布式系统中非常重要。
1.2.3.1网络IO实现方式
1.BIO方式
BIO即Blocking IO,采用阻塞的方式实现。一个Socket套接字需要使用一个线程来进行处理。发生建立连接、读数据、写数据的操作时,都可能会阻塞。使得一个线程只处理一个Socket,如果是Server端,那么在支持并发的连接时,就需要更多线程来完成这个工作。
2.NIO方式
NIO即Nonblocking IO,基于事件驱动思想,采用的是Reactor模式。这在Java实现的服务端系统中也是采用比较多的一种方式。相对于BIO,NIO的好处是不需要为每个Socket套接字分配一个线程,而可以在一个线程处理多个Socket套接字相关的工作。
Reactor模式的工作方式,Reactor会管理所有的handler,并且把出现的事件交给相应的Handler处理。在NIO的方式下不是用单个线程去应对单个Socket套接字,而是统一通过Reactor对所有客户端的Socket套接字的事件做处理,然后派发到不同的线程中。
客户端——>反应堆(Reactor)[分布(wait/notify)方式]——>处理线程
3.AIO方式
AIO即AsynchronousIO,就是异步IO。AIO采用Proactor模式。AIO与NIO的差别是,AIO在进行读/写操作时,只需要调用相应的read/write方法,并且需要传入CompletionHandler(动作完成的处理器);
1.2.4如何把应用从单机扩展到分布式
1.2.4.1控制器的变化
分布式系统是由多个节点通过网络连接在一起并通过消息的传递进行协调的系统。控制器的作用就是协调或控制节点之间的动作和行为。
示例:请求发起方和请求处理方中间有一个硬件负载均衡设备。所有的请求都要经过这个负载均衡设备来完成请求转发的控制。
1.2.5分布式系统的难点
1.2.5.1 缺乏全局时钟
因为同步的本身就存着时间差,我们使用时钟,区分两个动作的顺序,而不是一定要知道准确的时间。
1.2.5.2面对故障的独立性
整个系统的一部分问题而其他部分正常是经常出现的情况,称之为故障的独立性。
1.2.5.3处理单点故障
1.2.5.4事务的挑战