ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

大规模分布式存储系统:原理解析与架构实战——笔记

2019-10-03 15:02:22  阅读:317  来源: 互联网

标签:副本 架构 存储系统 粉色 分布式系统 数据 节点 分布式


大规模分布式存储系统:原理解析与架构实战
杨传辉


分布式系统的数据量远远超出了单个计算机的存储和处理能力

一个2亿用户的电信运营商,如果平均每个用户每天拨打接听总共10个电话,每个电话400字节,5年的话费记录总量即为0.2G×10×0.4K×365×5=1.46PB。除了分布式系统,人们还很难有其他高效的手段来存储和处理这些PB级甚至更多的数据。


单机和分布式有两个明显的不同

首先,分布式环境下会出现一部分计算机工作正常,另一部分计算机工作不正常的情况,程序需要在这种情况下尽可能地正常工作,这个挑战非常大。
其次,单机环境下的函数调用常常可以在微秒级内返回,所以除了少数访问外部设备(例如磁盘、网卡等)的函数采用异步方式调用外,大部分函数采用同步调用的方式,编译器和操作系统在调用前后自动保存与恢复程序的上下文;在分布式环境下,计算机之间的函数调用(远程调用,即RPC)的返回时间通常是毫秒或亚毫秒(0.1~1.0毫秒)级,差不多是单机环境的100倍,使用同步方式远远不能发挥现代CPU处理器的性能,所以分布式环境下的RPC通常采用异步调用方式,程序需要自己保存和恢复调用前后的上下文,并需要处理更多的异常。


著名公司

为了处理这些海量内容,每个互联网公司在后端都有一套成熟的分布式系统用于数据的存储、计算以及价值提取。
Google的核心技术正是后端这些处理海量数据的分布式系统。和Google类似,国外的亚马逊微软以及国内互联网三巨头阿里巴巴百度腾讯的核心技术也是其后端的海量数据处理系统。
互联网公司的分布式存储系统由数量众多的、低成本和高性价比的普通PC服务器通过网络连接而成。

本书作者2007年年底加入百度公司,从事大规模分布式存储的研究和实践工作,曾经开发过类似GFS、MapReduce和Bigtable的分布式系统,后来转战阿里巴巴继续开发分布式数据库OceanBase。


分布式存储是基础,云存储和大数据是构建在分布式存储之上的应用。

移动终端的计算能力和存储空间有限,而且有在多个设备之间共享资源的强烈的需求,这就使得网盘、相册等云存储应用很快流行起来。云存储的核心还是后端的大规模分布式存储系统。
大数据则更近一步,不仅需要存储海量数据,还需要通过合适的计算框架或者工具对这些数据进行分析,抽取其中有价值的部分。如果没有分布式存储,便谈不上对大数据进行分析。


分布式存储系统

分布式存储系统可以扩展到几百台甚至几千台的集群规模,而且,随着集群规模的增长,系统整体性能表现为线性增长。

分布式存储系统的挑战主要在于数据、状态信息的持久化,要求在自动迁移、自动容错、并发读写的过程中保证数据的一致性
分布式存储涉及的技术主要有:
数据分布:如何将数据分布到多台服务器才能够保证数据分布均匀
一致性:如何将数据的多个副本复制到多台服务器,即使在异常情况下,也能够保证不同副本之间的数据一致性
容错:检测服务器故障并自动将出现故障的服务器上的数据和服务迁移到集群中的其他服务器
负载均衡:新增服务器和集群运行中实现负载均衡
分布式事务,多版本并发控制


数据分类

非结构化数据:包括所有格式的办公文档、文本、图片、图像、音频和视频信息等。
结构化数据:一般存储在关系数据库中,可以用二维关系表结构来表示。结构化数据的模式Schema包括属性、数据类型以及数据之间的联系)和内容是分开的,数据的模式需要预先定义


不同的分布式存储系统适合处理不同类型的数据

分布式存储系统分为四类:
1、分布式文件系统
互联网应用需要存储大量的图片、照片、视频等非结构化数据对象,这类数据以对象的形式组织,对象之间没有关联,这样的数据一般称为Blob(Binary Large Object,二进制大对象)数据。分布式文件系统用于存储Blob对象。
在系统实现层面,分布式文件系统内部按照数据块(chunk)来组织数据
2、分布式键值系统
分布式键值系统用于存储关系简单的半结构化数据,它只提供基于主键的CRUD(Create/Read/Update/Delete)功能,即根据主键创建、读取、更新或者删除一条键值记录
从数据结构的角度看,分布式键值系统与传统的哈希表比较类似,不同的是,分布式键值系统支持将数据分布到集群中的多个存储节点。
一般用作缓存,比如Memcache
一致性哈希是分布式键值系统中常用的数据分布技术
3、分布式表格系统
分布式表格系统用于存储关系较为复杂的半结构化数据,与分布式键值系统相比,分布式表格系统不仅仅支持简单的CRUD操作,而且支持扫描某个主键范围。分布式表格系统以表格为单位组织数据,每个表格包括很多行,通过主键标识一行,支持根据主键的CRUD功能以及范围查找功能
分布式表格系统借鉴了很多关系数据库的技术,例如支持某种程度上的事务
与分布式数据库相比,分布式表格系统主要支持针对单张表格的操作,不支持一些特别复杂的操作,比如多表关联,多表联接,嵌套子查询;另外,在分布式表格系统中,同一个表格的多个数据行也不要求包含相同类型的列,适合半结构化数据。
4、分布式数据库
分布式数据库一般是从单机关系数据库扩展而来,用于存储结构化数据。分布式数据库采用二维表格组织数据,提供SQL关系查询语言,支持多表关联,嵌套子查询等复杂操作,并提供数据库事务以及并发控制
典型的系统包括MySQL数据库分片(MySQL Sharding)集群,阿里巴巴OceanBase系统也是一个支持自动扩展的分布式关系数据库。


存储引擎

存储引擎就是哈希表、B树等数据结构在机械磁盘、SSD等持久化介质上的实现。单机存储系统是单机存储引擎的一种封装,对外提供文件、键值、表格或者关系模型。
哈希存储引擎是哈希表的持久化实现,……


数据库将一个或多个操作组成一组,称作事务,事务必须满足原子性、一致性、隔离性以及持久性。

为了保证持久性,对于数据库的每一个变化都要在磁盘上记录日志,当数据库系统突然发生故障,重启后能够恢复到之前一致的状态。


摩尔定律:每18个月计算机等IT产品的性能会翻一番;或者说相同性能的计算机等IT产品,每18个月价钱会降一半。


早期的CPU为单核芯片,现代服务器基本为多核或多个CPU

经典的多CPU架构为对称多处理结构,即在一个计算机上汇集了一组处理器,它们之间对称工作,无主次或从属关系,共享相同的物理内存及总线。
SMP系统的每个CPU有两个核心(core),CPU与内存之间通过总线通信。每个核心有各自的L1d Cache(L1数据缓存)及L1i Cache(L1指令缓存),同一个CPU的多个核心共享L2以及L3缓存。
某些CPU还可以通过超线程技术(Hyper-Threading Technology)使得一个核心具有同时执行两个线程的能力。
现在的主流服务器架构一般为NUMA(Non-Uniform Memory Access,非一致存储访问)架构。它具有多个NUMA节点,每个NUMA节点是一个SMP结构,一般由多个CPU(如4个)组成,并且具有独立的本地内存、IO槽口等。NUMA节点可以直接快速访问本地内存,也可以通过NUMA互联互通模块访问其他NUMA节点的内存。
以Intel x48主板为例,它是典型的南、北桥架构。北桥芯片通过前端总线(Front Side Bus,FSB)与CPU相连,内存模块以及PCI-E设备(如高端的SSD设备Fusion-IO)挂接在北桥上
网卡(包括千兆以及万兆网卡),硬盘以及中低端固态盘(如Intel 320系列SSD)挂接在南桥上。


