分布式FastDFS存储原理2

框架

 

数据流程

FastDFS文件同步

        连接tracker有独立的线程(tracker_report_thread_entrance),连接n个tracker就有n个线程;一个group里面又n个storage,每个storage都有n-1个线程(storage_sync_thread_entrance)用来给同group的storage做同步。

storage的状态:
#define FDFS_STORAGE_STATUS_INIT	  0
#define FDFS_STORAGE_STATUS_WAIT_SYNC	  1
#define FDFS_STORAGE_STATUS_SYNCING	  2
#define FDFS_STORAGE_STATUS_IP_CHANGED    3
#define FDFS_STORAGE_STATUS_DELETED	  4
#define FDFS_STORAGE_STATUS_OFFLINE	  5
#define FDFS_STORAGE_STATUS_ONLINE	  6
#define FDFS_STORAGE_STATUS_ACTIVE	  7
#define FDFS_STORAGE_STATUS_RECOVERY	  9

同步命令:
#define STORAGE_PROTO_CMD_SYNC_CREATE_FILE	16	//新增文件
#define STORAGE_PROTO_CMD_SYNC_DELETE_FILE	17  // 删除文件
#define STORAGE_PROTO_CMD_SYNC_UPDATE_FILE	18	// 更新文件
#define STORAGE_PROTO_CMD_SYNC_CREATE_LINK	19  // 创建链接

同步日志所在目录

例如在192.168.221.152服务器上的sync log:

在 192.168.221.157服务器上看到的sync log:

192.168.221.152_23000.mark
binlog.000
binlog_index.dat

192.168.221.157_23000.mark

        同步状态文件,记录本机(192.168.221.152)到192.168.221.157的同步状态,文件名由同步源IP_Port组成。mark文件可以有多份,group里面如果有N个storage,就有N-1个mark文件;文件内容如下:

 mark文件内容解释如下:

binlog_index=0        //binlog索引id  表示上次同步给192.168.221.157机器的最后一条binlog文件索引
binlog_offset=232     //表示上次同步给192.168.221.157机器的最后一条binlog偏移量,
                      //若程序重启了,也只要从这个位置开始向后同步即可。
need_sync_old=0       //是否需要同步老数据
sync_old_done=0       //是否同步完成
until_timestamp=0     //同步已有数据文件的截至时间
scan_row_count=4      //扫描记录数
sync_row_count=3      //同步记录数

 binlog.000

        binlog文件,大小最大1G,超过1G,会重写下个文件,如binlog.001,binlog.002,...,同时更新binlog_index.dat文件中索引值。文件内容如下:

        FastDFS文件同步采用binlog异步复制方式。storage server使用binlog文件记录文件上传、删除等操作,根据binlog进行文件同步。binlog中只记录文件ID和操作,不记录文件内容。

        从上面可以看到,binlog文件有三列,依次为:

        (1)1685368794表示文件upload时间戳

        (2)C表示文件操作类型

        (3)文件的FileID

        例如:M00/00/00/wKjdmGR0r9qADDWgAAAoIvD4yLo41.conf,其中M00为stragepath索引;00/00/为路径;wKjdmGR0r9qADDWgAAAoIvD4yLo41.conf为文件系统中实际的文件名(若采用合并存储并不是一个实际的文件名)。

        wKjdmGR0r9qADDWgAAAoIvD4yLo41是经过base64编码后的值,由下面几个部分组成:

  • Storage_id(ip的数值型)
  • timestamp(创建时间)
  • file_size(若原始值为32位则前面加入一个随机值填充,最终为64位)
  • crc32(文件内容的检验码)

        文件操作类型采用单个字母编码,其中源头操作用大写字母表示,被同步的操作为对应的小写字母。文件操作字母含义如下:

副本

C :上传文件(upload)

c:副本创建

D:删除文件(delete)

d:副本删除

A:追加文件(append)

a:副本追加

M:部分文件更新(modify)

m:副本部分文件更新(modify)

