元数据记录了分片与节点的映射关系、节点状态等核心信息,分布式系统中,有专门的节点(节点集群)来管理元数据,我们称之为元数据服务器。元数据服务器有以下特点:
高性能:cache
高可用:冗余 加 快速failover
强一致性(同时只有一个节点对外提供服务)
第六:任务的动态均衡为了达到动态均衡,需要进行数据的迁移,如何保证迁移的时候同时对外提供服务,这是一个需要精心设计的工程实践问题。
可用性
可用性(Availability)是系统不间断对外提供服务的能力,可用性是一个度的问题,最高目标就是7 * 24,永远在线。但事实上做不到的,一般是用几个9来衡量系统的可用性,如下如所示:
也就是如果要达到4个9的可用度(99.99%),那么一年之中只能有52.6分钟不可用,这是个巨大的挑战
为什么分布式系统中必须要考虑可用性呢,这是因为分布式系统中故障的概率很高。分布式系统由大量异构的节点和网络组成,节点可能会crash、断电、磁盘损坏,网络可能丢包、延迟、网络分割。系统的规模放大的出故障的概率,因此分布式系统中,故障是常态。那么分布式系统的设计目标就是容错,在部分故障的情况下仍然对外提供服务,这就是可用性。
冗余是提高可用性、可靠性的法宝。
冗余就是说多个节点负责相同的任务,在需要状态维护的场景,比如分布式存储中使用非常广泛。在分布式计算,如MapReduce中,当一个worker运行异常缓慢时,master会将这个worker上的任务重新调度到其它worker,以提高系统的吞吐,这也算一种冗余。但存储的冗余相比计算而言要复杂许多,因此主要考虑存储的冗余。
维护同一份数据的多个节点称之为多个副本。我们考虑一个问题,当向这个副本集写入数据的时候,怎么保证并发情况下数据的一致性,是否有一个节点有决定更新的顺序。这就是中心化、去中心话副本协议的区别。
中心化与去中心化中心化就是又一个主节点(primary master)负责调度数据的更新,其优点是协议简单,将并发操作转变为顺序操作,缺点时primary成为瓶颈,在primary故障的时候重新选举会有一段时间的不可用。
去中心化就是所有节点地位平等,都能够发起数据的更新,优点时高可用,缺点时协议复杂,要保证一致性很难。
提到去中心化,比较有名的是dynamo,cassandra,使用了quorum、vector clock等算法来尽量保证去中心化环境下的一致性。对于去中心化这一块,目前还没怎么学习,所以下面主要讨论中心化副本集。对于中心化副本协议,我在《带着问题学习分布式之中心化复制集》一文中也有详细介绍,这里简单归纳总结
节点更新策略primary节点到secondary节点的数据时同步还是异步,即客户端是否需要等待数据落地到副本集中的所有节点。
同步的优点在于强一致性,但是可用性和性能(响应延迟)比较差;异步则相反。
数据流向即数据是如何从Primary节点到secondary节点的,有链式和主从模式。
链式的优点时充分利用网络带宽,减轻primary压力,但缺点是写入延迟会大一些。GFS,MongoDB(默认情况下)都是链式。
部分节点写入异常理论上,副本集中的多个节点的数据应该保持一致,因此多个数据的写入理论上应该是一个事务:要么都发生,要么都不发生。但是分布式事务(如2pc)是一个复杂的、低效的过程,因此副本集的更新一般都是best effort 1pc,如果失败,则重试,或者告诉应用自行处理。
primary的选举在中心化副本协议中,primary节点是如何选举出来的,当primary节点挂掉之后,又是如何选择出新的primary节点呢,有两种方式:自治系统,依赖其他组件的系统。(ps,这两个名字是我杜撰的 。。。)
所谓的自治系统,就是节点内部自行投票选择,比如mongodb,tfs,zookeeper
依赖其他组件的系统,是指primary由副本集之后的组件来任命,比如GFS中的primary由master(GFS的元数据服务器)任命,hdfs的元数据namenode由zookeeper心跳选主。
secondary是否对外提供服务(读服务)中心化复制集中,secondary是否对外提供读服务,取决于系统对一致性的要求。