FastDFS之磁盘恢复过程
基于FastDFS 5.03/5.04
2014-12-19
一、磁盘恢复概述
顾名思义,磁盘恢复也就是一台服务器的某个磁盘坏掉,换了一个新的硬盘,然后将旧磁盘本应该有的数据拷贝到新硬盘的过程。FastDFS原生支持该过程,可以自动检测,并完成。FastDFS推荐的方式是一个磁盘挂载成一个Store-Path,换了一个新的磁盘后,该Store_path目录下的数据丢失了,但是这部分数据在同组的其他Storage都有,因此只要从对应的Storage上拷贝到目录下的数据即可。
FastDFS-Storaged程序在启动时会检查每个Store_path目录下的子目录个数,默认情况下,每个Store_path下面会创建两级256个子目录。当非首次启动时,发现某个Store_path下没有任何目录,则会进入磁盘恢复过程。
该过程在代码的storage_disk_recovery.c之中。
二、磁盘恢复过程
磁盘恢复过程包括三个步骤:RecoveryStart、RecoveryStore、RecoveryFinish;这三个步骤之中的RecoveryStore可以多次执行,因此在恢复过程中记录了中间状态,因此即使在磁盘恢复过程中宕机或停止,下次再次启动时还是可以从上次的状态继续恢复数据。而RecoveryStart与RecoveryFinish都是只执行一次。
磁盘恢复过程的两个状态文件: .recovery.mark;.binlog.recovery
这两个状态文件保存与StorePath目录下,用于记录恢复过程的状态。
.recovery.mark文件包括三个字段:
saved_storage_status= ##表示状态
binlog_offset= ##表示恢复的binlog偏移量
fetch_binlog_done= ##表示是否已经下载binlog
.binlog.recovery文件,记录的是需要恢复的文件binlog,内容类似下面这样的记录:
1406858030 C M00/00/00/CmQPRlPa8y6AbW3ZAAADWjN_G5k15.conf
1、磁盘恢复开始RecoveryStart
在Storaged启动时,会依次检查每一个StorePath,首次启动时会为每个StorePath创建两级256个子目录(默认256,可配置),因此当非首次启动时,检测到StorePath下不存在这两级的256个子目录,那么程序就会认为该StorePath数据丢失,开始进行这个StorePath的磁盘恢复。
该过程在storage_disk_recovery_start函数之中。
RecoveryStart执行如下操作:
1)创建状态文件 .recovery.mark;.binlog.recovery,并初始化。
2)连接Tracker,查询该Storage的最大状态值(该值用于在磁盘恢复完成后,恢复到之前的状态),查询所在组的Storage列表,从中获取一个状态为Active的Storage,若获取不到Active的Storage则睡眠5秒后再次尝试;获取到的该Storage我们称为源Storage。
3)向Tracker报告,将自己状态设置成RECOVERY。
4)向源Storage发送FETCH_ONE_PATH_BINLOG命令,参数为group_name、store_path_index;源Storage收到该命令后从头遍历整个binlog,过滤出符合下列条件的binlog返回来:binlog文件的目录为指定的store_path;该binlog的操作类型为Create方式;该binlog对应的文件在文件系统中还存在;
5)将从源Storage返回的binlog写入到.binlog.recovery文件之中,若完成收到源Storage的整个回复,则设置.recovery.mark文件中的fetch_binlog_done标志为1;表示已经完成binlog文件的获取,设置saved_storage_status为第二步中查询到的最大状态值。
6)检查若采用合并存储,则需要将该binlog进行分割(由于合并存储存在缺陷,这里就不在详细叙述)。
2、磁盘恢复下载文件
这个步骤也就是真实地从一个源Storage上下载文件。详见storage_disk_recovery_store函数。如下:
1)检查是否存在.recovery.mark, .binlog.recovery文件,若任何一个不存在则返回。
2)向RecoveryStart一样,向Tracker请求,查找该组内的一个状态为Active的Storage作为源Storage。
3)打开.recovery.mark 文件,读取binlog_offset值,打开.binlog.recovery文件,定位到binlog_offset这个位置,也就是从上次最后保存的状态开始继续下载文件。
4)依次读取.binlog.recovery文件的后面记录,对于每一条记录都从源Storage中去下载对应文件
5)每下载1000个文件,将状态值binlog_offset写入到.recovery.mark 文件之中
6)当所有的binlog对应文件都下载完成后,向所有Tracker报告恢复之前的最高状态(该状态在恢复开始时从Trakcer中查询得到,见1.2的描述)。
3、磁盘恢复结束
该步骤清理开始时创建的临时文件 .recovery.mark, .binlog.recovery
三、注意事项
1、磁盘恢复是在Storaged程序的初始化过程中,此时进程还没有变成后台进程,因此若知道要进入磁盘恢复,最好使用nohup方式来启动。因此如果数据量大,该过程可能要持续很久,进程一致处于控制台。
2、恢复过程中需要下载对应的binlog与文件,可能到A机器下载binlog,而到B机器下载文件。所有的文件只会在选择好的原Storage上下载,因此压力会集中到一台的Storage上。
3、下载文件的过程中是以单线程,同步的方式进行的,因此不能最大化磁盘IO或者网络性能。