小白一枚,首先感谢本校大三时期李老师开的分布式计算课程。个人对分布式感兴趣,而且觉得云计算可能比现在更火,应用更广泛。所以本篇只作为分布式入门一个简单的了解,更偏向于对整体体系的把握,而不做技术细考。但分布式太过笼统,知识体系也非常庞大,所以本文只记录其中冰山一角。
本文大多参考本校老师的课程PPT(未经授权故本篇不公开ppt内容)、《数据密集型应用系统设计》及一些github博客。由于水平有限理解不够深入,做不出更好的说明,仅是一个整理笔记。
另外关于课程实验不作说明,都是熟悉模块流程的代码实验,没用什么算法。
参考:
BigData-Notes:关于一些工具很有用的讲解。
awesome-distributed-systems:awesome开头的github项目都不必解释,很全面,但不一定都看得懂哈哈哈。
分布式系统学习笔记:某位学长留下的笔记,供参考。
分布式系统课程总结:笔记,不太全面。
mark几个有用资料待看。
分布式系统学习资料汇总:全学完一定是大牛了
知乎-廖君的回答:如果真的从事这方面科研必读的论文
2020 MIT 6.824 分布式系统机翻视频
MIT6.824的课程和实验
知乎有个回答说的不错:学习分布式系统需要怎样的知识?
分布式主要包含三个方面:
课程主要基于前两方面,实际工作内容的大部分都是分布式计算方面。
1.1 分布式定义:
一个分布式系统由多个通过网络互联的独立自治的计算节点组成,这些计算节点基于消息传递机制进行相互协作,以完成共同的目标。
正确理解多个cpu的计算器不算分布式系统,区分消息传递模型和共享内存模型。
消息传递模型:
共享内存模型
理解分布式和并发计算区别:并行计算与分布式处理的区别
1.2 衡量分布式优劣指标
1.3 分布式系统的特性:见链接,很全面。
1.4分布式系统面临的挑战:
见分布式系统之一:分布式系统的挑战
异构性:各个节点的软硬件差异性很大
自治:各节点有自己独立的时钟、独立的内部状态
局部视图:节点只能看到整个系统的某个局部视图
开放性:节点数目在变动,网络情况在变动
可扩展性:节点增加时性能须合理增长
故障处理:必须处理网络故障、局部节点故障
安全性:保密性、完整性、认证性、隐私、可用性
透明性:应用层或用户无法察觉位置、并发、复制、故障、移动、伸缩、性能等变化
1.5 分布式一致性协议:算法原理和实现见链接。
Paxos
Paxos 应用极广,对每个人都有巨大的影响。很多强大的分布式系统都可以基于该协议实现,比如:
腾讯的分布式内存数据库 PaxosStore(已开源,github.com/Tencent/paxosstore):该数据库把数据暂存在内存中,虽然丢失的风险更大,但是可以通过“多主多备”模式(氪金)来降低翻车的概率。
阿里 OceanBase。未开源。数据多副本,通过 Paxos 实现同步。关于阿里的OceanBase其实还有个趣事:阿里云做云计算那么艰难,为什么后面其他公司都随便就拥有了云计算?
Raft
Raft 因 Paxos 协议过于难懂而被开发出来,对程序员更加友好、易于理解,效率并不比 Paxos 更高;
使用该协议实现的系统有 阿里巴巴的 PolarFS、浪潮内部的分布式数据库等
新兴的PingCAP也是raft协议。
1.6按分布式计算任务限定完成时间长短(时效性)分类:
实时处理任务,也叫OLTP(Online Transaction Processing)任务,往往有高并发要求
eg.在线购物、在线交易等
准实时处理任务,流处理模型:
eg.Web搜索时的联想、广告推送、商品推荐等
批处理任务,也叫OLAP(Online Analysis Processing)任务,往往只有单一用户
1.7 5类分布式系统构架模式:
1.8 引入中间件
中间件是什么?如何解释比较通俗易懂?
中间件的作用
为开发者提供高层的编程抽象,屏蔽分布式系统底层的异构
性和复杂性
提高互操作性和可移植性
提供分布式系统的基础设施服务
)
1.9 设计分布式算法时使用的抽象分布式系统模型,从以下三个方面
进行定义:(没太理解这个分类,参考其他博客)
所需的计算机网络知识不过多解释,底层通信只关注TCP和UDP,上层只介绍RPC和消息队列。
2.1 什么是socket?
传输层和网络层提供给应用层的标准化编程接口(或称为编程接口)
注:
路由器中只包含物理层、链路层、网络层协议实现模块。
主机中包含五层协议实现模块。
操作系统负责实现传输层及以下网络协议的实现。
2.2 关于tcp和udp的socket通信实验,此处借两张图说明过程。
具体代码,确立套接字,确认连接等参考:Java网络编程UDP与TCP(Socket编程)
多线程不必说,线程池调用ThreadPoolExecutor,参考线程池之ThreadPoolExecutor使用
关于并发技术的多线程和线程池详讲:分布式系统学习笔记2:分布式节点之间的通信技术:并发服务技术、RPC 与 RMI 概述
基于多线程的并发服务:优点是逻辑简单,每个线程内部的逻辑完全相同但缺点也非常明显:对于线程的频繁创建和销毁会造成较大的开销,且线程过多时会产生很高的线程切换成本
基于线程池的并发服务:该方案能够避免进程创建与销毁的开销,并能防止建立线程过多造成拥塞
但无论是多线程并发服务还是线程池,终究还是存在切换问题,切换过多总会造成较大的开销、浪费性能。
事件驱动技术(多路复用技术)
2.3 RPC和RMI
远程过程调用(Remote Procedure Call, RPC): 使应用程序可以像调用本地节点上的过程(子程序) 那样去调用一个远程节点上的子程序。
远程方法调用(Remote Method Invocation, RMI): 将面向对象的编程模型扩展到了分布式环境。
RMI和RPC的比较:参考RMI和RPC比较
RPC/RMI中间件的作用:
RPC/RMI中间件的实现原理:(可以扩展阅读深入浅出 RPC - 深入篇)
RPC/RMI中间件在调用者进程中植入stub/proxy模块,stub模块作为远程过程的本地代理,并且暴露与远程过程相同的接口。
RPC/RMI中间件在被调用者进程中植入skeleton模块, skeleton作为调用者在远程主机中的代理,代替客户端调用本地方法,并把结果返回给客户端。
stub模块与skeleton模块利用Socket进行通信。
skeleton模块相当于Client-Server通信模式中的服务器端,要先于客户端运行,并且在某个Socket端口进行监听。
常用的RPC/RMI中间件 (仅作了解,深入自行百度)
Java RMI:Java的自娱自乐
Microsoft .NET Remoting:.Net的自娱自乐
CORBA:重量级分布式对象中间件,跨语言
gRPC:Google的RPC中间件,高效,开源,跨语言
Thrift:Facebook、Apache的RPC中间件,高效,开源,跨语言
Hessian:基于HTTP+二进制,跨语言
Dubbo:淘宝开源中间件,Java
Motan:新浪开源中间件,Java
WebService:基于HTTP + SOAP/XML/JSON(了解这三个要素,这部分内容待补)
Google Protocol Buffers:一种对象序列化标准和开发库
2.4 面向消息中间件(MOM: Message Oriented Middleware)
提供了一种分布式消息队列服务,使得节点之间可以实现基于消息的形式灵活的异步通信。
可以看一看MQ(1)—— 从队列到消息中间件
增加mq好处:(解耦+缓冲+易扩展)
总线型架构:(回顾第一章)
不同节点之间通过虚拟总线相连
消息发送者不必知道接收者是谁,接收者也不知道发送者是谁
发送者和接收者之间用异步方式通信
一种松耦合架构
不同节点完成不同功能,分工协作
消息队列通信模式:可参考分布式系统学习笔记4:消息中间件
消息队列模式
中间件会在生产者、消费者(两者均可有多个)中间建立一个先进先出的队列,每个消息被某一个消费者取走,即会被在队列中删除(这意味着每条消息只能有一个消费者接收到)。出队的消息按照某种负载均衡策略发送给特定的消费者。
高级队列模式:带优先级的队列;支持持久性的队列
主题/订阅通信模式:
支持向一个特定的消息主题发布消息。
多个订阅同一主题的消费者可以同时接收发布到该消息主题的消息
可以灵活地实现广播、组播等多对多通信模式
三种消息接收方式(顾名思义,不解释):阻塞接收、轮询接收、回调接收(通知接收)
基于MOM实现通信的优点
2.5 常用的MOM中间件(工作一定会用到其中一些,学习一个写实验上手即可)
RabbitMQ:采用Erlang语言实现的AMQP协议的消息中间件,最初起源于金融系统。
RocketMQ:阿里 的开源产品,用 Java 语言实现;在阿里内部被广泛应用在订单,交易,充值,流计算,消息推送,日志流式处理等场景。
Apache Kafka:提供完全分布式架构,与Apache的其他平台如Hadoop、Apache Storm、Spark、Flink等集成方便。
ZeroMQ:号称史上最快的消息队列,基于C语言开发。
WebsphereMQ:IBM的MOM中间件产品
这里给个链接:RabbitMQ快速入门(详细),写的非常详细,作为实验写一遍,熟悉客户端和服务端流程。
可以学习《数据密集型应用系统设计》一书第二部分,把数据复制、分区和一致性原理讲的很清楚。
3.1 分布式存储要达成的目标
基本手段:
3.2 复制方法分类:
主从复制(单主复制):
② 优点:实现相对简单。大多数应用场景都是读多写少。
③ 缺点:主库即是性能瓶颈,又是单点故障节点(Single point of failure)
④ 为提高容错性,自动将某个从库切换为主库时会面临脑裂问题。
多节点复制(多主复制):
② 应用场景:多数据中心之间的复制;协同文档编辑。
③ 优点:写入性能高。
④ 缺点:写入冲突问题、多副本一致性问题解决方案太复杂。
无主节点复制:
① 没有主库从库的概念。
② 客户端直接将写入请求发送到到各个副本;或者客户端将写入发送给某个节点,由该节点充当代理节点向其他节点转发写入请求
同步复制优点是更容易实现副本之间的一致性; 缺点是写入速度慢;一个节点失效会使整体写入功能失败,阻塞其后所有写操作。
异步复制优点:写入速度快;容错性好; 缺点:保持多副本一致性复杂;
混合复制(半同步/半异步):部分节点同步复制,部分节点异步复制
补充:
在一些如 Raft、Paxos 的算法中,可以采用一种与上面两个都不同的方式:主库接收到一定比例(比如超过一半)的从库应答后,就会对用户发出应答
在 HDFS 中,使用“流水线”应答,逐级发送写入请求,逐级返回应答。而且并非一次写一整个数据块,而是每次只写一小块(比如 64kB ),全部写完再给 client 返回应答
3.3 多副本分布式存储中的一致性问题
数据一致性模型:
多个客户端在读写数据时,分布式存储系统为客户端提供的关于数据外在表现的保证。
关于这部分可以参考:[译] 分布式系统中的一致性模型
强一致性:(线性一致性/原子一致性)
在客户端看来,分布式存储系统的外在表现和单副本存储系统的外在表现完全一致。(类似于多个线程访问同一个寄存器)任意客户端看到的所有针对分布式系统的操作(读、写等原子操作)按全局一致的顺序排列(线性化),并且该排序满足多个操作在时间维度上的实际发生先后顺序。
顺序一致性:
任意客户端看到的所有针对分布式系统的操作(读、写等原子操作)按全局一致的顺序排列(线性化),同一个客户端发出的多个操作的顺序与该全局一致排序并不矛盾。
因果一致性:
不同客户端看到的所有针对分布式系统的操作(读、写等原子操作)排序不一定一致,但该排序不违背操作发生的因果关系。
最终一致性:在分布式系统停止更新时,最终所有读操作都可以获得最新版本的数据。
3.4 关于CAP和hadoop,mapreduce可看(译)分布式系统概述
CAP定理
关于CAP简单证明理解(非数学证明)可以看分布式系统的CAP理论
Consistensy(一致性):不同节点上数据的强一致性
• Partition Tolerance(分区容错性):允许部分节点与其它节点断裂
• Availability(可用性):发出的请求在规定时间段内总能返回结果(请求响应延时短,可用性高;否则可用性低)
• CAP定理:在设计分布式系统时,三者只能取其二,不能三者兼得。
BASE定理
BASE理论是对CAP中一致性和可用性权衡的结果,来源于对大规模互联网分布式系统实践的总结,核心思想是即使无法做到强一致性,但每个应用都可以根据自身业务特点降低部分一致性获得可用性。
• 基本可用(Basically Available):
– 在出现故障的时候,允许损失部分可用性,保证核心可用。
• 软状态(Soft State)
– 允许系统中的数据存在中间状态,允许系统在多个不同节点的数据副本存在更新延时。
• 最终一致性(Eventually Consistent)
– 不可能一直处于软状态,在一定期限后应当保证所有副本保持数据一致性,从而达到数据的最终一致性
3.5 数据分区
合理数据分区的目标:
将数据和查询负载均匀分布在各个节点上,避免出现偏斜(skew)和热点(hot spot)问题;分区方式要兼顾跨区查询问题。
根据主键范围进行分区
优点:按主键进行连续查询很方便。
缺点:在主键范围非均匀分布时必须建立全局索引以记录数据分区和存储节点的对应关系。一般要专门指定一个节点维护全局索引,该节点是中心节点。
根据主键的哈希值进行分区
优点:
① 可以在一定程度上避免了偏斜和热点问题。
② 无须全局索引,因而也无须中心节点。
缺点:
① 基于主键进行连续范围查询效率极低。
② 在物理存储节点较少时仍然会出现偏斜和热点问题(可以采用虚拟节点的方法进行缓解)
③ 桶的个数改变时会产生大量数据移动
(原因:分布式系统中,假设有 n 个节点,传统方案使用 mod(key, n) 映射数据和节点。
当扩容或缩容时(哪怕只是增减1个节点),映射关系变为 mod(key, n+1) / mod(key, n-1),绝大多数数据的映射关系都会失效。)
3.6 一致性哈希:参考一致性哈希算法的原理与实现
3.7 HDFS分布式文件系统
官方文档见:Hadoop分布式文件系统:架构和设计
HDFS 遵循主/从架构,由单个 NameNode(NN) 和多个DataNode(DN) 组成。
hdfs的读写流程和其他细节参考:HDFS经典简答题(实习生必看!)
3.8 NoSQL:相比之前所学的老古董,算是非常现代化的技术了,待补。
4.1 MapReduce并行计算模型
网上资料很多,只贴一个看过的通俗易懂地理解MapReduce计算框架
Map阶段:第一阶段并行,将输入文件(或指定目录下的多个输入文件)划分成多个分区,每个分区都交给一个独立的Map子任务进行处理。强制要求每个Map子任务将输出规整为一系列
聚集混洗阶段:不同Map子任务输出的
Reduce阶段:第二阶段并行,将聚集之后的数组A划分成多个分区,每个分区都交给一个独立的Reduce子任务进行处理。(每个分区内按key进行排序)。 Reduce子任务根据输入生成一系列
如果Reduce阶段输出不是最终结果,还可以启动新一轮
MapReduce过程。
要点:通过Map子任务输出的key值部分控制不同子任务输出结果的相互交换和聚集。
4.2 Combiner作用:参考MapReduce:Combiner,partition的作用
1)每一个map可能会产生大量的输出,Combiner的作用就是在map端对输出先做一次合并,以减少传输到reducer的数据量。
2)Combiner最基本是实现本地key的归并,Combiner具有类似本地的reduce功能。
如果不用Combiner,那么,所有的结果都是reduce完成,效率会相对低下。
使用Combiner,先完成的map会在本地聚合,提升速度。
注意:Combiner的输出是Reducer的输入,如果Combiner是可插拔的,添加Combiner绝不能改变最终的计算结果。所以Combiner只应该用于那种Reduce的输入key/value与输出key/value类型完全一致,且不影响最终结果的场景。比如累加,最大值等。
注意事项
不是每种作业都可以做combiner操作的,只有满足以下条件才可以:
1)combiner只应该用于那种Reduce的输入key/value与输出key/value类型完全一致,因为combine本质上就是reduce操作。
2)计算逻辑上,combine操作后不能影响计算结果,像求和,最大值就不会影响,求平均值就影响了。
可以看这个spark入门系列文章:大话Spark(1)-Spark概述与核心概念
然后了解为什么Spark比MapReduce快?
5.1 分布式弹性数据集RDD
RDD可以理解为一份数据在集群上的抽象, 被分为多个分区, 每个分区分布在集群不同的节点上(如上图), 从而让RDD中的数据可以被并行操作(分布式数据集).
RDD有一个重要的特性就是,提供了容错性,可以自动从节点失败中恢复过来。即如果某个节点上的RDD partition, 因为节点故障 导致数据丢了, 那么RDD会自动通过自己的数据来源重新计算该partition.
5.2 RDD与DAG
DAG中的节点表示三类对象:(1)输入文件;(2)输出文件;(3)RDD
DAG中有向边表示:RDD转换算子
5.3 RDD的基本操作
RDD有两种基本操作:Transformation 和 Action
Transformation
通过Scala集合或者Hadoop数据集构造一个新的RDD
通过已有的RDD产生新的RDD(RDD不可修改)
Action
通过RDD计算得到一个或者一组值
区别:
接口定义方式不同
Transformation: RDD[x] -> RDD[y]
Action: RDD[x] -> Z (Z不是一个RDD,可能是基本类型,数组等)
惰性执行(Lazy Exception)
Transformation 只会记录RDD转换关系,并不会触发计算
Action算子定义的动作一般会立即执行,进而触发其它的惰性
Transformation算子的执行。
spark算子讲解很多
参考:Transformation 和 Action 常用算子
5.4 关于Mapreduce和Spark的实验
尽管很多Mapreduce和spark教程大多都是基于命令行的,但建议大家再用IDE跑一遍代码,反正工作也要用,不如早早练习配环境。