《大规模分布式存储系统》读书笔记(一)

序言

与单机环境下编程相比,分布式环境下的编程有两点不同:

  1. 分布式环境下,会出现一部分计算机工作正常,另一部分计算机工作不正常的情况,程序需要在这种情况下尽可能地正常工作,挑战非常大。
  2. 单机环境下,大部分函数采用同步调用;在分布式环境下,函数调用的返回时间可能是单机环境下的100倍,所以分布式环境下的RPC通常采用异步调用

第一章  概述

 1、分布式存储分类

数据的种类大致可以分为三类:

  1. 非结构化数据,比如图像,音频,视频等。
  2. 机构化数据,储存在关系数据库中,可以用关系表结构来表示的。
  3. 半结构化数据,模式化结构和内容混在一起,比如 HTML 文档,XML。

 根据储存数据种类的不同,可以将储存系统分为以下几类:

  1. 分布式文件系统,存储非结构化数据,典型的系统有 Facebook Haystack,Taobao File Systen。
  2. 分布式键值系统,存储关系简单的半结构化数据,典型的有 Memcache 。
  3. 分布式表格系统,存储关系较为复杂的半结构化数据, 典型的有 Google Bigtable 。
  4. 分布式数据库,存储结构化数据。典型的系统有 MySQL 。

第二章  单机存储系统

1、硬件基础

  传统的数据中心网络拓扑为三层结构,该网络拓扑下,同一接入层下服务器之间带宽相同,不同接入层的服务器带宽会出现不一致的情况,因此,设计系统时需要考虑服务器是否在一个机架内。

  为了减少系统对网络拓扑结构的依赖,可以采用三级 CLOS 网络,使得任何两台服务器之间的带宽都相同。

2、单机存储引擎

2.1  哈希存储引擎

  Bitcask 是基于哈希表结构的键值存储系统,仅支持追加操作。内存中采用的是基于哈希表的索引,哈希表结构中的每一项包含文件编号(file_id),value 在文件中的位置(value_pos),value 长度(value_sz)。通过读取 file_id 对应的文件,从 value_pos 开始的 value_sz 个字节,就可得到 value 值。

扫描二维码关注公众号,回复: 5711305 查看本文章

2.2  B 树存储引擎

  叶子节点保存每行的完整数据,非叶子节点保存索引信息。数据库查询时从根节点开始二分查找到叶子节点,每次读取节点时,如果节点不在内存中,需要从磁盘中读取并缓存。

  缓冲区管理器会决定哪些页面淘汰,缓冲区的替换策略有以下两种:

  1. LRU,淘汰最长事件没有读或者写的块。
  2. LIRS,将缓冲池分为两级,数据首先进入第一级,如果数据在较短时间内被访问两次或者以上,则成为热点数据进入第一级,每一级内部还是采用LRU 算法。

 2.3  LSM树存储引擎

  LSM 树就是将对数据的修改增量保持在内存中,达到指定大小后将这些修改操作批量写入磁盘,读取时需要合并磁盘中的历史数据和内存中最近的修改操作。

  LevelDB 存储引擎包括:内存中的 MemTable 和不可变的 MemTable。写入记录时,LevelDB 会先将修改操作写入操作日志,之后再将修改操作应用到 MemTable,这样就完成了写入操作。MemTable 的大小达到上限值后,LevelDB 会将原先的 MemTable 变成不可变 MemTable,并重新生成新的MemTable,之后的修改操作记录在新的 MemTable 中。同时 LevelDB 后台线程会将不可变 MemTable 的数据转储到磁盘。

3、故障恢复

  分布式系统一般使用操作日志技术来实现故障恢复。操作日志可以分为回滚日志(undo log)重做日志(redo log)。回滚日志记录的是事务修改前的状态,重做日志记录的是事务修改之后的状态。

3.1  操作日志

  为了数据库数据的一致性,数据库操作需要持久化到磁盘,如果每次操作都更新磁盘上的数据,系统性能会较差。操作日志上面记录的就是每个数据库操作,并在内存中执行这些操作,内存中的数据定时刷新到磁盘,就可以实现随机写请求转化为顺序写请求。

