1、为什么要有分布式系统?
答:单机处理能力存在瓶颈;
分布式系统的稳定性和可用性强。
2、基础知识:ConcurrentHashMap是完全线程安全的吗?
答:总体上,读不加锁,写加锁,所有造成ConcurrentHashMap并非绝对的线程安全。
ConcurrentHashMap是一个线程安全的Hash Table,它的主要功能是提供了一组和HashTable功能相同但是线程安全的方法。ConcurrentHashMap可以做到读取数据不加锁,并且其内部的结构可以让其在进行写操作的时候能够将锁的粒度保持地尽量地小,不用对整个ConcurrentHashMap加锁。ConcurrentHashMap的内部结构:ConcurrentHashMap为了提高本身的并发能力,在内部采用了一个叫做Segment的结构。一个Segment其实就是一个类Hash Table的结构,Segment内部维护了一个链表数组,我们用下面这一幅图来
看下ConcurrentHashMap的内部结构:
从上面的结构我们可以了解到,ConcurrentHashMap定位一个元素的过程需要进行两次Hash操作,第一次Hash定位到Segment,第二次Hash定位到元素所在的链表的头部,因此,这一种结构的带来的副作用是Hash的过程要比普通的HashMap要长,但是带来的好处是写操作的时候可以只对元素所在的Segment进行加锁即可,不会影响到其他的Segment,这样,在最理想的情况下,ConcurrentHashMap可以最高同时支持Segment数量大小的写操作(刚好这些写操作都非常平均地分布在所有的Segment上),所以,通过这一种结构,ConcurrentHashMap的并发能力可以大大的提高。
3、基础知识:网络IO实现方式,分布式系统肯定涉及到数据的远程传输
bio :阻塞io,一个线程只处理一个socket;
nio :非阻塞io,一个线程可以处理多个socket,基于事件驱动思想,采用的是Reactor模式。如下图所示:
Reactor:负责响应事件,分发给绑定了该事件的 handler执行 task
Handler:绑定了某类事件,负责执行该事件对应的 task。
Acceptor : Handler 的一种,绑定了 connect 事件。它在系统启动的时候就已经绑定了 connnect 事件,并注册到 reactor 中。当有客户端发起 connect 请求时, reactor 会收到
accept 事件,然后分发给 acceptor 。 acceptor 首先会 accept 新的连接,然后新建一个 handler ,将其与该连接上得 read 事件绑定,并注册到 reactor 中。
通过Reactor对所有客户端的Socket套接字的事件做处理,然后派发到不同的线程中。
aio:异步io,采用Proactor模式。java7才引入的。
4、如何把应用从单机扩展到分布式
输入设备的变化:传统的人机交互的输入设备------->网络连接的多个节点,一个节点接受其他节点传来的信息时,这个其他节点可以看作为输入设备。
输出设备的变化:同输入设备的变化一样。
控制器的变化:单机系统中,控制器指的是cpu中的控制器;我们知道分布式系统是由多个节点通过网络连接在一起并通过消息的传递进行协调的系统。控制器的主要作用是协调
或控制节点之间的动作和行为。例如:硬件负载均衡的请求调用、lvs(Linux Virtual Server)的请求调用、采用名称服务的直连方式的请求调用、规则服务器控制
路由的请求直连调用、Master+Worker的方式。
关于名称服务需要简单的再说明下:“名称服务”的作用:
1、收集提供请求处理的服务器的地址信息;
2、提供这些地址信息给请求发起方。即:原来在透明代理上做的工作被拆分到名称服务和发起请求的机器上了。
图示:第一张图是采用软件的负载均衡,第二张是名称服务/规则服务。
名称服务与规则服务很类似,区别在于,名称服务会与处理请求的机器进行交互,而规则服务则不会。
运算器的变化:由多个节点共同组成(多个服务器),关于若有多个服务器,用户应该去访问哪个服务器?
方法一:通过DNS服务器进行调度和控制
方法二:通过DNS服务器和负载均衡设备,共同进行调度和控制。DNS返回的永远只是负载均衡的地址,
用户的访问通过负载均衡到达后面的网站服务器。
存储器的变化:多机。
5、分布式系统的难点
缺乏全局时钟;
面对故障独立性;
处理单点故障:分布式系统中,某个角色或者功能只有某台单机在支撑,这个节点称为单点,其发生的故障称为单点故障;
事务的挑战。