U:整个文件更新(set metadata)

u:副本整个文件更新(set metadata)

T:截断文件(truncate)

t:副本截断文件(truncate)

L:创建符号链接(文件去重功能,相同内容只保存一份)

l:副本创建符号链接(文件去重功能,相同内容只保存一份)

注:源表示客户端直接操作的那个Storage即为源,其他的Storage都为副本。如客户端向10.0.1.1主机Upload一个文件,那么在10.0.1.1机器上记录的就是C,当10.0.1.1机器将该条binlog的操作同步给10.0.1.2时,在10.0.1.2上记录的binlog就是c,其他几种操作同理。

binlog_index.dat

        记录了当前写binlog的索引id。

同步机制 

storage同步规则

  1. 文件同步采用增量方式,记录已同步的位置到mark文件中
  2. 文件同步只在同组内的storage server之间进行,采用push方式;
  3. 源头数据才需要同步,备份数据不需要再次同步,否则就构成环路了。源数据和备份数据是根据binlog的操作类型来区分:操作类型是大写字母表示源数据,小写字母表示备份数据
  4. 当新增加一台storage server时,由已有的一台storage server将已有的所有数据(包括源头数据和备份数据)同步给该新增服务器。
  5. 可以通过增加group,来扩展存储能力;
  6. 如果一个group由N个storage,则每个storage需要创建N-1个线程,每个线程中的所有操作都是以同步方式执行的。(例如:一组服务器有A、B、C三台机器,那么在每台机器上都有两个线程负责同步,如A机器,线程A1负责同步数据到B,线程A2负责同步数据到C。)

storage获取组内的其他storage信息,并启动同步线程

        tracker_report_thread_entrance 线程负责向tracker上报信息。

        在storage.conf配置文件中,只配置了Tracker的IP和Port,并没有配置组内其他的Storage:

tracker_server=192.168.221.152:22122
tracker_server=192.168.221.152:22123

        因此同组的其他Storage必须从Tracker获取。具体过程如下:

      1)Storage启动时为每一个配置的Tracker启动一个线程负责与该Tracker的通讯。

      2)默认每间隔30秒,与Tracker发送一次心跳包,在心跳包的回复中,将会有该组内的其他storage信息。

      3)Storage获取到同组的其他Storage信息之后,为组内的每个其他Storage开启一个线程负责同步。

同步线程执行过程

        storage_sync_thread_entrance是storage同步线程

        每个同步线程负责一台Storage的同步,以阻塞方式进行。

      1)打开对应storage的mark文件,如负责到192.168.221.157的同步则打开192.168.221.157_23000.mark文件,从中读取binlog_index、binlog_offset两个字段值,如取到值为:0、100,那么就打开binlog.000文件,seek到100这个位置。

      2)进入一个while循环,尝试着读取一行,若读取不到则睡眠等待。若读取到一行,并且该行的操作方式为源操作,如C、A、D、T(大写的都是),则将该行指定的操作同步给对方(非源操作,如c、a、d、t则不需要同步),同步成功后更新binlog_offset标志,该值会定期写入到192.168.221.157_23000.mark文件之中。

同步前删除

        假如同步较为缓慢,那么有可能在开始同步一个文件之前,该文件已经被客户端删除,此时同步线程将打印一条日志,然后直接接着处理后面的Binlog记录。

storage的最后最早被同步时间

        这个标题有点拗口,先举个例子:一组内有Storage-A、Storage-B、Storage-C三台机器。对于A这台机器来说,B与C机器都会同步Binlog(包括文件)给他,A在接收同步时会记录每台机器同步给他的最后时间(也就是Binlog中的第一个字段timpstamp)。比如B最后同步给A的Binlog-timestamp为100,C最后同步给A的Binlog-timestamp为200,那么A机器的最后最早被同步时间就为100.

      这个值的意义在于判断一个文件是否存在某个Storage上。比如这里A机器的最后最早被同步时间为100,那么如果一个文件的创建时间为99,就可以肯定这个文件在A上肯定有。为什呢?一个文件会Upload到组内三台机器的任何一台上:

      1)若这个文件是直接Upload到A上,那么A肯定有。

      2)若这个文件是Upload到B上,由于B同步给A的最后时间为100,也就是说在100之前的文件都已经同步A了,那么A肯定有。

      3)同理C也一样。

        Tracker也会定期将每个storage的最后最早时间写入到一个文件storage_sync_timestamp.dat之中,内容如下:

group1,10.0.0.1,0,1408524351,1408524352
group1,10.0.0.2,1408524353,0,1408524354
group1,10.0.0.3,1408524355,1408524356,0

每一行记录了,对应Storage同步给其他Storage的最后时间,如第一行表示10.0.0.1同步给10.0.0.2的最后时间为1408524351,同步给10.0.0.3的最后时间为1408524352;同理可以知道后面两行的含义了。每行中间都有一个0,这个零表示自己同步给自己,没有记录。按照纵列看,取非零最小值就是最后最早同步时间了,如第三纵列为10.0.0.1被同步的时间,其中1408524353就是其最后最早被同步时间。

新增storage节点同步流程

1、新节点storage C 启动的时候会创建线程tracker_report_thread_entrance,调⽤ tracker_report_join向tracker 发送命令TRACKER_PROTO_CMD_STORAGE_JOIN(81)报告⾃⼰的group名称,ip,端⼝,版本号,存储⽬录数,⼦⽬录数,启动时间,⽼数据是否同步完成,当前连接的 tracker信息,当前状态信息(FDFS_STORAGE_STATUS_INIT)等信息

2、tracker收到TRACKER_PROTO_CMD_STORAGE_JOIN命令后,将上报的信息和已有 (tracker数据⽂件中保存的信息)的信息进⾏⽐较,如果有则更新,没有的话,将节点及状态信息写⼊缓 存和数据⽂件中,并查找同group的其他节点做为同步源,如果有返回给stroage C

3、新节点stroage C 收到tracker响应继续流程。发送 TRACKER_PROTO_CMD_STORAGE_SYNC_DEST_REQ (87)查询同步⽬的

4、tracker收到TRACKER_PROTO_CMD_STORAGE_SYNC_DEST_REQ 请求后, 查找同group 的其他节点做为同步⽬标,及时间戳返回给新storage节点

5、新storage节点收到响应后,保存同步源及同步时间戳。继续流程,发送 TRACKER_PROTO_CMD_STORAGE_BEAT(83) 给tracker

6、tracker收到⼼跳报告后,leader trakcer(⾮leader不返回数据),把最新的group的 storagelist返回给新的stroaged

7、stroage C 收到 tracker storage list后,启动2个同步线程,准备将binlog同步到节点 A和 B(此时还不能同步,因为stroage C 还是WAIT_SYNC 状态)

8、这时候,其他的已在线的storage 节点 A 、B会发送⼼跳给tracker ,tracker 把会收到最新的 stroagelist,A、B、C返回给Storage A,B

9、storage A,B 收到tracker响应后,会发现本地缓存中没有stroage C,会启动binlog同步线 程,将数据同步给 stroage C

10、storage A 、B分别启动storage_sync_thread_entrance 同步线程,先向 tracker 发送 TRACKER_PROTO_CMD_STORAGE_SYNC_SRC_REQ(86)命令,请求同步源,tracker会把同步源 IP及同步时间戳返回

11、stroage A 、B节点的同步线程收到TRACKER_PROTO_CMD_STORAGE_SYNC_SRC_REQ 响应后,会检查返回的同步源IP是否和⾃⼰本地ip⼀致,如果⼀致置need_sync_old=1表示将做为源数据 将⽼的数据,同步给新节点C,如果不⼀致置need_sync_old=0,则等待节点C状态为Active时,再同步 (增量同步)。因为,如果A、 B同时作为同步源,同步数据给C的话,C数据会重复。这⾥假设节点A, 判断tracker返回的是同步源和⾃⼰的iP⼀致,A做为同步源,将数据同步给storage C节点。