3.2  重做日志

  使用 REDO 日志进行故障恢复,必须确保,在修改内存中的数据之前,把这一修改相关的操作日志刷新到磁盘上。这么做的原因在于,假设是先修改内存数据,如果在完成内存修改和写入日志之间发生故障,那么最近的修改操作没有办法通过 REDO 日志恢复,用户可能读取到修改后的结果,出现不一致的情况。

3.3  成组提交

  之前说过,数据库操作需要先写入操作日志,但是如果每次操作都立即将操作日志刷人磁盘,系统性能会降低。因此可以先将 REDO 日志储存在缓冲区,定期刷入磁盘。但这样做,可能会丢失最后一部分数据库操作。

3.4  检查点 

  当内存不足,或者 REDO 日志的大小达到上限时,需要将内存中修改后的数据刷新到磁盘上,这种技术就是 checkpoint(检查点)技术。同时系统会加入 checkpoint 时刻,以后的故障恢复只需要回放 checkpoint 时刻之后的 REDO 日志。


 第三章  分布式系统

1、基本概念

1.1  “超时”

  在分布式系统中,如果一个节点发起 RPC 调用,RPC 执行结果有三种:“成功”,“失败”,“超时”。当出现超时状态时,不能简单的认为 RPC 操作失败,只能通过不断读取之前操作的状态来验证 RPC 操作是否成功。当然,可以将系统设计为幂等性

1.2  一致性

  保证多个副本之间的一致性是分布式系统的核心。例如有 A,B,C 同时操作存储系统,可以将一致性大致分别三种:

  1. 强一致性,A 写入值,后续  A,B,C 读取的都是最新值。
  2. 弱一致性,A 写入值,不能保证后续  A,B,C 读取的都是最新值。
  3. 最终一致性,A 写入值,在后续没有更新该值,则后续  A,B,C 读取的都是最新值。有一个“不一致窗口”的概念。

2、数据分布

  分布式系统不同于传统的单机系统,分布式系统能够将数据分布到多个节点,在多个节点间实现负载均衡。以下介绍的是数据分布的两种方式。

2.1  哈希分布

  哈希分布就是根据数据的某一特征计算哈希值,哈希值与服务器有映射关系,以此实现数据的分布。哈希分布的优劣取决于散列函数的特征,容易出现“数据倾斜”的问题。而且,当有服务器上线或者下线时,哈希映射会被打乱,会带来大量的数据迁移。

  一致性哈希可以避免集群扩容造成的大量数据迁移问题。其思想是:系统中的每个节点都分配一个 token,这些 token 构成哈希环。储存数据时,先计算数据的哈希值,然后存放到顺时针第一个大于或者等于该哈希值的节点。这样在增加、删除节点时,只会影响到哈希环中相邻的节点。一致性哈希可以采用虚拟节点的发放来实现负载均衡。

2.2  顺序分布

  哈希分布实现数据分布时,不能支持顺序扫描。顺序分布可以提供连续的范围扫描,一般做法是将大表顺序分为连续的范围,每个范围一个子表。Bigtable 系统将索引分为两级,Root 表和元数据 Meta 表,由 Meta 表维护 User 表的位置信息, Root 表维护 Meta 表的位置信息。

3、复制

3.1  复制的概念

  在分布式系统中,同一份数据有多个副本,其中一个副本为主副本,其他为备副本。复制时,由主副本将数据复制到备份副本。复制协议可以分为强同步复制和异步复制。

  强同步复制要求主备成功后才可以返回成功,可以保证强一致性,但是,复制时是阻塞写操作,系统可用性较差。

  异步复制就是主副本不需要等待备副本的回应,只需要本地修改成功就可以返回成功。

  上述两种复制协议都是主副本将数据发送给其他副本,当主副本出现故障时,需要选择新的主副本。经典的选举协议为 Paxos 协议。

