Tracker-Leader的选择

Tracker-Leader的概述

在 FastDFS 中可以配置多个 tracker,每个 tracker 是对等的,但是在运行过程中针对某些操作会选择其中一个 tracker 作为 Leader,由 Leader 执行这些特殊的操作。

既然 Tracker 是对等的,为什么还需要选举 Leader,选出来的 Leader 能干什么?这个问题,余庆(fishhappy100)在 chinaunix bbs 中做了回答,他是如此解释的:

tracker server之间是对等的。客户端可以访问任意一台tracker server。

引入tracker leader是为了解决如下问题:

  1. 新加入一台storage server时,由leader指定向其同步的源storage server
  2. 使用了合并存储特性时,leader为每个group选举和维护唯一的一个trunk server
    以上分配如果不由leader来完成的话,可能会出现混乱情况,尤其是第2条。

Tracker-Relationship线程

在Tracker程序启动后,会启动一个Relationship线程,专门负责Leader的选择,与同Leader的通讯(若自己不是Leader)。

该线程的逻辑很简单,检查内存结构是否设置了Leader,若没有设置Leader,则选择一个Leader,否则向该Leader执行一个Ping操作。

1、选择(查询)Leader

relationship_select_leader函数

1)向所有的 Tracker(包括自己)发送一个 TRACKER_GET_STATUS 命令,来获取对方的状态信息,该信息包括:是否为 Leader;到目前的运行时间;上次停止时间间隔(也就是最后一次停止到启动的时间间隔);只要获取到至少一个该状态成功,则继续下一步:

2)对所有返回成功的 Tracker-Status 进行排序(根据上一步的信息顺序比较),获得状态值最高的 Tracker。

3)若状态最高的 Tracker 就是自己,那么进入一个两阶段提交协议:

通知除自己之外的所有 Tracker,将要变更Tracker-Leader,只要有一个 Tracker 通知成功,则进入下一步;

通知所有的 Tracker(包括自己),将 Leader 变更成自己,只要有一个 Tracker 返回成功,则表示整个变更成功;(此处通知了自己,那么这个步骤肯定会成功)。

4)若最高状态的 Tracker 当前就是 Leader ,那么就设置本地标志为 g_tracker_servers.leader_index,表示 Leader 已经确定。

5)否则,等待真正的 Leader 发起 Leader 变更消息。

这里的逻辑,多少让人不放心,若有三个或以上的Tracker并且中间出现网络不通的情况,很有可能会产生两个 Leader。不过要记住,Leader 只有在开启了合并存储时,才使用来选择 Trunk-Server。其他时候是没用的。

2、与 Leader 心跳(Ping)

relationship_ping_leader 函数

向 Tracker-Leader 发送一个 TRACKER_PING_LEADER 消息,该 Tracker 将响应一个数组,该数组每个成员为一个结构体如下:

1
{group_name,trunk-server-id}

通知这个消息可以从 Leader 中获取每个 Group 当前的 Trunk-Server 是哪个。

来源:荒废庭院 FastDFS之Tracker-Leader选择

Trunk-Server选择

Trunk-Server概述

假若所有的 Storage 都具有分配空闲空间的能力( upload 文件时自主决定存储到哪个 TrunkFile 之中),那么可能会由于同步延迟导致数据冲突,例如:Storage-A:Upload 一个文件 A.txt 100KB,将其保存到 000001 这个 TrunkFile 的开头,与此同时,Storage-B 也接受 Upload 一个文件 B.txt 200KB,将其保存在 000001 这个 TrunkFile 文件的开头,当 Storage-B 收到 Storage-A 的同步信息时,他无法将 A.txt 保存在 000001 这个 trunk 文件的开头,因此这个位置已经被 B.txt 占用。
   
 为了处理这种冲突,引入了 TrunkServer 概念,只有 TrunkServer 才有权限分配空闲空间,决定文件应该保存到哪个 TrunkFile 的什么位置。TrunkServer 由 Tracker(Tracker-Leader) 指定,并且在心跳信息中通知所有的 Storage。

Tracker-Leader选择TrunkServer

描述

在一个 FastDFS 集群之中,在开启合并存储时,为了分配空间引入了一个 TrunkServer 角色,该 TrunkServer 是该 Group 中的一个 Storage,只是该 Storage 要负责为该组内的所有 Upload 操作分配空间。为了避免不同 Tracker 为该 Group 选择了不同的 TrunkServer,此时引入了 Tracker-Leader 角色,也就是 TrunkServer 最终是由 Tracker-Leader 来选择的,然后通知给该组内的所有 Storage。

Tracker -Leader选择TrunkServer时机

1)当组内的一个 Storage 状态变成Active时,并且该组还没有指定 TrunkServer,在tracker_mem_active_store_server函数中触发。
   
    2)某个Tracker在经过选择,被设置成Leader时,则为当前还没有指定TrunkServer的组选择TrunkServer,在relationship_select_leader函数中触发。
   
    3)在定期指定的任务tracker_mem_check_alive函数中,默认该函数 100 秒指定一次。会尝试着为每个当前还没有指定TrunkServer的组选择TrunkServer。对已经指定的组检查其 TrunkServer 是否还处于活动状态(根据 TrunkServer 与 Tracker 的最后心跳时间计算),若不处于活动状态,则会尝试着给该组选择一个新的 TrunkServer。在tracker_mem_check_alive函数中触发。

Tracker-Leader选择TrunkServer的过程

该过程由tracker_mem_find_trunk_server函数负责,具体操作步骤如下:
   
1)依次向组内当前状态为ACTIVE的 Storage 发送TRUNK_GET_BINLOG_SIZE命令的消息,来查询每个 Storage 当前保存的 Trunk-Binlog 的文件大小。来找到 Trunk-Binlog 文件最大的 Storage。
   
2)若该 Group 的最后一个TrunkServer与要设置的新的 TrunkServer 并非同一个,则向该新的 TrunkServer 发送TRUNK_DELETE_BINLOG_MARKS命令,让其删除 trunk-binlog 同步的状态 mark 文件(既然这个 TrunkServer 是新的,那么就要清除同步 trunk-binlog 的状态,使其从头同步 trunk-binlog 给组内的其他S torage)。
   
    3)变更该组的 TrunkServer,并将修改写入到 storage_groups_new.dat文件之中,更新该组的最后 TrunkServer 设置,设置 TrunkServer 已经变更标志,该标志使得在与 Storage 的心跳中通知对方 TrunkServer 已经变更。

来源:HeyManLeader FastDFS合并存储策略