12、Storage A同步线程继续同步流程,⽤同步⽬的的ip和端⼝,为⽂件名,.mark为后缀,如 192.168.1.3_23000.mark,将同步信息写⼊此⽂件。将Storage C的状态置为 FDFS_STORAGE_STATUS_SYNCING 上报给tracker,开始同步:

A)、从data/sync⽬录下,读取binlog.index 中的,binlog⽂件Id,binlog.000读取逐⾏读取,进 ⾏解析 具体格式 如下: 1490251373 C M02/52/CB/CtAqWVjTbm2AIqTkAAACd_nIZ7M797.jpg 1490251373 表示时间戳 C 表示操作类型 M02/52/CB/CtAqWVjTbm2AIqTkAAACd_nIZ7M797.jpg ⽂件名 因为storage C是新增节点,这⾥需要全部同步给storage C服务 B)、根据操作类型,将数据同步给storage C,具体有如下类型

#define STORAGE_OP_TYPE_SOURCE_CREATE_FILE 'C' //upload file

#define STORAGE_OP_TYPE_SOURCE_APPEND_FILE 'A' //append file

#define STORAGE_OP_TYPE_SOURCE_DELETE_FILE 'D' //delete file

#define STORAGE_OP_TYPE_SOURCE_UPDATE_FILE 'U' //for whole file update such as metadata file

#define STORAGE_OP_TYPE_SOURCE_MODIFY_FILE 'M' //for part modify

#define STORAGE_OP_TYPE_SOURCE_TRUNCATE_FILE 'T' //truncate file

#define STORAGE_OP_TYPE_SOURCE_CREATE_LINK 'L' //create symbol link

#define STORAGE_OP_TYPE_REPLICA_CREATE_FILE 'c'

#define STORAGE_OP_TYPE_REPLICA_APPEND_FILE 'a'

#define STORAGE_OP_TYPE_REPLICA_DELETE_FILE 'd'

#define STORAGE_OP_TYPE_REPLICA_UPDATE_FILE 'u'

#define STORAGE_OP_TYPE_REPLICA_MODIFY_FILE 'm'

#define STORAGE_OP_TYPE_REPLICA_TRUNCATE_FILE 't'

#define STORAGE_OP_TYPE_REPLICA_CREATE_LINK 'l'

具体同步函数storage_sync_data

C)、 发送数据给Stroage C,StroageC 收数据并保存

D)、binlog⽂件读完之后,会将Stroage C 状态 置为FDFS_STORAGE_STATUS_OFFLINE,向 tracker 报告,同时更新同步状态到本地⽂件mark⽂件

E)、同步完成后调⽤ tracker_sync_notify 发送 TRACKER_PROTO_CMD_STORAGE_SYNC_NOTIFY通知tracker同步完成,将storage C的 状态置为 FDFS_STORAGE_STATUS_ONLINE

F) 当storage server C向tracker server发起heart beat时,tracker server将其状态更改为 FDFS_STORAGE_STATUS_ACTIVE。

tracker处理机制

tracker下载文件过程

         storage会定期将每台机器同步给他的最后时间告诉给Tracker,Tracker在客户端要下载一个文件时,需要判断一个Storage是否有该文件,只要解析文件的创建时间,然后与该值作比较,若该值大于创建创建时间,说明该Storage存在这个文件,可以从其下载。

tracker持久化storage信息

img

查看持久化的storage信息: 

tracker持久化storage信息是为了下次tracker启动时,可以加载该文件,快速获取storage信息。

如何选择tracker

当集群中有多个tracker server时,由于tracker之间是对等的关系,客户端在upload文件时可以任意选择一个tracker。

同步总结

1、为了避免循环推送,当发现binlog中的文件操作类型是大写的,才推送给其他storage;如果是小写的,则不用推送给其他storage.

2、

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值