最近看完了杨传辉老师写的《大规模分布式存储系统》一书,发现里面不少知识点和以前看的《大型网站系统与Java中间件》有不少相通之处,也渐渐加 深了我对分布式技术的兴趣。但无奈分布式涵盖范围太广了,分布式存储、分布式计算、CAP理论、Paxos算法、什么GFS、Hadoop、 Dynamo、BigTable、Spanner等等,不下点功夫还真不能理顺它们之间的内在关系。因此结合两书以及一些优秀博文,总结了分布式存储的知 识体系,为之后打下基础而努力。因为初入泥潭,必然有些理解不当的地方,如有大神路过还望不吝指教。html
本文更像是读书笔记,是对知识点的一个梳理,无奈越写越多,部分知识只能点到为止,具体内容能够查看原书或维基百科。算法
哈 希存储引擎是哈希表的持久化实现,支持增、删、改,以及随机读取操做,但不支持顺序扫描,对应的存储系统为键值(Key-Value)存储系统,如 Bitcask。它仅支持追加操做,删除也只是经过标识 value 为特殊值,经过按期合并(Compaction)实现垃圾回收。sql
B 树存储引擎是 B 树的持久化实现,不只支持单条记录的增、删、读、改操做,还支持顺序扫描,对应的存储系统是关系数据库。关系数据库中经过索引访问数据,在 Mysql InnoDB 中,有一个称为汇集索引的东西,行的数据存于其中,组织成 B+ 树的结构。更多 B 系树的内容能够参考 这里 。数据库
LSM 树(Log Structure Merge Tree)存储引擎采用批量转储技术来避免磁盘随机写入。其思想很朴素,就是将对数据的修改增量保持在内存中,达到指定的大小限制后将这些修改操做批量写 入磁盘。它普遍应用于互联网的后台存储系统, 例如 Google BigTable、 以及 Facebook 开源的 Cassandra系统。缓存
单机存储随着业务的增加会遇到性能与单点故障问题。一般有两种解决方案:服务器
这两种方法都能解决性能上的问题,通常结合使用。而对于数据丢失的问题,咱们只能经过第二种方法来完成——数据的冗余存储。可是加入更多的机器,会 致使事情变得复杂起来,尤为是分布式事务处理,也就是多台服务器之间的数据如何保持一致性,由于原先单机的 ACID 特性在分布式环境下都用不了了。网络
数据分布主要有两种方式:一种是哈希分布,如一致性哈希(Dynamo);另外一种是顺序分布(BigTable)。考虑因素包括读写场景, 即随机仍是顺序, 包括如何保证负载均衡从而提升性能等数据结构
传统的哈希分布算法简单的将哈希值与服务器个数作除法取模映射。可是当服务器上下线时,数据的从新分布会带来大量的数据迁移。架构
所以有了 一致性哈希算法 。算法思想以下 :给系统中每一个节点分配一个随机 token,这些 token 构成一个哈希环。执行数据存放操做时,先计算 Key(主键)的哈希值,而后存放到顺时针方向第一个大于或者等于该哈希值的 token 所在的节点。一致性哈希的优势在于节点加入 / 删除时只会影响到在哈希环中相邻的节点,而对其余节点没影响。增长节点后能很大程度上避免了数据迁移。为了考虑负载均衡,通常还会引入虚拟节点的技术,即 一个物理节点会对应着多个虚拟节点(如 Dynamo)。并发
复制协议有两种:强同步复制,异步复制。 区别在于用户的写请求是否须要同步到备副本才能够返回成功。
一致性和可用性是矛盾的。强同步复制协议保证主备副本之间的一致性,可是当备副本出现故障时会影响系统可用性。异步复制协议的可用性较好,可是一致性得不到保障,主副本出现故障时还有数据丢失的可能。
这两种协议都是将主副本的数据以某种形式(多为操做日志)发送到其余副本,这种复制协议称为基于主副本的复制协议。固然还有基于多个存储节点的复制协议。好比下面会介绍的 Dynamo 系统的 NWR 复制协议。
设计分布式系统的前提就是假定服务器时刻肯能发生故障。故障检测主要有心跳和租约两种机制。
提及数据一致性,简单说有三种类型(细分会有不少,此处不展开):
从这三种一致型的模型上来讲,咱们能够看到,Weak 和 Eventually 通常来讲是异步冗余的,而Strong通常来讲是同步冗余的,异步的一般意味着更好的性能,但也意味着更复杂的状态控制。同步意味着简单,但也意味着性能降低。
事务的支持对于业务是很是重要的特性,数据库在单机下的 ACID 事务特性是比较到位的,而一旦进行分库分表后就要面对一致性和可用性的问题了,这就是分布式事务了。
在分布式环境下须要考虑数据的一致性和性能的问题,咱们要了解下 CAP 理论:
在分布式系统中,对于这三者不能同时知足。这就是 CAP 理论。
简单地说就是:
1)要想让数据避免单点故障,就得写多份数据。
2)写多份的问题会致使数据一致性的问题。
3)数据一致性的问题又会引起性能问题
NWR 是一种在分布式存储系统中用于控制一致性级别的策略,应用于 Amazon Dynamo。NWR 模型将 CAP 的选择权交给了用户,由用户本身选择 CAP 中的哪两个。其中,N 表明 N 个备份,W 表明至少写 W 份才认为成功,R 表明至少要读 R 份才认为成功。
英文 Two Phase Commit,也叫 2PC。两阶段提交常常用于分布式事务,是强一致性算法。简要的说就是分两阶段:
第一阶段,主控节点(协调者)询问全部节点(参与者)是否能够提交操做,参与者回应 yes or no。
第二阶段,协调者根据收到的响 应,若是全部参与者都回应 yes,则向全部参与者发送“正式提交”的命令。参与者完成后恢复“完成”消息,协调者收集齐各节点的回应后结束这个 Global Transaction。若是有一个拒绝则给全部参与者发送“回滚操做”。参与者回滚成功后回应“回滚完成”,协调者收集各结点的“回滚”回应后,取消这 个 Global Transaction。
2PC说白了就是第一阶段作 Vote,第二阶段作决定的一个算法,相对于单库事务来讲就是在提交以前多了准备的阶段。可是也存在着问题,其中一个是同步阻塞操做,这个事情必然会很是 大地影响性能。另外一个主要的问题是在TimeOut上。所以出现了 3PC,主要是将提交过程分为两步,更多描述见 Wikipedia。
Google Chubby 的做者 Mike Burrows 说过,“世上只有一种一致性算法,那就是 Paxos”,全部其余一致性算法都是Paxos算法的残次版本。
Paxos是一个分布式选举算法, 最大的用途就是保持多个节点数据的一致性。看了很久的 Paxos 算法仍是有些迷糊,这里就不给出具体算法了。感兴趣的能够参看 WikiPedia 以及里面给出的示例。
实际上对于通常的开发人员,咱们并不须要了解 Paxos 全部细节及如何实现,只须要知道 Paxos 是一个分布式选举算法就够了。当咱们之后遇到类似的问题,知道有这样一个技术,能够正确及优雅地解决技术架构上一些难题就够了。
Paxos 协议和 2PC 协议在分布式系统中所起的做用并不相同。Paxos 协议用于保证同一个数据分片的多个副本之间的数据一致性。当这些副本分布到不一样的数据中心时,这个需求尤为强烈。2PC 协议用于保证属于多个数据分片上的操做的原子性。这些数据分片可能分布在不一样的服务器上,2PC 协议保证多台服务器上的操做要么所有成功,要么所有失败。可见 Paxos 的学术地位不通常。
Paxos 协议有两种用法:一种用法是用它来实现全局的锁服务或者命名和配置服务,例如 Google Chubby 以及 Apache Zookeeper 还有全局ID。另一种用法是用它来将用户数据复制到多个数据中心,例如 Google Megastore 以及 Google Spanner。
2PC 协议最大的缺陷在于没法处理协调者宕机问题。若是协调者宕机,那么,2PC协议中的每一个参与者可能都不知道事务应该提交仍是回滚,整个协议被阻塞,执行过 程中申请的资源都没法释放。所以,常见的作法是将 2PC 和 Paxos 协议结合起来,经过2PC 保证多个数据分片上的操做的原子性,经过 Paxos 协议实现同一个数据分片的多个副本之间的一致性。另外,经过 Paxos 协议解决 2PC 协议中协调者宕机问题。当 2PC协议中的协调者出现故障时,经过 Paxos 协议选举出新的协调者继续提供服务。
下图是几种策略原理的比较,来源于:Google App Engine的 co-founder Ryan Barrett在2009年的google i/o上的演讲《Transaction Across DataCenter》(视频)
图中 M/S 是 Master-Slave) 结构,实现简单,可是存在单点故障和数据丢失的问题。M/M 即 Multi-Master,解决了单点故障可是一致性的实现较复杂且存在冲突合并的问题(Vector Clock解决)。从上图咱们能够看到,咱们基本上来讲不可让全部的项都绿起来,也就是以前说到的著名的CAP理论:一致性,可用性,分区容忍性,你只可能要其中的两个。
分布式文件系统用于存储 Blob 对象,典型的系统有 Facebook Haystack 以及 Taobao File System(TFS)。分布式文件系统是分布式的基石,一般做为上层系统的底层存储。
整体上看,分布式文件系统存储三种类型的数据 :Blob 对象、定长块以及大文件。在系统实现层面,分布式文件系统内部按照数据块(chunk)来组织数据,每一个 chunk 的大小大体相同,每一个 chunk 能够包含多个 Blob 对象或者定长块,一个大文件也能够拆分为多个 chunk 。
分布式键值系统用于存储关系简单的半结构化数据,它只提供基于主键的 CRUD(Create/Read/Update/Delete)功能。
典型的系统有 Amazon Dynamo 以及 Taobao Tair。从数据结构的角度看,分布式键值系统与传统的哈希表比较相似,不一样的是,分布式键值系统支持将数据分布到集群中的多个存储节点。分布式键值系统 是分布式表格系统的一种简化实现,通常用做缓存,好比淘宝 Tair 以及 Memcache。一致性哈希是分布式键值系统中经常使用的数据分布技术。
分布式表格系统用于存储关系较为复杂的半结构化数据。分布式表格系统以表格为单位组织数据,每一个表格包括不少行,经过主键标识一行,支持根据主键的 CRUD 功能以及范围查找功能。
典型的系统包括 Google Bigtable 以及 Megastore,Microsoft Azure Table Storage,Amazon DynamoDB 等。在分布式表格系统中,同一个表格的多个数据行也不要求包含相同类型的列,适合半结构化数据。
分布式数据库通常是从单机关系数据库扩展而来,用于存储结构化数据。分布式数据库采用二维表格组织数据,提供 SQL 关系查询语言,支持多表关联,嵌套子查询等复杂操做,并提供数据库事务以及并发控制。
典型的系统包括 MySQL 数据库分片(MySQL Sharding)集群,Amazon RDS 以及Microsoft SQL Azure。分布式数据库支持的功能最为丰富,符合用户使用习惯,但可扩展性每每受到限制。固然,这一点并非绝对的。Google Spanner 的扩展性就达到了全球级,它不只支持丰富的关系数据库功能,还能扩展到多个数据中心的成千上万台机器。除此以外,阿里巴巴 OceanBase 也是一个支持自动扩展的分布式关系数据库。
书中有不少对于分布式的观点对我启发很大,将之引用以下。
“简单就是美。系统开发过程当中,若是某个方案很复杂,通常是实践者没有想清楚。”。关于这一点其实很早就据说过,就像贯穿UNIX哲学的 KISS原则(Keep It Simple,Stupid),而做者经过开发复杂的分布式存储系统过程当中得出这么宝贵经验,是“简单就是美”最好的注解。
中心化 VS 去中心。“主流的分布式系统通常都带有中心节点,这样可以简化设计,并且中心节点只维护少许元数据,通常不会成为性能瓶颈。在实践中 Dynamo 及其开源实现 Cassandra 受到的关注逐渐减小,去中心的设计短时间内难以成为主流。”