传统的数据中心网络拓扑

接入层交换机、汇聚层以及核心层的交换机。
由于同一个接入层的服务器往往部署在一个机架内,因此,设计系统的时候需要考虑服务器是否在一个机架内,减少跨机架拷贝大量数据。例如,Hadoop HDFS默认存储三个副本,其中两个副本放在同一个机架,就是这个原因。

Google在2008年的时候将网络改造为扁平化拓扑结构,即三级CLOS网络,同一个集群内最多支持20480台服务器,且任何两台都有1Gb带宽。CLOS网络需要额外投入更多的交换机,带来的好处也是明显的,设计系统时不需要考虑底层网络拓扑,从而很方便地将整个集群做成一个计算资源池。

同一个数据中心内部的传输延时是比较小的,网络一次来回的时间在1毫秒之内。数据中心之间的传输延迟是很大的,取决于光在光纤中的传输时间。例如,北京与杭州之间的直线距离大约为1300公里,光在信息传输中走折线,假设折线距离为直线距离的1.5倍,那么光传输一次网络来回延时的理论值为1300×1.5×2/300000=13毫秒,实际测试值大约为40毫秒。


存储系统的性能瓶颈一般在于IO。顺序读取1MB数据的时间为:磁盘寻道时间+数据读取时间,即10ms+1MB/100MB/s×1000=20ms。存储系统的性能瓶颈主要在于磁盘随机读写。

固态磁盘(SSD),各大互联网公司都有大量基于SSD的应用。SSD的特点是随机读取延迟小,能够提供很高的IOPS(每秒读写,Input/Output Per Second)性能;主要问题在于容量和价格。

磁盘适合大块顺序访问的存储系统,SSD适合随机访问较多或者对延时比较敏感的关键系统。

从分布式系统的角度看,整个集群中所有服务器上的存储介质(内存、机械硬盘,SSD)构成一个整体,其他服务器上的存储介质与本机存储介质一样都是可访问的,区别仅仅在于需要额外的网络传输及网络协议栈等访问开销
集群中有30个机架,每个机架接入40台服务器,同一个机架的服务器接入到同一个接入交换机,不同机架的服务器接入到不同的接入交换机。


哈希存储引擎不支持顺序扫描
B树(B-Tree)存储引擎支持顺序扫描,对应的存储系统是关系数据库。
LSM树(Log-Structured Merge Tree)存储引擎和B树存储引擎一样,支持增、删、改、随机读取以及顺序扫描。它通过批量转储技术规避磁盘随机写入问题,广泛应用于互联网的后台存储系统,例如Google BigtableGoogle LevelDB以及Facebook开源的Cassandra系统

Bitcask是一个基于哈希表结构的键值存储系统,它仅支持追加操作(Append-only),即所有的写操作只追加而不修改老的数据。在Bitcask系统中,每个文件有一定的大小限制,当文件增加到相应的大小时,就会产生一个新的文件,老的文件只读不写。在任意时刻,只有一个文件是可写的,用于数据追加,称为活跃数据文件。
Bitcask数据文件中的数据是一条一条的写入操作,每一条记录的数据项分别为主键(key)、value内容(value)、主键长度(key_sz)、value长度(value_sz)、时间戳(timestamp)以及crc校验值。(数据删除操作也不会删除旧的条目,而是将value设定为一个特殊的值用作标识)。内存中采用基于哈希表的索引数据结构,哈希表的作用是通过主键快速地定位到value的位置。哈希表结构中的每一项包含了三个用于定位数据的信息,分别是文件编号(file id),value在文件中的位置(value_pos),value长度(value_sz),通过读取file_id对应文件的value_pos开始的value_sz个字节,这就得到了最终的value值。写入时首先将Key-Value记录追加到活跃数据文件的末尾,接着更新内存哈希表,因此,每个写操作总共需要进行一次顺序的磁盘写入和一次内存操作。
系统基于一个假设,value的长度远大于主键的长度。假如value的平均长度为1KB,每条记录在内存中的索引信息为32字节,那么,磁盘内存比为32:1。这样,32GB内存索引的数据量为32GB×32=1TB。
Bitcask系统中的记录删除或者更新后,原来的记录成为垃圾数据。如果这些数据一直保存下去,文件会无限膨胀下去,为了解决这个问题,Bitcask需要定期执行合并(Compaction)操作以实现垃圾回收。所谓合并操作,即将所有老数据文件中的数据扫描一遍并生成新的数据文件,这里的合并其实就是对同一个key的多个操作以只保留最新一个的原则进行删除,每次合并后,新生成的数据文件就不再有冗余数据了。
Bitcask系统中的哈希索引存储在内存中,如果不做额外的工作,服务器断电重启重建哈希表需要扫描一遍数据文件,如果数据文件很大,这是一个非常耗时的过程。Bitcask通过索引文件(hint file)来提高重建哈希表的速度。索引文件就是将内存中的哈希索引表转储到磁盘生成的结果文件。

 

相比哈希存储引擎,B树存储引擎不仅支持随机读取,还支持范围扫描
叶子节点保存每行的完整数据
B+树一次检索最多需要h-1次磁盘IO,复杂度为O(h)=O(logdN)(N为元素个数,d为每个节点的出度,h为B+树高度)
修改操作首先需要记录提交日志,接着修改内存中的B+树。如果内存中的被修改过的页面超过一定的比率,后台线程会将这些页面刷到磁盘中持久化
缓冲区管理器负责将可用的内存划分成缓冲区,缓冲区是与页面同等大小的区域,磁盘块的内容可以传送到缓冲区中。缓冲区管理器的关键在于替换策略,即选择将哪些页面淘汰出缓冲池。


