与单机环境下编程相比,分布式环境下的编程有两点不一样:算法
数据的种类大体能够分为三类:数据库
根据储存数据种类的不一样,能够将储存系统分为如下几类:编程
传统的数据中心网络拓扑为三层结构,该网络拓扑下,同一接入层下服务器之间带宽相同,不一样接入层的服务器带宽会出现不一致的状况,所以,设计系统时须要考虑服务器是否在一个机架内。缓存
为了减小系统对网络拓扑结构的依赖,能够采用三级 CLOS 网络,使得任何两台服务器之间的带宽都相同。服务器
Bitcask 是基于哈希表结构的键值存储系统,仅支持追加操做。内存中采用的是基于哈希表的索引,哈希表结构中的每一项包含文件编号(file_id),value 在文件中的位置(value_pos),value 长度(value_sz)。经过读取 file_id 对应的文件,从 value_pos 开始的 value_sz 个字节,就可获得 value 值。网络
叶子节点保存每行的完整数据,非叶子节点保存索引信息。数据库查询时从根节点开始二分查找到叶子节点,每次读取节点时,若是节点不在内存中,须要从磁盘中读取并缓存。负载均衡
缓冲区管理器会决定哪些页面淘汰,缓冲区的替换策略有如下两种:异步
LSM 树就是将对数据的修改增量保持在内存中,达到指定大小后将这些修改操做批量写入磁盘,读取时须要合并磁盘中的历史数据和内存中最近的修改操做。分布式
LevelDB 存储引擎包括:内存中的 MemTable 和不可变的 MemTable。写入记录时,LevelDB 会先将修改操做写入操做日志,以后再将修改操做应用到 MemTable,这样就完成了写入操做。MemTable 的大小达到上限值后,LevelDB 会将原先的 MemTable 变成不可变 MemTable,并从新生成新的MemTable,以后的修改操做记录在新的 MemTable 中。同时 LevelDB 后台线程会将不可变 MemTable 的数据转储到磁盘。函数
分布式系统通常使用操做日志技术来实现故障恢复。操做日志能够分为回滚日志(undo log),重作日志(redo log)。回滚日志记录的是事务修改前的状态,重作日志记录的是事务修改以后的状态。
为了数据库数据的一致性,数据库操做须要持久化到磁盘,若是每次操做都更新磁盘上的数据,系统性能会较差。操做日志上面记录的就是每一个数据库操做,并在内存中执行这些操做,内存中的数据定时刷新到磁盘,就能够实现随机写请求转化为顺序写请求。
使用 REDO 日志进行故障恢复,必须确保,在修改内存中的数据以前,把这一修改相关的操做日志刷新到磁盘上。这么作的缘由在于,假设是先修改内存数据,若是在完成内存修改和写入日志之间发生故障,那么最近的修改操做没有办法经过 REDO 日志恢复,用户可能读取到修改后的结果,出现不一致的状况。
以前说过,数据库操做须要先写入操做日志,可是若是每次操做都当即将操做日志刷人磁盘,系统性能会下降。所以能够先将 REDO 日志储存在缓冲区,按期刷入磁盘。但这样作,可能会丢失最后一部分数据库操做。
当内存不足,或者 REDO 日志的大小达到上限时,须要将内存中修改后的数据刷新到磁盘上,这种技术就是 checkpoint(检查点)技术。同时系统会加入 checkpoint 时刻,之后的故障恢复只须要回放 checkpoint 时刻以后的 REDO 日志。
在分布式系统中,若是一个节点发起 RPC 调用,RPC 执行结果有三种:“成功”,“失败”,“超时”。当出现超时状态时,不能简单的认为 RPC 操做失败,只能经过不断读取以前操做的状态来验证 RPC 操做是否成功。固然,能够将系统设计为幂等性。
保证多个副本之间的一致性是分布式系统的核心。例若有 A,B,C 同时操做存储系统,能够将一致性大体分别三种:
分布式系统不一样于传统的单机系统,分布式系统可以将数据分布到多个节点,在多个节点间实现负载均衡。如下介绍的是数据分布的两种方式。
哈希分布就是根据数据的某一特征计算哈希值,哈希值与服务器有映射关系,以此实现数据的分布。哈希分布的优劣取决于散列函数的特征,容易出现“数据倾斜”的问题。并且,当有服务器上线或者下线时,哈希映射会被打乱,会带来大量的数据迁移。
一致性哈希能够避免集群扩容形成的大量数据迁移问题。其思想是:系统中的每一个节点都分配一个 token,这些 token 构成哈希环。储存数据时,先计算数据的哈希值,而后存放到顺时针第一个大于或者等于该哈希值的节点。这样在增长、删除节点时,只会影响到哈希环中相邻的节点。一致性哈希能够采用虚拟节点的发放来实现负载均衡。
哈希分布实现数据分布时,不能支持顺序扫描。顺序分布能够提供连续的范围扫描,通常作法是将大表顺序分为连续的范围,每一个范围一个子表。Bigtable 系统将索引分为两级,Root 表和元数据 Meta 表,由 Meta 表维护 User 表的位置信息, Root 表维护 Meta 表的位置信息。
在分布式系统中,同一份数据有多个副本,其中一个副本为主副本,其余为备副本。复制时,由主副本将数据复制到备份副本。复制协议能够分为强同步复制和异步复制。
强同步复制要求主备成功后才能够返回成功,能够保证强一致性,可是,复制时是阻塞写操做,系统可用性较差。
异步复制就是主副本不须要等待备副本的回应,只须要本地修改为功就能够返回成功。
上述两种复制协议都是主副本将数据发送给其余副本,当主副本出现故障时,须要选择新的主副本。经典的选举协议为 Paxos 协议。
CAP 理论就是:一致性(Consistency),可用性(Availability),分区可容忍性(Tolerance of network Partition)三者不能同时知足。
分区可容忍性指的是在机器故障、网站故障等异常状况下仍然知足一致性和可用性。
设计存储系统时须要在一致性和可用性之间权衡。若是采用强同步复制,保证系统的一致性,当主备副本之间出现故障时,写操做被阻塞,系统的可用性将没法知足。若是采用异步复制,保证了可用性,但没法作到一致性。
Oracle 数据库的 DataGuard 复制组件有三种模式,能够借鉴:
故障检测可使用心跳的方式来作,但并不能保证机器必定出现了故障,多是机器 A 和机器 B 之间的网络发生问题。
一般使用租约机制来进行故障检测。租约机制就是:机器 A 向 机器 B 发放租约,机器 B 在持有租约的有效期内才容许提供服务,不然主动中止服务,机器 B 能够再租约快要到期的时候向机器 A 从新申请租约。
总控节点检测到工做机器出现故障时,须要将服务迁移到其余工做机节点。总控节点自己可有可能出现故障,也须要将自身状态实行同步到备机。
分布式存储系统的总控节点只须要维护数据的位置信息,一般不会成为瓶颈。若是成为瓶颈,能够采用两级结构:
数据库扩容的手段有:
传统的数据库为同构系统,在扩容上不够灵活。同一组内的节点存储相同的数据,在增长副本时须要迁移的数据量太大。
、
异构系统将数据划分为不少大小接近的分片,每一个分片的多个副本能够分布 到集群中的任何一个存储节点。若是某个节点发生故障,原有的服务将由整个集群而不 是某几个固定的存储节点来恢复。如图3-9所示,系统中有五个分片(A, B, C, D, E),每一个分片包含三个副本, 如分片A的三个副本分别为Al, A2以及A3。假设节点1发生永久性故障,那么能够 从剩余的节点中任意选择健康的节点来增长A, B以及E的副本。因为整个集群都参与 到节点1的故障恢复过程,故障恢复时间很短,并且集群规模越大,优点就会越明显。
两阶段提交协议(2PC)用来保证跨节点操做的原子性。该协议中,将系统节点分为:协调者和事务参与者。正常执行过程以下:
两阶段提交协议可能面临的故障:
两阶段提交协议是阻塞协议,执行期间要锁住其余更新,且不能容错。大多数分布式存储系统都对之避而远之。
Paxos 协议用来解决多个节点之间的一致性问题。当主节点出现故障时,Paxos 协议能够在多个备节点中选举出惟一的主节点。
Paxos 协议的两种用法:
paxos 协议怎么作的???待填坑!!!
2PC 能够和 Paxos 协议结合起来,经过 2PC 保证多个数据分片上的操做的原子性,经过 Paxos 协议实现同一数据分片的多个副本之间的一致性。另外,经过 Paxos 协议解决 2PC 协议中协调者出现故障的问题。当 2PC 协议中的协调者出现故障时,经过 Paxos 协议选举出新的协调者继续提供服务。