最近在找java服务器端的工作,面试了一些公司,很多面试官都会问到分布式相关的问题,在理论方面功底还是有所欠缺,在此从理论上学习一下并记录笔记。
开始学习分布式系统,主要是通过《分布式系统原理》这本书,发现很有意思,在此记录一下学习笔记。
一、基本概念
1、节点
节点是指一个独立按照分布式协议完成一组逻辑的程序个体。一般是运行在一台机器上的一个程序,一般认为节点是一个完整的、不可分割的整体。
2、通信
节点与节点之间是完全独立的、相互隔离的,节点之间传递信息的唯一方式是通过不可靠的网络进行通信,即一个节点可以向其他节点通过网络发送信息,但发送信息的节点无法确认消息是否被接收节点完整正确收到
3、存储
节点可以通过将数据写入与节点在同一台机器的本地存储设备保存数据。通常的存储设备有磁盘、SSD等。存储、读取数据的节点称为有状态的节点,反之是无状态的节点。如果某个节点A存储数据的方式是将数据通过网络发送到另一个节点B,由节点B负责将数据存储到节点B的本地存储设备,那么A不是有状态节点,只有B是无状态节点。
4、异常
分布式系统的核心问题之一就是处理各种异常(failure)情况,异常情况包括以下内容:
(1)机器宕机
机器宕机是最常见的异常之一。在大型集群中每日发生宕机的概率为千分之一左右。宕机造成的后果通常为该机器上节点不能正常工作。架设节点的工作流程是三个独立原子的步骤,宕机造成的后果是节点可能在处理某个步骤后不再继续处理后续步骤,从而造成某些协议路程无法完成。
当发生宕机时,节点无法正常工作,称为“不可用”(unabailable)状态。
(2)网络异常
网络异常是另一类常见的异常形式,节点之间通过不可靠的网络进行通信。网络异常如下:
消息丢失
消息乱序
数据错误
不可靠的TCP
二、分布式系统原理
1、数据分布方式
所谓分布式系统顾名思义就是利用多台计算机协同解决单台计算机不能解决的计算、存储等问题。单机系统和分布式系统的最大区别在于问题的规模,即计算、存储的数据量的区别。将单机问题使用分布式解决,首先要解决就是如何将问题拆解为可以使用多机多机分布式解决,使得分布式系统中的每台机器负责原问题的一个子集。由于无论是计算还是存储,其问题输入对象都是数据,所以如何拆解分布式系统的输入数据成为分布式系统的基本问题。拆分如下:
(1)、哈希方式
(2)、按数据范围分布
(3)、按数据量分布
(4)、一致性哈希
(5)、副本与数据分布
(6)、本地化计算
(7)、数据分布方式的选择
2、基本副本协议
副本控制协议指按特定的协议流程控制副本数据的读写行为,使得副本满足一定的可用性和一致性要求的分布式协议。副本控制协议要具有一定的对抗异常状态的容错能力,从而使得系统具有一定的可用性,同时副本控制协议要能提供一定的一致性。由CAP原理可知,要设计一种满足强一致性,且在出现任何网络异常时都可用的副本协议是不可能的。为此,实际中的副本控制协议总是在可用性、一致性与性能等各要素之间按照具体需求折中。
控制协议分为两大类: “中心化副本控制协议”和”去中心化副本控制协议”
(1)、中心化副本控制协议
中心化副本控制协议的基本思路是由一个中心节点协调副本数据的更新、维护副本之间的一致性。下图为中心化副本协议的通用架构。
- 优点: 协议相对较简单,所有副本相关的控制交由中心节点完成。并发控制由中心节点完成,从而使得一个分布式并发控制问题简化为一个单击并发控制问题。
并发控制: 多个节点需要同时修改副本数据时,需要解决“写写”、“读写”等并发冲突。单击系统上常用加锁等方式进行并发控制,对于分布式并发控制,加锁也是常用的方法,但是如果没有中心节点进行锁管理,就需要完全分布式化的锁系统,会使协议非常复杂。
- 缺点: 系统的可用性依赖于中心化节点,当中心节点异常或与中心节点通信中断时,系统将失去某些服务,所以中心化副本控制协议的缺点正式存在一定的服务停止时间
primary-secondary协议
primary-secondary协议是一种中心化副本控制协议,在primary-secondary协议中,副本被分为两大类,其中有且仅有一个副本作为primary副本,其他的都是secondary副本,维护副本的节点作为中心节点,中心节点负责维护数据的更新、并发控制、协调副本的一致性。
primary-secondary协议主要解决四大问题:
- 数据更新流程
- 数据读取方式
- Primary副本的确定和切换
- 数据同步
[1]、数据更新流程
1)、数据更新都由primary节点协调完成
2)、外部节点将更新操作发送给primary节点
3)、primary节点进行并发控制即确定并发更新操作的先后顺序
4)、primary节点将更新操作发送给secondary节点
5)、primary更具secondary节点的完成情况决定更新是否成功并将结果返回给外部节点
[2]、数据读取方式
数据读取方式是primary-secondary类协议需要解决的第二个问题。与数据更新流程类似,读取方式也与一致性高度相关。如果只需要最终一致性,则读取任何副本都可以满足需求。如果需要会话一致性,则可以为副本设置版本号,每次更新后递增版本号,用户读取副本时验证版本号,从而保证用户读到的数据在会话范围内单调递增,使primary-secondary比较困难是实现强一致性。
以下是实现primary-secondary实现强一致性的几种思路:
- 由于数据更新流程都是primary控制的,primary副本上的数据一定是最新的,所以如果始终只读primary副本的数据,可以实现强一致性。
- 由primary控制节点secondary节点的可用性。当primary更新某个secondary副本不成功时,primary将该secondary副本标记为不可用,从而用户不在读取该不可用的副本,不可用的secondary副本可以继续尝试与primary同步数据,同步成功后,标记为可用。
- 基于Quorum机制