3.2  一致性和可用性

  CAP 理论就是:一致性(Consistency),可用性(Availability),分区可容忍性(Tolerance of network Partition)三者不能同时满足。

  分区可容忍性指的是在机器故障、网站故障等异常情况下仍然满足一致性和可用性。

  设计存储系统时需要在一致性和可用性之间权衡。如果采用强同步复制,保证系统的一致性,当主备副本之间出现故障时,写操作被阻塞,系统的可用性将无法满足。如果采用异步复制,保证了可用性,但无法做到一致性。

  Oracle 数据库的 DataGuard 复制组件有三种模式,可以借鉴:

  1. 最大保护模式:即强同步模式
  2. 最大性能模式:即异步复制模式
  3. 最大可用模式:正常情况是最大保护模式,主备间出现故障时,切换为最大性能模式。

4、容错

4.1  故障检测

  故障检测可以使用心跳的方式来做,但并不能保证机器一定出现了故障,可能是机器 A 和机器 B 之间的网络发生问题。

  通常使用租约机制来进行故障检测。租约机制就是:机器 A 向 机器 B 发放租约,机器 B 在持有租约的有效期内才允许提供服务,否则主动停止服务,机器 B 可以再租约快要到期的时候向机器 A 重新申请租约。

4.2  故障恢复

  总控节点检测到工作机器出现故障时,需要将服务迁移到其他工作机节点。总控节点本身可有可能出现故障,也需要将自身状态实行同步到备机。

  分布式存储系统的总控节点只需要维护数据的位置信息,通常不会成为瓶颈。如果成为瓶颈,可以采用两级结构:

5、可扩展性

5.1  数据库扩容

  数据库扩容的手段有:

  • 通过主从复制提高系统的读写能力
  • 通过垂直拆分和水平拆分将数据分布到多个节点

  

  传统的数据库为同构系统,在扩容上不够灵活。同一组内的节点存储相同的数据,在增加副本时需要迁移的数据量太大。

 

  异构系统将数据划分为很多大小接近的分片,每个分片的多个副本可以分布 到集群中的任何一个存储节点。如果某个节点发生故障,原有的服务将由整个集群而不 是某几个固定的存储节点来恢复。如图3-9所示,系统中有五个分片(A, B, C, D, E),每个分片包含三个副本, 如分片A的三个副本分别为Al, A2以及A3。假设节点1发生永久性故障,那么可以 从剩余的节点中任意选择健康的节点来增加A, B以及E的副本。由于整个集群都参与 到节点1的故障恢复过程,故障恢复时间很短,而且集群规模越大,优势就会越明显。

6、分布式协议

6.1  两阶段提交协议

  两阶段提交协议(2PC)用来保证跨节点操作的原子性。该协议中,将系统节点分为:协调者事务参与者。正常执行过程如下:

  1. 请求阶段协调者通知事务参与者准备提交(事务参与者本地执行成功)或者取消(事务参与者本地执行失败)事务。
  2. 提交阶段,协调者根据请求阶段的结果进行决策:提交或者取消。只有所有事务参与者都同意提交时,协调者才会通知所有的参与者提交事务,否则取消事务

  两阶段提交协议可能面临的故障:

  1. 事务参与者发生故障。给事务设置超时时间,达到超时时间后整个事务失败。
  2. 协调者发生故障。可以备用协调者。

  两阶段提交协议是阻塞协议,执行期间要锁住其他更新,且不能容错。大多数分布式存储系统都对之避而远之。

6.2  Paxos 协议

  Paxos 协议用来解决多个节点之间的一致性问题。当主节点出现故障时,Paxos 协议可以在多个备节点中选举出唯一的主节点。

  Paxos 协议的两种用法:

  1. 用它来实现全局的锁服务或者命名和配置服务
  2. 用它来将用户数据复制到多个数据中心

  paxos 协议怎么做的???待填坑!!!

6.3 Paxos 与 2PC

  2PC 可以和 Paxos 协议结合起来,通过 2PC 保证多个数据分片上的操作的原子性,通过 Paxos 协议实现同一数据分片的多个副本之间的一致性。另外,通过 Paxos 协议解决 2PC 协议中协调者出现故障的问题。当 2PC 协议中的协调者出现故障时,通过 Paxos 协议选举出新的协调者继续提供服务。

 

猜你喜欢

转载自www.cnblogs.com/lizhimin123/p/10619695.html