分布式存储系统需要将数据分布到多个节点,并在多个节点之间实现负载均衡。常见的数据分布的方式有两种:一种是哈希分布,如一致性哈希,典型的系统是Amazon Dynamo系统;另一种是顺序分布,即将表格上的数据按主键排序,并切分成多块数据,每个数据存到不同的节点中,典型的系统是Google Bigtable, Taobao Oceanbase。
将数据分散存储到多台机后,要尽量保证每台的存储量、访问压力等是均衡的,一般需要一个总控节点定时收集所有工作节点的负载信息,然后将负载高的节点的数据迁移到负载低的节点,实现自动负载均衡。
为了保证可靠性,数据一般要复制多份并存储到多个物理节点中。一般有三种复制模式:异步、强同步、半同步。
复制带来的问题:一致性、可用性、性能之间的权衡
复制到多个副本,就要考虑多副本之间的一致性。如果采用强同步复制,可以保证多副本的一致性,但是写性能较差,且主副本之间出现网络问题或其它故障时,写操作将阻塞。如果采用异步模式,保证了系统的可用性,但是无法做到多副本的强一致性。所以在设计存储系统时,需要在一致性、性能、可用性之间权衡,在适当的场景下,采用合理的策略。也可以做一些折衷处理,强调其中某一个特性,适当兼顾另外两者。
如何衡量可扩展性? 可扩展性不能简单地通过系统是否为P2P架构 或 是否能将数据分布到多个存储节点来衡量,应该综合考虑,下面列出几点:
若采用master/slave架构,master节点会成为扩展的瓶颈吗? 一般主流的分布式存储系统都是master/slave架构,且能够支持上万台的集群规模,一般不会成为扩展的瓶颈。
master节点用于管理所有存储节点,执行数据分布、异常处理、负载均衡等任务,它需要缓存很多元信息,内存容量可能会成为瓶颈。在设计时,可做一些优化措施,来适当减少master的负载。比如在Google GFS中,舍弃了对小文件的支持(减少了元数据的存储量),把数据读写的控制权下放到chunkServer,通过客户端缓存元数据减少对master节点的访问等。
如果master节点成为瓶颈,可以在master节点和slave节点之间加一个中间层节点,每个中间层结点只维护一部分元数据,这样master只需要维护很少的中间层结点的信息,不会成为瓶颈。
传统数据库扩容的缺点 传统数据库扩容的方法有:通过主从复制、读写分离 提高系统的读取能力,通过垂直拆分和水平拆分将数据分布到多个存储节点,通过主从复制将系统扩展到多个数据中心。当主节点出现故障时,可将服务切换到从节点。另外,当数据库整体服务能力不足时,可以根据业务的特点重新拆分数据进行扩容。但是在扩容时,会面临如下问题:
异构系统
同构系统指同一存储组内的所有存储节点服务相同的分片数据。当某一个机器宕机需要增加一台备机,或者为了增加读性能而扩展一台存储机器时,需要向其它同组的结点拷贝整个结点的数据。由于数据量很大,耗时长,在拷贝过程中容易减少 被拷贝节点 的服务能力,会增加丢失整个结点数据的风险。
异构系统将数据划分成很多大小接近的分片,每个分片的多个副本分布到集群中的任何一个存储节点,同一个存储组内的多个结点存储服务不同的分片。这样,如果发生故障,原有的服务将由整个集群而不是某几个固定的存储节点来恢复,这样分担了压力,也减少了丢失整块数据的风险。
心跳 心跳是很容易想到的一种方法。master节点每隔一段时间向slave节点发心跳包,然后slave回一个心跳包。如果过了一定的间隔,master收不到slave的回复,则重试几次。若重试几次后,仍收不到slave的回复,则认为与slave的网络断开、或者slave宕机、停止服务。一般收不到心跳回复有几种原因:与slave的网络断开,slave操作系统崩溃、程序崩溃、slave工作繁忙无法回复。所以这带来了一个问题:如何确定这台机器已经宕机,或停止服务了?
租约(lease) 在实践中,可以通过租约机制来进行故障检测。租约是一种带有超时时间的授权。假设机器A要检测机器B是否发生故障,机器A可以给机器B发放租约,机器B只能在租约有效期内提供服务,否则主动停止服务。机器B在租约快到期的时候,向机器B重新申请租约。当机器B出现故障时 或 与机器A之间的网络发生故障时,机器B的租约过期,从而机器A确定机器B不再向外提供服务,可以将机器B的服务迁移到其它机器上。
多副本的数据 分布式存储系统保存了数据的多个副本(例如,GFS缺省保存3份),当某个副本失效后,分布式文件系统的master会在适当的时机启动副本复制,使得数据的副本数保持设定的数量,保证了数据的安全。
worker故障 分布式存储系统的worker可能出现故障,master通过内置的heartbeat/lease监控所有worker的状态,一旦确认某个worker故障,master会把该worker保存的数据的副本个数减一,以便系统在适当时机启动副本复制以保证数据不会丢失。
master故障 为了避免master成为系统的单点,master也有多个副本:其中一个是主master,其余为辅master,主master承担着master的职责,例如应答用户和worker的请求,记录操作日志等;辅master通过操作日志保持与主master的准同步。当主master发生故障后,在分布式选举协议作用下,一个辅master会升级成为主master,保证系统的继续运行。
应用程序容错 出于容错和故障恢复的原因,分布式存储系统的上层应用程序不能假设它正在或将要使用哪个worker,也不能假设数据存储在或将要存储到哪个worker上,当应用程序需要使用数据时,客户端库将询问系统的master获得数据副本所在的位置,并向其中一个副本(通常是与该客户端网络“距离”最近的)发出数据请求,如果该worker在开始或者中途出现故障或因为其他原因无法完成该请求,则客户端库会自动转向另外一个副本,这对上层应用是完全透明的。
《分布式系统工程实践》 杨传辉的博客 阳振坤的博客 《大规模分布式存储系统》 《大数据日知录:架构和算法》 《分布式系统设计模式》PPT 汪源
出处:https://baozh.github.io/2015-12/distributed-system-fundamental-sec/
版权申明:内容来源网络,版权归原创者所有。除非无法确认,我们都会标明作者及出处,如有侵权烦请告知,我们会立即删除并表示歉意。谢谢。