@HUST张友东 work@taobao zyd_com@126.com
分类: 服务器与存储
2012-05-17 17:04:36
Nameserver(NS)是TFS的总控节,NS的主要职责包括为写分配block、为读查找block、管理block与dataserver对应关系、管理dataserver、备NS状态,执行后台复制、均衡、压缩任务,以保证整个集群良好的工作。
Block分配
NS接收到客户端的写请求,会分配一个可写的block,如果没有可写block,则会创建一个新的block,每个block由一个id标识(uint32_t,后续会将该值提升至uint64_t),blockid不能重复,且不复用,新创建的block,在当前id的基础上递增,产生新的blockid。
为了保证产生不重复的blockid,必须将blockid当前的值进行持久化,NS在启动时加载这个值,才能知道下一个block id如何分配;唯一能保证完全不重复的方式是,每次blockid增加的时候,都进行持久化操作,但由于NS上的并发请求较多,并且NS上的其他元数据都是全内存化的,在每次创建block时都持久化blockid,对正常服务的影响较大。
目前采取的解决方法是,记录blockid递增的次数,当次数达到某个阈值(比如100)时,对blockid进行持久化。这样做的问题时,下次再启动,如果上次结束时最新的blockid还未持久化,则会出现重复的blockid,解决的方法是在启动加载blockid后,直接往后跳100,这样就能保证每次生成的blockid不重复,同时不会对NS的服务性能产生大的影响。
Block与Dataserver关系的管理
每个dataserver(DS)上可以拥有很多个block,每个block可以存在于多个DS(决定于配置的副本数),当新创建一个block时,NS会选择多个位置安全的DS,并在这些DS上创建block, block创建成功后,建立block到这多个DS的对应关系。
每个DS包含三个block列表
每个block包含一个server列表
每次写请求到达时,NS会从hold master列表中选择一个目标block,返回给客户端用于写,hold master列表中block个数会维持在一个数值内,这样做的好处是,每次先把一批block写满,再写下一批,而不是把数据分配到所有的block上,减少了维护block的元数据。当hold master中的block个数不足时,会从writable中提升一批到hold master,如果writable里没有可用的,则需新创建一批,以保证能随时满足写请求服务。
DS及备NS管理
NS需要管理所有DS的状态,同时NS为了主备容灾,还需要维护备NS的状态。
DS启动后,会周期性的给主备NS(在配置文件中指定)发送心跳信息,NS超过阈值时间(没有收到DS的心跳就认为DS挂掉,将DS添加到dead server列表,当有新的DS心跳时,NS会先检查新的DS在不在dead server列表中,如果在则从该列表中移除。dead server中的DS存在超过一段时间如240s,则认为这个server已经彻底死掉,这个server上的block的副本数需要增加,将这些block加入到复制任务中。google的研究表明,90%以上的机器故障在15min钟内能恢复,故在故障时不必立即对block进行复制,可以等一段时间,具体等多久可根据系统的副本数确定。
NS在启动时,会根据自己是否拥有vip来判断自己的身份,备NS在启动时,会主动向主NS发送login信息,NS为其分配一个租约,随后备NS会一直续约,只要备NS的租约有效,主NS会将一些操作同步个备NS,这些操作主要包括创建block、删除block、block复制及迁移等。
主备NS间同步主要是考虑到,当主NS挂掉时,NS服务会通过HA切换到备NS,备NS只包含各个DS刚启动时的block信息,而随着系统的运行,各个DS都相应发生了block创建、删除、复制、迁移等操作,也就是说,备NS上的block信息是过期的、不完整的。一种处理方式是在服务切到备NS时,让所有的DS重新汇报一次block,但汇报block是个漫长的过程,在block汇报完前,备NS服务是不可用的。通过将主NS的block创建等操作同步到备NS,备NS的block信息就基本接近主NS(可能有些操作未来得及同步),备NS接管后,能立即正常服务。
任务管理
Nameserver还负责协调整个集群的工作,执行一些后台任务,以保证整个集群良好的工作,主要包括以下几种类型。
复制任务:当有DS挂掉时,该DS上的block都会丢失,导致这些block的副本数下降,如果不及时增加副本,则再出现其他DS故障时,可能导致某些block永久丢失;复制任务及时发现这些副本数少于配置值的block,将其复制到合适的DS,保证数据的可靠性。当有DS宕机时,会触发复制任务,复制任务在4个任务中优先级最高,另外2个副本的block比丢失一个副本的block优先级更高,DS收到NS的任务请求时,应尽快处理优先级高的任务。
均衡任务:当某些DS负载较高时,如磁盘空间使用率太高,或整体工作负载较高等,这时就需要将该DS上的部分block转移到负载较轻的DS上。均衡任务将DS按照所有DS负载的平均值分成两堆,对超过平均值一定范围(可配置)的DS中选择迁移源,从低于平均值一定范围的的DS中选择迁移目标。当创建均衡时,没有限制每个DS上均衡任务数,这样可能导致在一次创建过程中,很多DS的均衡任务并没有被创建。另外在DS上选择block时,应该尽量选择存储数据较多的block(最近出现空block被迁移的情况)。
压缩任务:当某些block上文件删除很多时,block上就会出现很多空洞,但这些空间在没有回收前是不能被使用的,压缩任务用于回收这些block上已删除文件占用的空间。压缩任务目前由NS发起,后期考虑把压缩任务都移到DS上。
删除任务:当某些block的副本数超出配置值时,需要删除掉多余的副本,以节省存储空间。
Nameserver在启动时,会启动任务创建线程和任务执行线程。前者周期性的检查server、block的状态,并依次创建上述4种任务,并将创建的任务添加到任务队列中;后者则从任务队列中取去任务,并将任务发送到相应的DS并执行。