LSM树(Log Structured Merge Tree)的思想非常朴素,就是将对数据的修改增量保持在内存中,达到指定的大小限制后将这些修改操作批量写入磁盘,读取时需要合并磁盘中的历史数据和内存中最近的修改操作。LSM树的优势在于有效地规避了磁盘随机写入问题,但读取时可能需要访问较多的磁盘文件
LevelDB存储引擎主要包括:内存中的MemTable和不可变MemTable(Immutable MemTable,也称为Frozen MemTable,即冻结MemTable)以及磁盘上的几种主要文件:当前(Current)文件、清单(Manifest)文件、操作日志(Commit Log,也称为提交日志)文件以及SSTable文件当应用写入一条记录时,LevelDB会首先将修改操作写入到操作日志文件,成功后再将修改操作应用到MemTable,这样就完成了写入操作。
当MemTable占用的内存达到一个上限值后,需要将内存的数据转储到外存文件中。LevelDB会将原先的MemTable冻结成为不可变MemTable,并生成一个新的MemTable。新到来的数据被记入新的操作日志文件和新生成的MemTable中。顾名思义,不可变MemTable的内容是不可更改的,只能读取不能写入或者删除。LevelDB后台线程会将不可变MemTable的数据排序后转储到磁盘,形成一个新的SSTable文件,这个操作称为Compaction。SSTable文件是内存中的数据不断进行Compaction操作后形成的,且SSTable的所有文件是一种层级结构,第0层为Level 0,第1层为Level 1,以此类推。
SSTable中的文件是按照记录的主键排序的,每个文件有最小的主键和最大的主键。LevelDB的清单文件记录了这些元数据,包括属于哪个层级、文件名称、最小主键和最大主键。当前文件记录了当前使用的清单文件名。在LevelDB的运行过程中,随着Compaction的进行,SSTable文件会发生变化,新的文件会产生,老的文件被废弃,此时往往会生成新的清单文件来记载这种变化,而当前文件则用来指出哪个清单文件才是当前有效的。
直观上,LevelDB每次查询都需要从老到新读取每个层级的SSTable文件以及内存中的MemTable。LevelDB做了一个优化,由于LevelDB对外只支持随机读取单条记录,查询时LevelDB首先会去查看内存中的MemTable,如果MemTable包含记录的主键及其对应的值,则返回记录即可;如果MemTable没有读到该主键,则接下来到同样处于内存中的不可变Memtable中去读取;类似地,如果还是没有读到,只能依次从新到老读取磁盘中的SSTable文件。


数据模型
文件关系以及随着NoSQL技术流行起来的键值模型、关系弱化的表格模型
文件系统以目录树的形式组织文件,以类UNIX操作系统为例,根目录为/,包含/usr、/bin、/home等子目录,每个子目录又包含其他子目录或者文件
POSIX(Portable Operating System Interface)是应用程序访问文件系统的API标准,它定义了文件系统存储接口及操作集。
POSIX标准适合单机文件系统,在分布式文件系统中,出于性能考虑,一般不会完全遵守这个标准。NFS(Network File System)文件系统允许客户端缓存文件数据,多个客户端并发修改同一个文件时可能出现不一致的情况。举个例子,NFS客户端A和B需要同时修改NFS服务器的某个文件,每个客户端都在本地缓存了文件的副本,A修改后先提交,B后提交,那么,即使A和B修改的是文件的不同位置,也会出现B的修改覆盖A的情况。
对象模型与文件模型比较类似,用于存储图片、视频、文档等二进制数据块,典型的系统包括Amazon Simple Storage(S3)Taobao File System(TFS)。这些系统弱化了目录树的概念,Amazon S3只支持一级目录,不支持子目录,Taobao TFS甚至不支持目录结构。与文件模型不同的是,对象模型要求对象一次性写入到系统,只能删除整个对象,不允许修改其中某个部分。

SQL查询还有一个强大的特性是允许在WHERE、FROM和HAVING子句中使用子查询,子查询又是一个完整的select-from-where语句。

大量的NoSQL系统采用了键值模型(也称为Key-Value模型),Key-Value模型过于简单,支持的应用场景有限,NoSQL系统中使用比较广泛的模型是表格模型

表格模型弱化了关系模型中的多表关联,支持基于单表的简单操作,典型的系统是Google Bigtable以及其开源Java实现HBase。表格模型除了支持简单的基于主键的操作,还支持范围扫描,另外,也支持基于列的操作。与关系模型不同的是,表格模型一般不支持多表关联操作,Bigtable这样的系统也不支持二级索引,事务操作支持也比较弱,各个系统支持的功能差异较大,没有统一的标准。另外,表格模型往往还支持无模式(schema-less)特性,也就是说,不需要预先定义每行包括哪些列以及每个列的类型,多行之间允许包含不同列

关系数据库在海量数据场景面临如下挑战:1、事务关系模型要求多个SQL操作满足ACID特性,所有的SQL操作要么全部成功,要么全部失败。在分布式系统中,如果多个操作属于不同的服务器,保证它们的原子性需要用到两阶段提交协议,而这个协议的性能很低,且不能容忍服务器故障,很难应用在海量数据场景。2、联表传统的数据库设计时需要满足范式要求,例如,第三范式要求在一个关系中不能出现在其他关系中已包含的非主键信息。假设存在一个部门信息表,其中每个部门有部门编号、部门名称、部门简介等信息,那么在员工信息表中列出部门编号后就不能加入部门名称、部门简介等部门有关的信息,否则就会有大量的数据冗余。而在海量数据的场景,为了避免数据库多表关联操作,往往会使用数据冗余等违反数据库范式的手段。实践表明,这些手段带来的收益远高于成本。

关系数据库采用B树存储引擎,更新操作性能不如LSM树这样的存储引擎。另外,如果只有基于主键的增、删、查、改操作,关系数据库的性能也不如专门定制的Key-Value存储系统。
数据库事务具有原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)以及持久性(Durability)
多个事务并发执行时,如果它们的执行结果和按照某种顺序一个接着一个串行执行的效果等同,这种隔离级别称为可串行化。可串行化是比较理想的情况,商业数据库为了性能考虑,往往会定义多种隔离级别。事务的并发控制一般通过锁机制来实现,锁可以有不同的粒度,可以锁住行,也可以锁住数据块甚至锁住整个表格
为了提高读事务性能,可以采用写时复制(Copy-On-Write,COW)或者多版本并发控制(Multi-Version Concurrency Control,MVCC)技术来避免写事务阻塞读事务
原子性,事务的原子性也体现在事务对数据的读取上,例如,一个事务对同一数据项的多次读取的结果一定是相同的。
一致性,事务需要保持数据库数据的正确性、完整性和一致性,一般情况下银行账务余额不能是负数,信用卡消费不能超过该卡的信用额度等。
隔离性,数据库需要保证每一个事务在它的修改全部完成之前,对其他的事务是不可见的,换句话说,不能让其他事务看到该事务的中间状态。从银行账户A转一笔款项a到账户B,不能让其他事务(例如账户查询)看到A账户已经扣除款项a但B账户却还没有增加款项a的状态。
永久性,事务完成后,它对于数据库的影响是永久性的,即使系统出现各种异常也是如此。

出于性能考虑,许多数据库允许使用者选择牺牲隔离属性来换取并发度,从而获得性能的提升。SQL定义了4种隔离级别。
隔离级别的降低可能导致读到脏数据或者事务执行异常
锁也分为两种类型:读锁以及写锁,允许对同一个元素加多个读锁,但只允许加一个写锁,且写事务将阻塞读事务。这里的元素可以是一行,也可以是一个数据块甚至一个表格
T1和T2两个事务操作不同行,初始时A=B=25,T1将A加100,T2将B乘以2,由于T1和T2操作不同行,两个事务没有锁冲突,可以并行执行而不会破坏系统的一致性。
T1扫描从A到C的所有行,将它们的结果相加后更新A,初始时A=C=25,假设在T1执行过程中T2插入一行B,那么,事务T1和T2无法做到可串行化。为了保证数据库一致性,T1执行范围扫描时需要锁住从A到C这个范围的所有更新,T2插入B时,由于整个范围被锁住,T2获取锁失败而等待T1先执行完成。
多个事务并发执行可能引入死锁。表2-6中T1读取A,然后将A的值加100后更新B,T2读取B,然后将B的值乘以2更新A,初始时A=B=25。T1持有A的读锁,需要获取B的写锁,而T2持有B的读锁,需要A的写锁。T1和T2这两个事务循环依赖,任何一个事务都无法顺利完成。
解决死锁的思路主要有两种:第一种思路是为每个事务设置一个超时时间,超时后自动回滚,表2-6中如果T1或T2二者之中的某个事务回滚,则另外一个事务可以成功执行。第二种思路是死锁检测。死锁出现的原因在于事务之间互相依赖,T1依赖T2,T2又依赖T1,依赖关系构成一个环路。检测到死锁后可以通过回滚其中某些事务来消除循环依赖

