NameServer中的BlockManage和Servermanage的介绍
1.BlockManager 用来管理所有来自DataServer和Block的信息
因为Block的数量非常多, 所以BlockManage将Block组织成一个HashMap的结构(它的桶的数量可以在参数 MAX_BLOCK_CHUNK_NUMS中设置).
它还定义了一个双向队列,用于对要删除的Block进行管理, 在规定的时间内写过的Block也会组织成一个HashMap,它会根据时间在 last_write_blocks_[i]中记录最近写入的Block,官方文档上说这个可能和延迟删除有关.....官方文档还带吐槽的吗.
它可以通过BlockId判断某个Block是否存在,还可以通过BlockId获取Block的集合(因为Block默认是有三个备份的),用于获取到Block所对应的DataServer
它提供了一些接口:
- 创建.解除.更新具体的Block与DataServer关系的接口
- 判断某个Block是否需要复制,压缩,迁移的接口.
2.ServerManager: 用来管理所有Server的信息
- 它和BlockManage一样 也拥有管理DataServer和Block关系的功能 但是不同的是从Server角度的
- TFS的负载均衡都是由它来做的
- ServerManager定义了两个Server列表servers_和dead_servers_
- DataServer 的新增和退出也是由它来管理的
- 它还负责在写入数据的时候挑选哪一个DataServer为写入的主块 然
- DataServer来挑选合适的Block块进行写入
- 当备份的Block多了的时候也是由它负责删除
DataServer后台线程介绍 (下面三个大概看了一下copy过来了,以后需要了再仔细看看吧)
1.心跳线程
这里的心跳的指DataServer像NameServer周期性发送统计信息 以前会在心跳里加上block的信息,现在心跳只负责告诉NameServer我还活着
2.复制线程
人工或者Ns可以添加复制Block任务至复制队列中,复制线程会从复制队列中取出并执行。结合Ns,整个复制的大致过程是ns向复制的源Ds发起复制任务,源Ds将复制任务所需要的信息结构(ReplBlockExt)加入复制队列中。复制线程取出一个复制任务后,会先通过ReadRawData接口将源Ds的Block数据读出,然后向目标Ds发WriteRawData消息,目标ds在接到writeRawData消息后复制数据,然后通过batch_write_info进行index的复制。然后源Ds将复制是否成功的状态向Ns进行回复,Ns在收到复制成功的消息后会进行Block与Ds关系的更新。当从ns中收到move的操作后,还会将源ds上的Block删除掉。在管理复制的过程中,还用到两个重要的数据结构ReplicateBlockMap_和ClonedBlockMap_,前者用来记录源中将要进行复制的Block,后者用来记录目标中正在复制Block的状态。
3.压缩线程
真正的压缩线程也从压缩队列中取出并进行执行(按文件进行,小文件合成一起发送)。压缩的过程其实和复制有点像,只是说不需要将删除的文件数据以及index数据复制到新创建的压缩块中。要判断某个文件是否被删除,还需要拿index文件的offset去fileinfo里面取删除标记,如果标记不是删除的,那么就可以进行write_raw_data的操作,否则则滤过。
4.检查线程
- a 清理过期的Datafile;
- b 修复check_file_queue_中的逻辑块(block_checker.cpp)
- c 清理过期的复制块(由于复制过程中出错导致的错误复制块,复制目标的ds做)
- d 清理过期的压缩块(由于压缩过程中出错导致的错误压缩块,压缩在同一个ds上做)
- e 每天rotate读写日志,清理过期的错误逻辑块 f 读日志累积后刷磁盘
b的详细过程: 每次对文件进行读写删操作失败的时候,会try_add_repair_task(blockid, ret)来将ret错误的block加入check_file_queue_中,正常情况下加入的为-EIO(I/O错误)的错误Block,那什么时候加入的是CRC的错误呢?人工进行修复的时候发该类型的CRC_ERROR_MESSAGE消息,然后也会加入check_file_queue_中.也就是说人工修复是认为CRC错误的。然后在check的时候会根据类型进行do_repair_crc还是do_repair_eio操作,对各自类型进行错误统计,其中check_block的过程就是通过crc_error和eio_error数量来判断该Block是否过期(对于过期的逻辑块,在错误位图上进行相应物理块的设置),如果是,则请求Ns进行update_block_info, 如果不是,对于eio请求,则无法修复,设置Block不正常(abnormal)的最新时间,对于Crc的则尝试修复,修复过程中会从其他Ds上读副本来进行修复,若出错则会请求Ns进行update_block_info,否则设置Block不正常的最新时间。
RsServer介绍
TFS 在2.0版本增加了一个server, 叫做 rcserver. 这个 server 主要是为了淘宝内部管理使用 TFS 的各个应用. 我们给每个应用分配一个唯一的 AppKey. TFS 客户端使用这个 AppKey 登录到 rcserver, 取得自己应该访问的 TFS 集群信息. 客户端还会定期把自己的一些统计值发送给 rcserver. 具体信息可以参看源码中 doc 目录下的关于 rcserve 的文档.
简单来说就是TFS以前没有权限功能,现在2.0以上的版本通过RsServer来生成一个AppKey TFS通过这个AppKey来实现访问权限的控制.
MetaServer介绍
以下是官方文档里写的:
简介
metaserver是我们在2.0版本引进的一个服务. 用来存储一些元数据信息, 这样原本不支持自定义文件名的 TFS 就可以在 metaserver 的帮助下, 支持自定义文件名了.
组成
metaserver 由一个主控节点(rootserver), 若干服务节点(metaserver) 组成. rootserver 主要管理所有的 metaserver. 而metaserver 完成跟文件相关的操作. metaserver 缓存最近的被访问到目录和文件信息. 对于任何写入, 除了更改自己的缓存外还要更改后端持久化存储中的内容. 目前我们暂时使用 mysql 数据库提供后端持久化存储, 将来会替换成淘宝自己的分布式数据库 oceanbase.
访问过程
客户端在做自定义文件名的读操作的时候, 会先从 rootserver 得到关于 metaserver 的信息, 并缓存在自己的内存中. 然后用自定义文件名去 metaserver 中查找 TFS 文件名信息, 再去 TFS 中访问该文件. 客户端在做自定义文件名的写操作的时候, 会先写入到 TFS 中, 再把 TFS 文件名和自定义文件的对应关系写入metaserver中.
自定义文件名的限制
我们目前要求使用自定义文件名的时候必须传入一个app_id 一个 uid. 这两个 id 成为所有自定义文件名的固定前缀. mv 操作只能在相同的app_id, uid 之下进行. 这样做是我们为了简化实现复杂度. 我们的应用都是要面向海量客户, 每个客户自身的数据量有限. 有了上面的限制, 我们可以总是把对同一个app_id uid的请求用相同的 metaserver 来响应. 这样使得我们可以很容易的处理数据一致性问题.
写文件的特殊点
在使用自定义文件名写文件的时候, 必须先调用 creat_file 接口建立文件. 文件建立之后, 可以多进程并发的写这个文件. 这样是为了便于大文件的分片上传. 我们还是不支持对已有文件的修改, 所以分片上传的时候各个分片是不能互相覆盖的.
后续计划
目前自定义文件名提供的功能还比较简单初级, 我们会根据应用的需求逐步完善功能, 提高性能. 我们将来计划在 oceanbase 团队的帮助下, 把后端存储替换成 oceanbase 数据库. 另:编译时候我们设置了 mysql 的最低版本, 这个版本设置的比较高, 其实只要是5.0以上版本就可以支持这个应用.
MetaServer的引入解决了原来不能自定义文件名和缺点,然后里面会有一些特别的限制需要注意.