FastDFS之合并存储缺陷导致数据丢失或错误
基于FastDFS 5.03/5.04
2014-12-19
一、问题描述
问题的关键在于Trunk-Server上,Trunk-Server实现空间的分配,每一次的空间分配都记录到Trunk-Binlog文件之中,并且定期(每秒)将该文件的更新同步给组内的其他Storage服务器。问题就是若某种情况下Trunk-Server无法将该Trunk-Binlog同步出去,就宕机了。Tracker检测到后会将Trunk-Server变成组内的另外一台Storage,而这台Storage并不知道有一些空间已经分配出去了,会重复分配该空间。当之前宕机的那台Trunk-Server回来之后,文件会被互相同步,那么这两次写入的数据就被覆盖,而产生错误文件。
也可以参考,论坛上的一个作者没有回答的帖子(我在里面也有回复):
http://bbs.chinaunix.net/forum.php?mod=viewthread&tid=4153275&extra=page%3D3%26filter%3Dtypeid%26typeid%3D424%26typeid%3D424
二、重现具体过程
服务器描述:有两台机器分别为151与70,每天机器上都有Storage和Tracker。
1)启动151、70两台服务器上的Tracker和Storage,此时Trunk-Server为151机器
2)向服务器Upload一个20字节的文件,产生的Trunk-binlog如下:
文件内容如下:wozhizhongchangshou
Trunk-binlog各字段含义如下:
timestamp,type,store_path,sub_high_path,sub_low_path,fileid,offset,size
1412736359 A 0 0 0 1 0 67108864 #创建一个新文件1,64MB
1412736359 D 0 0 0 1 0 67108864 #删除该1这个文件空间,用于分裂
1412736359 A 0 0 0 1 44 67108820 #分裂第二部分,44~
1412736359 A 0 0 0 1 0 44 #分裂第一部分,0~44
1412736359 D 0 0 0 1 0 44 #空间分配,将0~44分配用于存储
标记为状态1;
3)关闭70-Storage
4)向服务器再次Upload一个20字节的文件,增加了如下的Trunk-binlog
1412738792 D 0 0 0 1 44 67108820 #删除44~空闲块,用于分裂
1412738792 A 0 0 0 1 88 67108776 #分裂第二部分,88~
1412738792 A 0 0 0 1 44 44 #分裂第一部分,44~88
1412738792 D 0 0 0 1 44 44 #将44~88这块用于存储文件
标记为状态2;
5)关闭151-Storage,等待停止后,启动70-Storage,注意:此时第二次Upload的文件binlog并没有同步到70-Storage
6)等待Tracker将Trunk-Server却换到70-Storage,此时151-Storage处于状态1,而70-Storage处于状态2;
7)向服务器Upload一个11字节的文件,文件内容为:XXXXXXXXXX
产生了如下的Trunk-binlog:
1412748730 D 0 0 0 1 44 67108820 #删除44~空闲块,用于分裂
1412748730 A 0 0 0 1 79 67108785 #分裂第二部分,88~
1412748730 A 0 0 0 1 44 35 #分裂第一部分,44~79
1412748730 D 0 0 0 1 44 35 #将44~79这块用于存储文件
标记为状态3;
此时151-Storage处于状态2:44~88这块用于存储一个20字节的文件,而70-Storage处于状态3:44~79这块用于存储一个11字节文件
8)当70-Storage启动时,Trunk-binlog会从Trunk-Server同步到其他Storage,也就是151的状态2会被覆盖成状态3;同时源文件同步功能启动后会使得151将44~88的文件同步给70Storage,而70Storage也会将44~79的文件同步给151,源文件同步完成后,文件就被破坏了。
9)下载文件测试,发现第二次Upload的20字节文件内容变成:wozhizhongcF# 这后面的内容被第三个文件的Trunk-header覆盖掉了。