互联网业务中读事务占的比例往往远远超过写事务,很多应用的读写比例达到6:1,甚至10:1。写时复制(Copy-On-Write,COW)读操作不用加锁,极大地提高了读取性能
1)拷贝:将从叶子到根节点路径上的所有节点拷贝出来。 2)修改:对拷贝的节点执行修改。 3)提交:原子地切换根节点的指针,使之指向新的根节点。
如果读操作发生在第3步提交之前,那么,将读取老节点的数据,否则将读取新节点,读操作不需要加锁保护
写时复制技术涉及引用计数,对每个节点维护一个引用计数,表示被多少节点引用,如果引用计数变为0,说明没有节点引用,可以被垃圾回收。
写时复制技术原理简单,问题是每次写操作都需要拷贝从叶子到根节点路径上的所有节点,写操作成本高

除了写时复制技术,多版本并发控制,即MVCC(Multi-Version Concurrency Control),也能够实现读事务不加锁。MVCC对每行数据维护多个版本,无论事务的执行时间有多长,MVCC总是能够提供与事务开始时刻相一致的数据。
以MySQL InnoDB存储引擎为例,InnoDB对每一行维护了两个隐含的列,其中一列存储行被修改的“时间”,另外一列存储行被删除的“时间”,注意,InnoDB存储的并不是绝对时间,而是与时间对应的数据库系统的版本号,每当一个事务开始时,InnoDB都会给这个事务分配一个递增的版本号,所以版本号也可以被认为是事务号。对于每一行查询语句,InnoDB都会把这个查询语句的版本号同这个查询语句遇到的行的版本号进行对比,然后结合不同的事务隔离级别,来决定是否返回改行。
如果行的修改或者删除版本号大于事务号,说明行是被该事务后面启动的事务修改或者删除的。在可重复读取隔离级别下,后开始的事务对数据的影响不应该被先开始的事务看见,所以应该忽略后开始的事务的更新或者删除操作。
MVCC读取数据的时候不用加锁,每个查询都通过版本检查,只获得自己需要的数据版本,从而大大提高了系统的并发度。当然,为了实现多版本,必须对每行存储额外的多个版本的数据。另外,MVCC存储引擎还必须定期删除不再需要的版本,及时回收空间。


故障恢复
数据库运行过程中可能会发生故障,这个时候某些事务可能执行到一半但没有提交,当系统重启时,需要能够恢复到一致的状态,即要么提交整个事务,要么回滚。数据库系统以及其他的分布式存储系统一般采用操作日志(有时也称为提交日志,即Commit Log)技术来实现故障恢复。操作日志分为回滚日志(UNDO Log)、重做日志(REDO Log)以及UNDO/REDO日志
为了保证数据库的一致性,数据库操作需要持久化到磁盘,如果每次操作都随机更新磁盘的某个数据块,系统性能将会很差。因此,通过操作日志顺序记录每个数据库操作并在内存中执行这些操作,内存中的数据定期刷新到磁盘,实现将随机写请求转化为顺序写请求。
操作日志记录了事务的操作。例如,事务T对表格中的X执行加10操作,初始时X=5,更新后X=15,那么,UNDO日志记为<T,X,5>,REDO日志记为<T,X,15>,UNDO/REDO日志记为<T,X,5,15>。关系数据库系统一般采用UNDO/REDO日志。
存储系统如果采用REDO日志,其写操作流程如下: 1)将REDO日志以追加写的方式写入磁盘的日志文件。 2)将REDO日志的修改操作应用到内存中。 3)返回操作成功或者失败。
存储系统要求先将REDO日志刷入磁盘才可以更新内存中的数据,如果每个事务都要求将日志立即刷入磁盘,系统的吞吐量将会很差。因此,存储系统往往有一个是否立即刷入磁盘的选项,对于一致性要求很高的应用,可以设置为立即刷入;相应地,对于一致性要求不太高的应用,可以设置为不要求立即刷入,首先将REDO日志缓存到操作系统或者存储系统的内存缓冲区中,定期刷入磁盘。这种做法有一个问题,如果存储系统意外故障,可能丢失最后一部分更新操作。
成组提交(Group Commit)技术是一种有效的优化手段。REDO日志首先写入到存储系统的日志缓冲区中: a)日志缓冲区中的数据量超过一定大小,比如512KB; b)距离上次刷入磁盘超过一定时间,比如10ms。当满足以上两个条件中的某一个时,将日志缓冲区中的多个事务操作一次性刷入磁盘,接着一次性将多个事务的修改操作应用到内存中并逐个返回客户端操作结果。与定期刷入磁盘不同的是,成组提交技术保证REDO日志成功刷入磁盘后才返回写操作成功。这种做法可能会牺牲写事务的延时,但大大提高了系统的吞吐量。
如果所有的数据都保存在内存中,那么可能出现两个问题: ●故障恢复时需要回放所有的REDO日志,效率较低。如果REDO日志较多,比如超过100GB,那么,故障恢复时间是无法接受的。 ●内存不足
因此,需要将内存中的数据定期转储(Dump)到磁盘,这种技术称为checkpoint(检查点)技术。系统定期将内存中的操作以某种易于加载的形式(checkpoint文件)转储到磁盘中,并记录checkpoint时刻的日志回放点,以后故障恢复只需要回放checkpoint时刻的日志回放点之后的REDO日志。由于将内存数据转储到磁盘需要很长的时间,而这段时间还可能有新的更新操作,checkpoint必须找到一个一致的状态。checkpoint流程如下: 1)日志文件中记录"START CKPT"。 2)将内存中的数据以某种易于加载的组织方式转储到磁盘中,形成checkpoint文件。checkpoint文件中往往记录"START CKPT"的日志回放点,用于故障恢复。 3)日志文件中记录"END CKPT"。

传统的行式数据库将一个个完整的数据行存储在数据页中。如果处理查询时需要用到大部分的数据列,这种方式在磁盘IO上是比较高效的。
列式数据库是将同一个数据列的各个值存放在一起。插入某个数据行时,该行的各个数据列的值也会存放到不同的地方。
列式数据库大大地提高了OLAP大数据量查询的效率。当然,列式数据库不是万能的,每次读取某个数据行时,需要分别从不同的地方读取各个数据列的值,然后合并在一起形成数据行
很多列式数据库还支持列组(column group,Bigtable系统中称为locality group),即将多个经常一起访问的数据列的各个值存放在一起。如果读取的数据列属于相同的列组,列式数据库可以从相同的地方一次性读取多个数据列的值,避免了多个数据列的合并。列组是一种行列混合存储模式,这种模式能够同时满足OLTP和OLAP的查询需求。
由于同一个数据列的数据重复度很高,因此,列式数据库压缩时有很大的优势。例如,Google Bigtable列式数据库对网页库压缩可以达到15倍以上的压缩率
另外,可以针对列式存储做专门的索引优化。比如,性别列只有两个值,“男”和“女”,可以对这一列建立位图索引:如图2-12所示,“男”对应的位图为100101,表示第1、4、6行值为“男”;“女”对应的位图为011010,表示第2、3、5行值为“女”。如果需要查找男性或者女性的个数,只需要统计相应的位图中1出现的次数即可。另外,建立位图索引后0和1的重复度高,可以采用专门的编码方式对其进行压缩。

