第三章 Google云计算原理
一、 云计算(Cloud Computing)
- 定义:
云计算是一种商业计算模式,它将计算任务分布在大量计算机构成的资源池上,使用户能够按需获取计算力、存储空间和信息服务
这种资源池称为“云”,是指可以自我维护和管理的虚拟计算资源,通常是一些大型的服务器集群,包括计算服务器、存储服务器和宽带资源等 - 云计算的特点
1)超大规模 2)虚拟化 3)高可靠性 4)通用性 5)高可扩展性 6)极其廉价 - 云计算的服务类型
- 将基础设施作为服务IaaS(Infrastructure as a Service)
将硬件设备等基础资源封装成服务供用户使用 - 将平台作为服务PaaS(Platform as a Service )
将应用程序的运行环境供用户使用 - 将软件作为服务SaaS(Software as a Service)
将某些特定应用软件功能封装成服务供用户使用
- Web Service服务
- Web Service是两个系统的远程调用,使两个系统进行数据交互
- Web Service是跨语言调用,发送Http请求,使用的数据格式是XML格式
- 云计算实现机制
二、 GFS(谷歌文件系统,Google File System)
- 概念:
- 元数据
任何文件系统中的数据分为现实数据和元数据
现实数据是指普通文件中的实际数据
元数据是用来描述一个文件的特征系统数据,如访问权限、文件拥有者以及文件数据块的分布信息等 - POSIX规范
可移植操作系统接口(Portable Operating System Interface)
- GFS系统架构
- GFS特点
1)采用中心服务器模式
- 不缓存数据
3)在用户态下实现
4)只提供专用接口
- GFS容错机制
- 主服务器容错机制
a) 主服务器上保存三种元数据信息:
命名空间:整个文件系统的目录结构以及数据块基本信息
数据块与文件名的映射表
数据块副本的位置信息,每个数据块通常有三个副本
b) 前两个元数据通过操作日志来提供容错功能
第三种元数据通过数据块服务器维护
c) 主服务器远程实时备份 - 数据块服务器容错
a) GFS采用复制多个副本的方式实现数据块服务器的容错
b) 数据块服务器会对存储的数据维持校验
- GFS系统管理技术
1)大规模集群安装技术
- 故障检测技术
3)节点动态加入技术
4)节能技术
三、 并行数据处理MapReduce
- 概述:Map(映射)、Reduce(化简)
MapReduce是Google提出的一个软件架构,是一种海量数据的并行编程模式,用于大规模数据集(通常大于1TB)并行运算 - MapReduce执行流程图
- 主控程序失效
在主控程序中会周期性的设置检查点(checkpoint),并导出主控程序的数据 - 工作机失效
主控程序会周期性给工作机发送ping命令
四、 分布式锁服务Chubby
- 锁的类型
- 竞争锁:任务通过竞争获取锁才能对该资源进行操作
- 占有锁:当有一个任务在对资源进行更新
- 任务阻塞:其他任务都不可以对这个资源进行操作
- 释放锁:指导该任务完成更新
- Paxos算法
- 概念:一种基于消息传递(Messages Passing)的一致性算法,用于解决分布式系统中的一致性问题
- 算法描述:
a) Proposers: 提出提案 (Proposal)。提案信息包括提案编号 (Proposal ID) 和提议的值 (Value)
Acceptors:参与决策,回应Proposers的提案。收到提案后可以接受提案,若提案获得多数Acceptors的接受,则称该提案被批准
Learners:不参与决策,从Proposers/Acceptors学习最新达成一致的提案值(Value)
b) 第一阶段:Prepare阶段
Proposers向Acceptors发出Prepare(准备)请求,Acceptors针对收到的Prepare请求进行Promise(承诺)
第二阶段:Accept阶段
Proposers收到多数Acceptors承诺后,向Acceptors发出Accept请求,Acceptors针对收到提案请求进行Accept处理
第三阶段:Learn阶段
Proposers在收到多数Acceptors的Accept之后,标志着本次Accept成功,决议形成。Acceptors会将形成的决议发送给Proposers和Learners
c) 解决一致性问题算法:为了减少决议发布过程中的消息量,acceptors将这个通过的决议发送给learners的一个子集,然后由这个子集中的learners去通知所有其他的learners
d) 特殊情况:如果两个proposer在某种情况下都会提出一个编号大于n的提案,可能陷入活锁。此时需要选举出一个president,仅允许president提出提案 - 保证数据的一致性,要满足三个条件:
a) 决议只有在被proposers提出后才能批准
b) 每次只批准一个决议
c) 只有决议确定被批准后leaners才能获取这个决议 - acceptors满足以下约束条件:
当且仅当acceptors没有收到编号大于n的请求时,acceptors才批准编号为n的提案。
- 分布式锁服务Chubby
- 概念:
Google设计的提供粗粒度锁服务的一个文件系统,它基于松耦合分布式系统,解决了分布的一致性问题
一种建议性的锁而不是强制性的锁;具有更大的灵活性 - 用途:
a) GFS使用Chubby选取一个主服务器
b) Bigtable使用Chubby指定一个主服务器并发现、控制其子表服务器
c) Chubby可以作为一个稳定的存储系统存储包括元数据在内的小数据
d) Google内部使用Chubby进行名字服务(Name Server) - Chubby系统设计目标
a) 高可用性和高可靠性
首要目标,在保证这一目标的基础上再考虑系统的吞吐量和存储能力。
b) 高扩展性
将数据存储在价格较为低廉的RAM,支持大规模用户访问文件
c) 支持粗粒度的建议性锁服务
提供这种服务的根本目的是提高系统的性能
d) 服务信息的直接存储
可直接存储包括元数据、系统参数在内的有关服务信息
e) 支持通报机制
客户可以及时地了解到事件发生
f) 支持缓存机制
通过一致性缓存将常用信息保存在客户端,避免了频繁地访问主服务器 - Chubby基本架构:
客户端和服务器端,两者通过远程过程调用(RPC)来连接
a) 客户端每个客户应用程序都有一个Chubby程序库(Chubby Library),所有应用都是通过调用这个库中相关函数来完成
b) 服务器一端Chubby单元,一般由五个称为副本(Replica)服务器组成,它们配置上完全一致,且系统刚开始时处于对等地位
- Chubby中的Paxos
a) 选择一副本为协调者(Coordinator)
b) 协调者从客户提交的值中选择一个值并接受这个值,将接受值的消息广播给所有的副本,其他的副本收到广播后,选择接受或者拒绝这个值,并将决定结果反馈给协调者
c) 协调者收到大多数副本接受信息后,认为达到了一致性,接着向相关副本发送一个commit消息
- Chubby文件系统
Chubby系统本质上就是一个分布式的、存储大量小文件的文件系统,它所有的操作都是在文件的基础上完成。
a) Chubby最常用的锁服务中,每一个文件代表一个锁,用户通过打开、关闭和读取文件,获取共享(Shared)锁或独占(Exclusive)锁
b) 在选举主服务器过程中,符合条件的服务器都同时申请打开某个文件并请求锁住该文件
c) 主服务器会主动将其地址写入这个文件夹,以便其他服务器和用户可以获知主服务器的地址信息 - Chubby客户端与服务器端的通信过程
a) 从左到右的水平方向表示时间在增加,斜向上的箭头表示一次KeepAlive请求,斜向下的箭头则是主服务器的一次回应
b) M1、M2、M3表示不同的主服务器租约期;C1、C2、C3则是客户端对主服务器租约期时长做出的一个估计
c) KeepAlive是周期发送的信息,两大功能:延迟租约的有效期和携带事件信息告诉用户更新 - 故障处理——客户租约期到期
客户端向主服务器发出一个KeepAlive请求(上图标号1)
a) 如果有需要通知的事件时则主服务器会立刻做出回应,否则等到客户端的租约期C1快结束的时候才做出回应(图标号2),并更新主服务器租约期为M2
b) 客户端接到回应后认为该主服务器仍处于活跃状态,于是将租约期更新为C2并立刻发出新的KeepAlive请求(图标号3)
c) 宽限期内,客户端不会立刻断开与服务器端的联系,而是不断地做探询,当它接到客户端第一个KeepAlive请求(图标号4)时会拒绝(图标号5)
d) 客户端在主服务器拒绝后使用新纪元号发送KeepAlive请求(图标号6)
e) 新的主服务器接受这个请求并立刻做出回应(图标号7)
f) 如果客户端接收到这个回应的时间仍处于宽限期内,系统会恢复到安全状态,租约期更新为C3。如果在宽限期未接到主服务器的相关回应,客户端终止当前的会话
如果这一过程在宽限期内顺利完成,则用户不会感觉到任何故障的发生,也就是说新旧主服务器的替换对于用户来说是透明的,用户仅仅感觉到一个延迟 - 一致性
a) 每个Chubby单元是由五个副本组成的,这五个副本中需要选举产生一个主服务器,这种选举本质上就是一个一致性问题。实际执行过程中,Chubby使用Paxos算法来解决
b) 客户端的所有读写操作都是由主服务器来完成的
读操作很简单,客户端直接从主服务器上读取所需数据
写操作就会涉及数据一致性的问题;为了保证客户的写操作能够同步到所有的服务器上,系统再次利用了Paxos算法 - 安全性
a) Chubby用ACL(access Control List,访问控制列表)形式安全保障措施。系统有三种ACL名:写ACL名(Write ACL Name)、读ACL名(Read ACL Name)和变更ACL名(Change ACL Name)
b) ACL同样被保存在文件中,它是节点元数据的一部分,用户在进行相关操作时首先需要通过ACL来获取相应的授权
c) 只要不被覆写,子节点都是直接继承父节点的ACL名
- 性能优化
为满足系统高可扩展性,Chubby采取提高主服务器默认的租约期、使用协议转换服务将Chubby协议转换成较简单的协议、客户端一致性缓存等;Google的工程师们考虑使用代理(Proxy)和分区(Partition)技术
a) 代理可以减少主服务器处理KeepAlive以及读请求带来的服务器负载,但是它并不能减少写操作带来的通信量
b) 分区可以将一个单元的命名空间(Name Space)划分成N份。除了少量的跨分区通信外,大部分的分区都可以独自地处理服务请求。通过分区可以减少各个分区上的读写通信量,但不能减少KeepAlive请求的通信量
五、 分布式结构化数据表BigTable
- 设计目标:
- 广泛的适用性
Bigtable是为了满足系列Google产品而非特定产品存储要求 - 很强的可扩展性
根据需要随时可以加入或撤销服务器 - 高可用性
确保几乎所有的情况下系统都可用 - 简单性
底层系统简单性既可减少系统出错概率,也为上层应用开发带来便利
- 数据模型
- 概述
a) Bigtable是一个分布式多维映射表,表中的数据通过一个行关键字、一个列关键字以及一个时间戳进行索引
b) Bigtable对存储在其中的数据不做任何解析,一律看作字符串
c) Bigtable的存储逻辑可以表示为:
(row: string, column: string, time: int64)→string - 行
a) Bigtable的行关键字可以是任意的字符串,但是大小不能超过64KB
b) Bigtable和传统的关系型数据库有很大不同,它不支持一般意义上的事务,但能保证对于行的读写操作具有原子性
c) 表中数据都是根据行关键字进行排序的,排序使用的是词典序
d) 一个典型实例,其中com.cnn.www就是一个行关键字。不直接存储网页地址而将其倒排是Bigtable的一个巧妙设计。
同一地址域的网页被存储在表中的连续位置,有利于用户查找和分析 倒排便于数据压缩,可以大幅提高压缩率
- 列
a) Bigtable并不是简单地存储所有的列关键字,而是将其组织成列族,每个列族中的数据都属于同一个类型,并且同族的数据会被压缩在一起保存
b) 语法规则:族名:限定词(family:qualifier)
族名必须有意义,限定词则可以任意选定
上图中,内容、锚点都是不同的族。而cnnsi.com和my.look.ca则是锚点族中不同的限定词
列族也是Bigtable中访问控制(Access Control)基本单元,也就是说访问权限的设置是在列族这一级别上进行的 - 时间戳
为了简化不同版本的数据管理,Bigtable提供了两种设置:
a) 保留最近的N个不同版本,上图中数据模型保存了最新的三个版本数据
b) 保留限定时间内的所有不同版本,比如可以保存最近10天的所有不同版本数据。失效的版本将会由Bigtable的垃圾回收机制自动处理
- 系统架构
- 在Bigtable中Chubby主要有以下几个作用:
a) 选取并保证同一时间内只有一个主服务器(Master Server)
b) 获取子表的位置信息
c) 保存Bigtable的模式信息及访问控制列表 - Bigtable主要由三个部分组成:客户端程序库(Client Library)、一个主服务器(Master Server)和多个子表服务器(Tablet Server)
a) 客户访问Bigtable服务时,首先要利用其库函数执行Open()操作来打开一个锁(实际上就是获取了文件目录),锁打开以后客户端就可以和子表服务器进行通信
b) 与许多具有单个主节点分布式系统一样,客户端主要与子表服务器通信,几乎不和主服务器进行通信,这使得主服务器的负载大大降低
c) 服务器主要进行一些元数据操作以及子表服务器之间负载调度问题,实际数据是存储在子表服务器上 - 主服务器
a) 新子表分配:
当一个新子表产生时,主服务器通过一个加载命令将其分配给一个空间足够的子表服务器。
创建新表、表合并以及较大子表的分裂都会产生一个或多个新子表
对于前面两种,主服务器会自动检测到,而较大子表的分裂是由子表服务发起并完成的,所以主服务器并不能自动检测到,因此在分割完成之后子表服务器需要向主服务器发出一个通知
b) 子表服务器监控
由于系统设计之初要求能达到良好的扩展性,所以主服务器必须对子表服务器的状态进行监控,以便及时检测到子表服务器的加入或撤销
Bigtable中主服务器对子表服务器的监控是通过Chubby完成的——子表服务器在初始化时都会从Chubby中得到一个独占锁。通过这种方式所有子表服务器基本信息被保存在Chubby中服务器目录
c) 子表服务器之间的负载均衡
主服务器会定期询问独占锁的状态。如果子表服务器的锁丢失或没有回应,此时可能有两种情况
主服务器尝试获取这个独占锁,如果失败,说明Chubby服务出现问题,需等待恢复;如果成功,则说明Chubby服务良好而子表服务器本身出现了问题
当在状态监测时发现某个子表服务器上负载过重时,主服务器会自动对其进行负载均衡操作
基于系统出现故障是一种常态的设计理念,每个主服务器被设定了一个会话时间的限制。当某个主服务器到时退出后,管理系统就会指定一个新的主服务器,这个主服务器的启动需要经历以下四个步骤
从Chubby中获取一个独占锁,确保同一时间只有一个主服务器
扫描服务器目录,发现目前活跃的子表服务器
与所有的活跃子表服务器取得联系以便了解所有子表分配情况
扫描元数据表,发现未分配的子表并将其分配到合适子表服务器
如果元数据表未分配,则首先需要将根子表(Root Tablet)加入未分配的子表中。由于根子表保存了其他所有元数据子表的信息,确保了扫描能够发现所有未分配的子表
- SSTable及子表基本结构
- SSTable结构
a) SSTable中数据被划分成块(Block),每个块的大小可以设置,一般为64KB
b) 在SSTable的结尾有一个索引(Index),这个索引保存了块的位置信息。在SSTable打开时这个索引会被加载进内存,用户在查找某个块时首先在内存中查找块的位置信息,然后在硬盘上直接找到这个块
c) 由于每个SSTable一般都不是很大,用户可以选择将其整体加载进内存,这样查找起来会更快 - 子表实际组成
a) 每个子表都是由多个SSTable以及日志(Log)文件构成
b) 不同子表的SSTable可以共享
- 日志文件
a) Bigtable中的日志文件是一种共享日志,每个子表服务器上仅保存一个日志文件,某个子表日志只是这个共享日志的一个片段。这样会节省大量的空间,但在数据丢失恢复时有一定的难度
b) Google对日志做了改进。Bigtable规定将日志的内容按照键值进行排序,这样不同的子表服务器都可以连续读取日志文件。
c) 一般来说每个子表的大小在100MB到200MB之间。每个子表服务器上保存的子表数量可以从几十到上千不等,通常情况下是100个左右 - 子表地址结构
子表地址的查询是用户经常使用的操作。在Bigtable系统的内部采用的是一种类似B+树的三层查询体系
a) 所有子表地址都被记录在元数据表中,元数据表也是由一个个的元数据子表(Metadata tablet)组成
b) 根子表是元数据表中一个比较特殊的子表,它既是元数据表的第一条记录,也包含了其他元数据子表的地址,同时Chubby中的一个文件也存储了这个根子表的信息
c) 查询时,首先从Chubby中提取这个根子表的地址,进而读取所需的元数据子表的位置,最后可以从元数据子表中找到待查询的子表
d) 为了减少访问开销,提高客户访问效率,Bigtable使用了缓存(Cache)和预取(Prefetch)技术。
子表的地址信息被缓存在客户端,客户在寻址时直接根据缓存信息进行查找
预取是在每次访问元数据表时不仅读取所需的子表元数据,而且读取多个子表的元数据,这样下次需要时就不用再次访问元数据表
- 子表数据存储及读/写操作
- Bigtable将数据存储划分成两块:较新的数据存储在内存中内存表(Memtable)的有序缓冲里,较早的数据则以SSTable格式保存
- 写操作(Write Op)
a) 先查询Chubby中保存的访问控制列表确定用户是否具有相应写权限,通过认证之后写入的数据首先被保存在提交日志(Commit Log)中
b) 提交日志中以重做记录(Redo Record)的形式保存着最近的一系列数据更改,这些重做记录在子表进行恢复时可以向系统提供已完成的更改信息
c) 数据成功提交以后就被写入内存表中 - 读操作(Read Op)
先通过认证,之后文件来进行,因为内存表和SS读操作就要结合内存表和SSTable中都保存了数据
- Bigtable中三种形式的数据压缩
a) 次压缩(Minor Compaction)
每一次旧的内存表停止使用时都会进行一个次压缩操作,这会产生一个SSTable。但如果系统中只有这种压缩的话,SSTable的数量就会无限制地增加下去
b) 合并压缩(Merging Compaction)
在Bigtable中,读操作实际上比写操作更重要,因此Bigtable会定期地执行一次合并压缩的操作,将一些已有的SSTable和现有的内存表一并进行一次压缩
c) 主压缩(Major Compaction)
d) 主压缩其实是合并压缩的一种,只不过它将所有的SSTable一次性压缩成一个大的SSTable文件。主压缩也是定期执行,执行一次主压缩之后可以保证将所有的被压缩数据彻底删除
- 性能优化
- 局部性群组
a) 有的用户只对网页内容感兴趣,可以通过设置局部性群组只看内容这一列
b) 有的用户对网页语言、网站排名等可以用于分析的信息比较感兴趣,可以将这些列设置到一个群组中
- 压缩
- 布隆过滤器