谷歌云概述
分布式文件系统GFS (文件系统)
Client (客户端),Master (主服务器), Chunk Server(数据块服务器)
Client:提供给应用程序的访问接口
Master:GFS的管理节点,在逻辑上只有一个,保存系统的元数据,负责整个文件系统的管理,是GFS文件系统中的“大脑”
Chunk Server:负责具体的存储工作,Chunk Server的个数决定了GFS的规模。
GFS将文件按照固定的大小进行分块,默认64KB,每一块称为一个Chunk,每一个Chunk都有一个对应的索引号(Index)
- 客户端首先访问Master节点,获取交互的Chunk Server信息,然后访问这些Chunk Server,完成数据存取工作。这种设计方法实现了控制流和数据流的分离。
- Client与Master之间只有控制流,而无数据流,极大地降低了Master的负载
- Client与Chunk Server之间直接传输数据流,同时由于文件被分成多个Chunk进行分布式存储,Client可以同时访问多个Chunk Server,从而使得整个系统的I/O高度并行,系统整体性能得到提高。
容错机制:
-
Master容错
Master上保存了GFS文件系统的三种元数据
- 命名空间(Name Space),也就是整个文件系统的目录结构。(操作日志提供容错机制)
- Chunk与文件名的映射表。(操作日志提供容错机制)
- Chunk副本的位置信息,每一个Chunk默认有三个副本。(直接保存在各个Chunk Server上 )
当Master发生故障时,在磁盘数据保存完好的情况下,可以迅速恢复以上元数据;为了防止Master彻底死机,GFS还提供了Master远程的实时备份。
-
Chunk Server容错(副本 & 校验和)
GFS采用副本的方式实现Chunk Server的容错,每一个Chunk有多个存储副本(默认为三个),对于每一个Chunk,必须将所有的副本全部写入成功,才视为成功写入,相关的副本出现丢失或不可恢复等情况,Master自动将该副本复制到其他Chunk Server。GFS中的每一个文件被划分成多个Chunk,Chunk的默认大小是64MB ,每一个Chunk以Block为单位进行划分,大小为64KB,每一个Block对应一个32bit的校验和,读取一个Chunk副本时,Chunk Server会将读取到的数据和校验和进行比较。
分布式结构化数据表Bigtable (数据模型)
Bigtable是一个分布式多维映射表,表中的数据通过一个行关键字(Row Key)、一个列关键字(Column Key)以及一个时间戳(Time Stamp)进行索引
Bigtable的存储逻辑可以表示为: (row:string, column:string, time:int64)→string
-
表中数据都是根据行关键字进行排序的,排序使用的是词典序
-
BigTable将一个表分成了很多子表(tablet),每个子表包含多个行
- A table = a list of tablets
- A tablet = a list of sorted <key, value>
-
BigTable并不是简单存储所有列关键字,而是将其组织为所谓的列族(Column Family),表示为 族名:限定词(family:qualifier),族名必须有意义,限定词则可以任意选定 。族同时也是Bigtable中访问控制(Access Control)的基本单元 。
-
Google的很多服务比如网页检索和用户的个性化设置等都需要保存不同时间的数据,这些不同的数据版本必须通过时间戳来区分。
系统架构
Bigtable 中 Chubby 的主要作用
-
主服务器 Master
- 当一个新的子表产生时,主服务器通过一个加载命令将其分配给一个空间足够的子表服务器。
- 创建新表、表合并以及较大子表的分裂都会产生一个或多个新子表。对于前两种主服务器能自动检测到,较大子表的分裂由子表服务器完成,分割完成之后子服务器需要向主服务发出一个通知。
- 主服务器必须对子表服务器的状态进行监控,以便及时检测到服务器的加入或撤销
-
子表服务器 Tablet Server
SSTable是Google为Bigtable设计的内部数据存储格式。所有的SSTable文件都存储在GFS上,用户可以通过键来查询相应的值。
每一个SSTable都包含了连续的几个块(默认情况下,每个块64KB)块索引(存放在SSTable的最后)是用来定位块的;当SStable打开时索引就被加载进内存。首先在内存中查找块的位置信息,然后在硬盘上直接找到这个块。
每个子表由多个SSTable及Log构成,不同子表的SSTable可以共享,每个子表服务器上仅保存一个日志文件,Bigtable规定将日志的内容按照键值进行排序。
读写操作
-
写入数据:不直接写入SSTable,通过写入内存表(memTable)来加速,为避免数据丢失在写入内存表之前,数据首先被保存在Log中。当内存表过大,将memTable导入硬盘,成为一个新的SSTable。
A tablet = memTable(临时) + a list of SSTables + log
-
读数据:
- SSTable内部的数据是有序的,SSTable之间的数据是无序的
- 每次查找需要查找所有的SSTable和memTable
- 使用索引(index)加快读数据
- 使用bloomfilter进行过滤可以进一步加快读数据
分布式数据处理MapReduce (算法)
MapReduce把对数据集的大规模操作,分发给一个主节点管理下的各分节点共同完成,通过这种方式实现任务的可靠执行与容错机制。
Map函数 — 对一部分原始数据进行指定的操作。每个Map操作都针对不同的原始数据,因此Map与Map之间是互相独立的,这使得它们可以充分并行化。
Reduce操作 — 对每个Map所产生的一部分中间结果进行合并操作,每个Reduce所处理的Map中间结果是互不交叉的,所有Reduce产生的最终结果经过简单连接就形成了完整的结果集。
$Map: (in_key, in_value) \rightarrow {(key_j, value_j) | j = 1…k} $
$Reduce: (key, [value1,…,valuem]) \rightarrow (key, final_value) $
例:通过MapReduce完成排序工作
-
对原始的数据进行分割(Split),得到N个不同的数据分块 。
-
对每一个数据分块都启动一个Map进行处理。采用桶排序的方法,每个Map中按照首字母将字符串分配到26个不同的桶中。
-
对于Map之后得到的中间结果,启动26个Reduce。按照首字母将Map中不同桶中的字符串集合放置到相应的Reduce中进行处理。
实现机制 :
- MapReduce函数首先把输入文件分成M块
- 分派的执行程序中有一个主控程序Master
- 一个被分配了Map任务的Worker读取并处理相关的输入块
- 这些缓冲到内存的中间结果将被定时写到本地硬盘,这些数据通过分区函数分成R个区
- 当Master通知执行Reduce的Worker关于中间<key,value>对的位置时,它调用远程过程,从Map Worker的本地硬盘上读取缓冲的中间数据
- Reduce Worker根据每一个唯一中间key来遍历所有的排序后的中间数据,并且把key和相关的中间结果值集合传递给用户定义的Reduce函数
- 当所有的Map任务和Reduce任务都完成的时候,Master激活用户程序
容错机制:
- Master失效:Master会周期性地设置检查点(checkpoint),并导出Master的数据。一旦某个任务失效,系统就从最近的一个检查点恢复并重新执行。由于只有一个Master在运行,如果Master失效了,则只能终止整个MapReduce程序的运行并重新开始。
- Worker失效:Master会周期性地给Worker发送ping命令,如果没有Worker的应答,则Master认为Worker失效,终止对这个Worker的任务调度,把失效Worker的任务调度到其他Worker上重新执行。