分布式系统面临的第一个问题就是数据分布,即将数据均匀地分布到多个存储节点。另外,为了保证可靠性和可用性,需要将数据复制多个副本,这就带来了多个副本之间的数据一致性问题。大规模分布式存储系统的重要目标就是节省成本,因而只能采用性价比较高的PC服务器。这些服务器性能很好,但是故障率很高,要求系统能够在软件层面实现自动容错。当存储节点出现故障时,系统能够自动检测出来,并将原有的数据和服务迁移到集群中其他正常工作的节点。
分布式系统中有两个重要的协议,包括Paxos选举协议以及两阶段提交协议。Paxos协议用于多个节点之间达成一致,往往用于实现总控节点选举。两阶段提交协议用于保证跨多个节点操作的原子性,这些操作要么全部成功,要么全部失败。
服务器宕机
重启后也需要恢复内存信息。
设计容错系统的一个基本原则是:网络永远是不可靠的,任何一个消息只有收到对方的回复后才可以认为发送成功,系统设计时总是假设网络将会出现异常并采取相应的处理措施。
磁盘故障分为两种情况:磁盘损坏和磁盘数据错误。
多台服务器,即使其中一台服务器磁盘出现故障,也能从其他服务器上恢复数据
对于磁盘数据错误,往往可以采用校验和(checksum)机制来解决
在分布式系统中,如果某个节点向另外一个节点发起RPC(Remote Procedure Call)调用,这个RPC执行的结果有三种状态:“成功”、“失败”、“超时”(未知状态),也称为分布式存储系统的三态。
图3-1给出了RPC执行成功但超时的例子
当出现超时状态时,只能通过不断读取之前操作的状态来验证RPC操作是否成功。当然,设计分布式存储系统时可以将操作设计为“幂等”的,也就是说,操作执行一次与执行多次的结果相同,例如,覆盖写就是一种常见的幂等操作
由于异常的存在,分布式存储系统设计时往往会将数据冗余存储多份,每一份称为一个副本
副本是分布式存储系统容错技术的唯一手段。由于多个副本的存在,如何保证副本之间的一致性是整个分布式系统的理论核心。
一般来说,存储系统可以支持强一致性,也可以为了性能考虑只支持最终一致性。从客户端的角度看,一般要求存储系统能够支持读写一致性,会话一致性,单调读,单调写等特性
常见的性能指标有:系统的吞吐能力以及系统的响应时间
这两个指标往往是矛盾的,追求高吞吐的系统,往往很难做到低延迟;追求低延迟的系统,吞吐量也会受到限制
如果系统部署在同一个数据中心,只要系统设计合理,在保证强一致性的前提下,不会对性能和可用性造成太大的影响。后文中笔者在Alibaba参与开发的OceanBase系统以及Google的分布式存储系统都倾向强一致性。
生成一张有30张缩略图(假设图片原始大小为256KB)的页面需要多少时间? ●方案1:顺序操作,每次先从磁盘中读取图片,再执行生成缩略图操作,执行时间为:30×10ms(磁盘随机读取时间)+30×256K/30MB/s(假设缩略图生成速度为30MB/s)=560ms ●方案2:并行操作,一次性发送30个请求,每个请求读取一张图片并生成缩略图,执行时间为:10ms+256K/300MB/s=18ms
分布式系统区别于传统单机系统在于能够将数据分布到多个节点,并在多个节点之间实现负载均衡。数据分布的方式主要有两种,一种是哈希分布,如一致性哈希,代表系统为Amazon的Dynamo系统;另外一种方法是顺序分布,即每张表格上的数据按照主键整体有序,代表系统为Google的Bigtable系统。Bigtable将一张大表根据主键切分为有序的范围,每个有序范围是一个子表。
哈希取模的方法很常见,其方法是根据数据的某一种特征计算哈希值,并将哈希值与集群中的服务器建立映射关系,从而将不同哈希值的数据分布到不同的服务器上。所谓数据特征可以是key-value系统中的主键(key),也可以是其他与业务逻辑相关的值。例如,将集群中的服务器按0到N-1编号(N为服务器的数量),根据数据的主键(hash(key)%N)或者数据所属的用户id(hash(user_id)%N)计算哈希值,来决定将数据映射到哪一台服务器。
如果哈希函数的散列特性很好,哈希方式可以将数据比较均匀地分布到集群中去
然而,找出一个散列特性很好的哈希函数是很难的。这是因为,如果按照主键散列,那么同一个用户id下的数据可能被分散到多台服务器,这会使得一次操作同一个用户id下的多条记录变得困难;如果按照用户id散列,容易出现“数据倾斜”(data skew)问题,即某些大用户的数据量很大,无论集群的规模有多大,这些用户始终由一台服务器处理。
传统的哈希分布算法还有一个问题:当服务器上线或者下线时,N值发生变化,数据映射完全被打乱,几乎所有的数据都需要重新分布,这将带来大量的数据迁移
一种思路是不再简单地将哈希值和服务器个数做除法取模映射,而是将哈希值与服务器的对应关系作为元数据,交给专门的元数据服务器来管理。访问数据时,首先计算哈希值,再查询元数据服务器,获得该哈希值对应的服务器。这样,集群扩容时,可以将部分哈希值分配给新加入的机器并迁移对应的数据。另一种思路就是采用一致性哈希
哈希散列破坏了数据的有序性,只支持随机读取操作,不能够支持顺序扫描
顺序分布在分布式表格系统中比较常见,一般的做法是将大表顺序划分为连续的范围,每个范围称为一个子表,总控服务器负责将这些子表按照一定的策略分配到存储节点上。
用户表(User表)的主键范围为1~7000,在分布式存储系统中划分为多个子表,分别对应数据范围1~1000,1001~2000,……6001~7000
信息。读User表时,需要通过Meta表查找相应的User子表所在的存储节点
分布式存储系统的每个集群中一般有一个总控节点,其他节点为工作节点,由总控节点根据全局负载信息进行整体调度。工作节点刚上线时,总控节点需要将数据迁移到该节点,另外,系统运行过程中也需要不断地执行迁移任务,将数据从负载较高的工作节点迁移到负载较低的工作节点。
分布式存储系统通过复制协议将数据同步到多个存储节点,并确保多个副本之间的数据一致性。
同一份数据的多个副本中往往有一个副本为主副本(Primary),其他副本为备副本(Backup),由主副本将数据复制到备份副本
复制协议分为两种,强同步复制以及异步复制,二者的区别在于用户的写请求是否需要同步到备副本才可以返回成功。
一致性和可用性是矛盾的,强同步复制协议可以保证主备副本之间的一致性,但是当备副本出现故障时,也可能阻塞存储系统的正常写服务,系统的整体可用性受到影响;异步复制协议的可用性相对较好,但是一致性得不到保障,主副本出现故障时还有数据丢失的可能。
主副本将写请求复制到其他备副本,常见的做法是同步操作日志
假设所有副本的个数为N,且N>2,即备副本个数大于1。那么,实现强同步协议时,主副本可以将操作日志并发地发给所有备副本并等待回复,只要至少1个备副本返回成功就可以回复客户端操作成功。强同步的好处在于如果主副本出现故障,至少有1个备副本拥有完整的数据,分布式存储系统可以自动地将服务切换到最新的备副本而不用担心数据丢失的情况。
强同步复制和异步复制都是将主副本的数据以某种形式发送到其他副本,这种复制协议称为基于主副本的复制协议
在任何时刻只能有一个副本为主副本
NWR复制协议,其中,N为副本数量,W为写操作的副本数,R为读操作的副本数。NWR协议中多个副本不再区分主和备
只要W+R>N,可以保证读到的副本中至少有一个包含了最新的更新。然而,这种协议的问题在于不同副本的操作顺序可能不一致,从多个副本读取时可能出现冲突。这种方式在实际系统中比较少见,不建议使用。
存储系统设计时需要在一致性和可用性之间权衡,在某些场景下,不允许丢失数据,在另外一些场景下,极小的概率丢失部分数据时允许的,可用性更加重要。例如,Oracle数据库的DataGuard复制组件包含三种模式: ●最大保护模式(Maximum Protection):即强同步复制模式,
●最大性能模式(Maximum Performance):即异步复制模式
标注 (粉色) - 第3章 分布式系统 > 位置 1108
单台服务器故障的概率是不高的,然而,只要集群的规模足够大,每天都可能有机器故障发生
标注 (粉色) - 第3章 分布式系统 > 位置 1109
在分布式系统中,故障检测往往通过租约(Lease)协议实现
标注 (粉色) - 第3章 分布式系统 > 位置 1120
容错处理的第一步是故障检测,心跳是一种很自然的想法。假设总控机A需要确认工作机B是否发生故障,那么总控机A每隔一段时间,比如1秒,向工作机B发送一个心跳包。如果一切正常,机器B将响应机器A的心跳包;否则,机器A重试一定次数后认为机器B发生了故障。然而,机器A收不到机器B的心跳并不能确保机器B发生故障并停止了服务,在系统运行过程中,可能发生各种错误,比如机器A与机器B之间网络发生问题,机器B过于繁忙导致无法响应机器A的心跳包
标注 (粉色) - 第3章 分布式系统 > 位置 1128
租约机制就是带有超时时间的一种授权。假设机器A需要检测机器B是否发生故障,机器A可以给机器B发放租约,机器B持有的租约在有效期内才允许提供服务,否则主动停止服务。机器B的租约快要到期的时候向机器A重新申请租约。正常情况下,机器B通过不断申请租约来延长有效期,当机器B出现故障或者与机器A之间的网络发生故障时,机器B的租约将过期,从而机器A能够确保机器B不再提供服务,机器B的服务可以被安全地迁移到其他服务器。
标注 (粉色) - 第3章 分布式系统 > 位置 1139
单层结构的分布式存储系统维护了多个副本,例如副本个数为3,主备副本之间通过操作日志同步。如图3-5所示,某单层结构的分布式存储系统有3个数据分片A、B、C,每个数据分片存储了三个副本。其中,A1,B1,C1为主副本,分别存储在节点1,节点2以及节点3。假设节点1发生故障,将被总控节点检测到,总控节点选择一个最新的副本,比如A2或者A3替换A1成为新的主副本并提供写服务
标注 (粉色) - 第3章 分布式系统 > 位置 1146
两层结构的分布式存储系统会将所有的数据持久化写入底层的分布式文件系统,每个数据分片同一时刻只有一个提供服务的节点。如图3-5所示,某双层结构的分布式存储系统有3个数据分片,A、B和C。它们分别被节点1,节点2和节点3所服务。当节点1发生故障时,总控节点将选择一个工作节点,比如节点2,加载A的服务。由于A的所有数据都存储在共享的分布式文件系统中,节点2只需要从底层分布式文件系统读取A的数据并加载到内存中。
标注 (粉色) - 第3章 分布式系统 > 位置 1155
总控节点自身也可能出现故障,为了实现总控节点的高可用性(High Availability),总控节点的状态也将实时同步到备机,当故障发生时,可以通过外部服务选举某个备机作为新的总控节点,而这个外部服务也必须是高可用的。为了进行选主或者维护系统中重要的全局信息,可以维护一套通过Paxos协议实现的分布式锁服务,比如Google Chubby或者它的开源实现Apache Zookeeper。
标注 (粉色) - 第3章 分布式系统 > 位置 1170
分布式存储系统中往往有一个总控节点用于维护数据分布信息,执行工作机管理,数据定位,故障检测和恢复,负载均衡等全局调度工作
标注 (粉色) - 第3章 分布式系统 > 位置 1175
开源的Hadoop也能够扩展到3000台以上的集群。
标注 (粉色) - 第3章 分布式系统 > 位置 1203
同一个组内的节点服务相同的数据,这样的系统称为同构系统。同构系统的问题在于增加副本需要迁移的数据量太大,假设每个存储节点服务的数据量为1TB,内部传输带宽限制为20MB/s,那么增加副本拷贝数据需要的时间为1TB/20MB/s=50000s,大约十几个小时
标注 (粉色) - 第3章 分布式系统 > 位置 1211
如图3-9所示,系统中有五个分片(A,B,C,D,E),每个分片包含三个副本,如分片A的三个副本分别为A1,A2以及A3。假设节点1发生永久性故障,那么可以从剩余的节点中任意选择健康的节点来增加A,B以及E的副本。由于整个集群都参与到节点1的故障恢复过程,故障恢复时间很短,而且集群规模越大,优势就会越明显。
标注 (粉色) - 第3章 分布式系统 > 位置 1215
异构系统
标注 (粉色) - 第3章 分布式系统 > 位置 1216
分布式系统涉及的协议很多,例如租约,复制协议,一致性协议
标注 (粉色) - 第3章 分布式系统 > 位置 1217
两阶段提交协议用于保证跨多个节点操作的原子性,也就是说,跨多个节点的操作要么在所有节点上全部执行成功,要么全部失败
标注 (粉色) - 第3章 分布式系统 > 位置 1218
Paxos协议用于确保多个节点对某个投票(例如哪个节点为主节点)达成一致。
标注 (粉色) - 第3章 分布式系统 > 位置 1220
两阶段提交协议(Two-phase Commit,2PC)经常用来实现分布式事务
标注 (粉色) - 第3章 分布式系统 > 位置 1221
在两阶段协议中,系统一般包含两类节点:一类为协调者( coordinator),通常一个系统中只有一个;另一类为事务参与者( participants, cohorts 或 workers),一般包含多个。
笔记 - 第3章 分布式系统 > 位置 1222
分布式事务
笔记 - 第3章 分布式系统 > 位置 1222
分布式事务
标注 (粉色) - 第3章 分布式系统 > 位置 1224
阶段1:请求阶段(Prepare Phase)。在请求阶段,协调者通知事务参与者准备提交或者取消事务,然后进入表决过程。在表决过程中,参与者将告知协调者自己的决策:同意(事务参与者本地执行成功)或者取消(事务参与者本地执行失败)。 ●阶段2:提交阶段(Commit Phase)。在提交阶段,协调者将基于第一个阶段的投票结果进行决策:提交或者取消。当且仅当所有的参与者同意提交事务协调者才通知所有的参与者提交事务,否则协调者通知所有的参与者取消事务。参与者在接收到协调者发来的消息后将执行相应的操作
标注 (粉色) - 第3章 分布式系统 > 位置 1229
例如,A组织B、C和D三个人去爬长城:如果所有人都同意去爬长城,那么活动将举行;如果有一人不同意去爬长城,那么活动将取消。
标注 (粉色) - 第3章 分布式系统 > 位置 1237
假如D一直不能回复邮件,那么A、B和C将不得不处于一直等待的状态。并且B和C所持有的资源一直不能释放,
标注 (粉色) - 第3章 分布式系统 > 位置 1238
A可以
标注 (粉色) - 第3章 分布式系统 > 位置 1239
通过引入事务的超时机制防止资源一直不能释放的情况
标注 (粉色) - 第3章 分布式系统 > 位置 1239
更为严重的是,假如A发完邮件后生病住院了,即使B、C和D都发邮件告诉A同意下周三去爬长城,如果A没有备份,事务将被阻塞,
标注 (粉色) - 第3章 分布式系统 > 位置 1241
两阶段提交协议可能面临两种故障: ●事务参与者发生故障。给每个事务设置一个超时时间,如果某个事务参与者一直不响应,到达超时时间后整个事务失败。
标注 (粉色) - 第3章 分布式系统 > 位置 1243
●协调者发生故障。协调者需要将事务相关信息记录到操作日志并同步到备用协调者,假如协调者发生故障,备用协调者可以接替它完成后续的工作。如果没有备用协调者,协调者又发生了永久性故障,事务参与者将无法完成事务而一直等待下去。
标注 (粉色) - 第3章 分布式系统 > 位置 1246
大多数分布式存储系统都采用敬而远之的做法,放弃对分布式事务的支持。
标注 (粉色) - 第3章 分布式系统 > 位置 1247
Paxos协议用于解决多个节点之间的一致性问题。多个节点之间通过操作日志同步数据,如果只有一个节点为主节点,那么,很容易确保多个节点之间操作日志的一致性。考虑到主节点可能出现故障,系统需要选举出新的主节点。Paxos协议正是用来实现这个需求。
标注 (粉色) - 第3章 分布式系统 > 位置 1251
为了实现高可用性,主节点往往将数据以操作日志的形式同步到备节点。如果主节点发生故障,备节点会提议自己成为主节点。这里存在的问题是网络分区的时候,可能会存在多个备节点提议(Proposer,提议者)自己成为主节点。Paxos协议保证,即使同时存在多个proposer,也能够保证所有节点最终达成一致,即选举出唯一的主节点。
标注 (粉色) - 第3章 分布式系统 > 位置 1254
大多数情况下,系统只有一个proposer,他的提议也总是会很快地被大多数节点接受。Paxos协议执行步骤如下: 1)批准(accept):Proposer发送accept消息要求所有其他节点(acceptor,接受者)接受某个提议值,acceptor可以接受或者拒绝。 2)确认(acknowledge):如果超过一半的acceptor接受,意味着提议值已经生效,proposer发送acknowledge消息通知所有的acceptor提议生效。
标注 (粉色) - 第3章 分布式系统 > 位置 1257
当出现网络或者其他异常时,系统中可能存在多个proposer,他们各自发起不同的提议
标注 (粉色) - 第3章 分布式系统 > 位置 1259
如果proposer第一次发起的accept请求没有被acceptor中的多数派批准(例如与其他proposer的提议冲突),那么,需要完整地执行一轮Paxos协议。过程如下:
标注 (粉色) - 第3章 分布式系统 > 位置 1267
Paxos协议需要考虑两个问题:正确性,即只有一个提议值会生效;可终止性,即最后总会有一个提议值生效
标注 (粉色) - 第3章 分布式系统 > 位置 1275
Paxos协议有两种用法:一种用法是用它来实现全局的锁服务或者命名和配置服务,例如
标注 (粉色) - 第3章 分布式系统 > 位置 1276
Apache Zookeeper
标注 (粉色) - 第3章 分布式系统 > 位置 1276
另外一种用法是用它来将用户数据复制到多个数据中心
标注 (粉色) - 第3章 分布式系统 > 位置 1277
2PC协议最大的缺陷在于无法处理协调者宕机问题。如果协调者宕机,那么,2PC协议中的每个参与者可能都不知道事务应该提交还是回滚,整个协议被阻塞,执行过程中申请的资源都无法释放。因此,常见的做法是将2PC和Paxos协议结合起来,通过2PC保证多个数据分片上的操作的原子性,通过Paxos协议实现同一个数据分片的多个副本之间的一致性。另外,通过Paxos协议解决2PC协议中协调者宕机问题。当2PC协议中的协调者出现故障时,通过Paxos协议选举出新的协调者继续提供服务。
标注 (粉色) - 第3章 分布式系统 > 位置 1283
跨机房部署方案有三个:集群整体切换、单个集群跨机房、Paxos选主副本。
标注 (粉色) - 第3章 分布式系统 > 位置 1302
在前两种方案中,总控节点需要和工作节点之间保持租约(lease),当工作节点出现故障时,自动将它上面服务的主副本切换到其他工作节点。如果采用Paxos协议选主副本,那么,每个数据分片的多个副本构成一个Paxos复制组。如图3-12所示,B1、B2、B3、B4构成一个复制组,某一时刻B1为复制组的主副本,当B1出现故障时,其他副本将尝试切换为主副本,Paxos协议保证只有一个副本会成功。这样,总控节点与工作节点之间不再需要保持租约,总控节点出现故障也不会对工作节点产生影响。
第二篇 范型篇
标注 (粉色) - 第4章 分布式文件系统 > 位置 1321
Google文件系统(GFS)是构建在廉价服务器之上的大型分布式系统。
标注 (粉色) - 第4章 分布式文件系统 > 位置 1323
GFS是Google分布式存储的基石,其他存储系统,如Google Bigtable、Google Megastore、Google Percolator均直接或者间接地构建在GFS之上。另外,Google大规模批处理系统MapReduce也需要利用GFS作为海量数据的输入输出。
标注 (粉色) - 第4章 分布式文件系统 > 位置 1325
GFS系统的节点可分为三种角色:GFS Master(主控服务器)、GFS ChunkServer(CS,数据块服务器)以及GFS客户端。
标注 (粉色) - 第4章 分布式文件系统 > 位置 1332
客户端是GFS提供给应用程序的访问接口,它是一组专用接口,不遵循POSIX规范,以库文件的形式提供。客户端访问GFS时,首先访问主控服务器节点,获取与之进行交互的CS信息,然后直接访问这些CS,完成数据存取工作。
标注 (粉色) - 第4章 分布式文件系统 > 位置 1592
CDN通过将网络内容发布到靠近用户的边缘节点,使不同地域的用户在访问相同网页时可以就近获取。
标注 (粉色) - 第4章 分布式文件系统 > 位置 1594
所谓的边缘节点是CDN服务提供商经过精心挑选的距离用户非常近的服务器节点,仅“一跳”(Single Hop)之遥。用户在访问时就无需再经过多个路由器,大大减少访问时间。
标注 (粉色) - 第4章 分布式文件系统 > 位置 1596
从图4-9可以看出,DNS在对域名解析时不再向用户返回源服务器的IP,而是返回了由智能CDN负载均衡系统选定的某个边缘节点的IP。用户利用这个IP访问边缘节点,然后该节点通过其内部DNS解析得到源服务器IP并发出请求来获取用户所需的页面,如果请求成功,边缘节点会将页面缓存下来,下次用户访问时可以直接读取,而不需要每次都访问源服务器。
标注 (粉色) - 第4章 分布式文件系统 > 位置 1601
淘宝CDN系统用于支持用户购物,尤其是“双11”光棍节时的海量图片请求。如图4-10所示,图片存储在后台的TFS集群中,CDN系统将这些图片缓存到离用户最近的边缘节点
标注 (粉色) - 第4章 分布式文件系统 > 位置 1615
相比分布式存储系统,分布式缓存系统的实现要容易很多。这是因为缓存系统不需要考虑数据持久化,如果缓存服务器出现故障,只需要简单地将它从集群中剔除即可。
标注 (粉色) - 第4章 分布式文件系统 > 位置 1623
由于Blob存储系统读访问量大,更新和删除很少,特别适合通过CDN技术分发到离用户最近的节点。
标注 (粉色) - 第4章 分布式文件系统 > 位置 1629
新上线的CDN缓存节点配备的磁盘均为SSD。
标注 (粉色) - 第5章 分布式键值系统 > 位置 1630
分布式键值模型可以看成是分布式表格模型的一种特例。然而,由于它只支持针对单个key-value的增、删、查、改操作,因此,适用3.3.1节提到的哈希分布算法
标注 (粉色) - 第5章 分布式键值系统 > 位置 1722
Dynamo写入数据时,首先,根据一致性哈希算法计算出每个数据副本所在的存储节点,其中一个副本作为本次写操作的协调者。接着,协调者并发地往所有其他副本发送写请求,每个副本将接收到的数据写入本地,协调者也将数据写入本地。当某个副本写入成功后,回复协调者。如果发给某个副本的写请求失败,协调者会将它加入重试列表不断重试。等到W-1个副本回复写入成功后(即加上协调者共W个副本写入成功),协调者可以回复客户端写入成功。协调者回复客户端成功后,还会继续等待或者重试,直到所有的副本都写入成功。 Dynamo读取数据时,首先,根据一致性哈希算法计算出每个副本所在的存储节点,其中一个副本作为本次读操作的协调者。接着,协调者根据负载策略选择R个副本,并发地向它们发送读请求。每个副本读取本地数据,协调者也读取本地数据。当某个副本读取成功后,回复协调者读取结果。等到R-1个副本回复读取成功后(即加上协调者共R个副本读取成功),协调者可以回复客户端。这里分为两种情况:如果R个副本返回的数据完全一致,将某个副本的读取结果回复客户端;否则,需要根据冲突处理规则合并多个副本的读取结果。Dynamo系统默认的策略是根据修改时间戳选择最新的数据,当然用户也可以自定义冲突处理方法。读取过程中如果发现某些副本上的数据版本太旧,Dynamo内部会异步发起一次读取修复操作,使用冲突解决后的结果修正错误的副本。
标注 (粉色) - 第5章 分布式键值系统 > 位置 1735
Dynamo设计支持可插拔的存储引擎,比如Berkerly DB(BDB),MySQL InnoDB等。
标注 (粉色) - 第5章 分布式键值系统 > 位置 1746
Dynamo采用无中心节点的P2P设计,增加了系统可扩展性,但同时带来了一致性问题,影响上层应用。另外,一致性问题也使得异常情况下的测试变得更加困难,由于Dynamo只保证最基本的最终一致性,多客户端并发操作的时候很难预测操作结果,也很难预测不一致的时间窗口,影响测试用例设计。
标注 (粉色) - 第5章 分布式键值系统 > 位置 1749
主流的分布式系统一般都带有中心节点,这样能够简化设计,而且中心节点只维护少量元数据,一般不会成为性能瓶颈。
标注 (粉色) - 第5章 分布式键值系统 > 位置 1751
无中心节点的设计短期之内难以成为主流
标注 (粉色) - 第5章 分布式键值系统 > 位置 1753
Tair是淘宝开发的一个分布式键/值存储引擎。Tair分为持久化和非持久化两种使用方式:非持久化的Tair可以看成是一个分布式缓存,持久化的Tair将数据存放于磁盘中。
标注 (粉色) - 第5章 分布式键值系统 > 位置 1758
Tair作为一个分布式系统,是由一个中心控制节点和若干个服务节点组成。其中,中心控制节点称为Config Server,服务节点称为Data Server。Config Server负责管理所有的Data Server,维护其状态信息;Data Server对外提供各种数据服务,并以心跳的形式将自身状况汇报给Config Server。Config Server是控制点,而且是单点,目前采用一主一备的形式来保证可靠性,所有的Data Server地位都是等价的。
标注 (粉色) - 第5章 分布式键值系统 > 位置 1765
根据数据的主键计算哈希值后,分布到Q个桶中,桶是负载均衡和数据迁移的基本单位。Config Server按照一定的策略把每个桶指派到不同的Data Server上
标注 (粉色) - 第5章 分布式键值系统 > 位置 1769
当某台Data Server故障不可用时,Config Server能够检测到。每个哈希桶在Tair中存储多个副本,如果是备副本,那么Config Server会重新为其指定一台Data Server,如果是持久化存储,还将复制数据到新的Data Server上。如果是主副本,那么ConfigServer首先将某个正常的备副本提升为主副本,对外提供服务。接着,再选择另外一台Data Server增加一个备副本,确保数据的备份数。
标注 (粉色) - 第5章 分布式键值系统 > 位置 1772
机器加入或者负载不均衡可能导致桶迁移,迁移的过程中需要保证对外服务。当迁移发生时,假设Data Server A要把桶3、4、5迁移到Data Server B。迁移完成前,客户端的路由表没有变化,客户端对3、4、5的访问请求都会路由到A。现在假设3还没开始迁移,4正在迁移中,5已经迁移完成。那么如果对3访问,A直接服务;如果对5访问,A会把请求转发给B,并且将B的返回结果返回给用户;如果对4访问,由A处理,同时如果是对4的修改操作,会记录修改日志,等到桶4迁移完成时,还要把修改日志发送到B,在B上应用这些修改操作,直到A和B之间数据完全一致迁移才真正完成。
标注 (粉色) - 第5章 分布式键值系统 > 位置 1787
Tair默认包含两个存储引擎:Mdb和Fdb,此外,还支持Berkerly DB、Tokyo Cabinet、InnoDB、Leveldb等各种存储引擎。
标注 (粉色) - 第5章 分布式键值系统 > 位置 1788
Amazon Dynamo采用P2P架构,而在Tair中引入了中心节点Config Server。这种方式很容易处理数据的一致性,不再需要向量时钟、数据回传、Merkle树、冲突处理等复杂的P2P技术。另外,中心节点的负载很低。笔者认为,分布式键值系统的整体架构应该参考Tair,而不是Dynamo。
标注 (粉色) - 第5章 分布式键值系统 > 位置 1791
Tair最主要的用途在于分布式缓存,持久化存储起步比较晚,在实现细节上也有一些不尽如人意的地方。例如,Tair持久化存储通过复制技术来提高可靠性,然而,这种复制是异步的。因此,当有Data Server发生故障时,客户有可能在一定时间内读不到最新的数据,甚至发生最新修改的数据丢失的情况。

标签:副本,架构,存储系统,粉色,分布式系统,数据,节点,分布式
来源: https://www.cnblogs.com/Mike_Chang/p/11619782.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有