数据文件storage_groups.dat和storage_servers.dat中的记录之间以换行符(\n)分隔,字段之间以英文逗号(,)分隔。
# 我的tracker server目录是/home/fastdfs/tracker_22122,看个人配置
/home/fastdfs/tracker_22122
# 文件结构
├── data
│ ├── fdfs_trackerd.pid
│ ├── storage_changelog.dat #storage有修改过ip
│ ├── storage_groups_new.dat # 存储分组信息
│ ├── storage_servers_new.dat # 存储服务器列表
│ └── storage_sync_timestamp.dat # 同步时间戳
└── logs
└── trackerd.log # Server日志文件
可以使用tail -f logs/trackerd.log查看打印信息,这对有报错时进行日志分析非常有用。 (1)storage_changelog.dat。例如:
1645866390 group1 192.168.0.104 192.168.0.105
(2)storage_groups_new.dat。例如:
# global section
[Global] group_count=1
# group: group1
[Group001]
group_name=group1
storage_port=23000
storage_http_port=8888
store_path_count=1
subdir_count_per_path=256
current_trunk_file_id=0
trunk_server=
last_trunk_server=
(3)storage_servers.dat。例如:
[Storage001]
group_name=group1
ip_addr=192.168.0.104
status=7
version=6.07
join_time=1646292828
....
[Storage002]
group_name=group1
ip_addr=192.168.0.105
status=7
version=6.07
join_time=1646292925
storage_port=23000
....
(4)主要参数如下: group_name:所属组名。 ip_addr:ip地址。 status:状态。 sync_src_ip_addr:向该storage server同步已有数据文件的源服务器。 sync_until_timestamp:同步已有数据文件的截至时间(UNIX时间戳)。 stat.total_upload_count:上传文件次数。 stat.success_upload_count:成功上传文件次数。 stat.total_set_meta_count:更改meta data次数。 stat.success_set_meta_count:成功更改meta data次数。 stat.total_delete_count:删除文件次数。 stat.success_delete_count:成功删除文件次数。 stat.total_download_count:下载文件次数。 stat.success_download_count:成功下载文件次数。 stat.total_get_meta_count:获取meta data次数。 stat.success_get_meta_count:成功获取meta data次数。 stat.last_source_update:最近一次源头更新时间(更新操作来自客户端)。 stat.last_sync_update:最近一次同步更新时间(更新操作来自其他storage server的同步)。
|__data
| |__.data_init_flag # 当前storage server初始化信息
| |__storage_stat.dat #当前storage server统计信息
| |__sync #存放数据同步相关文件
| | |__binlog.index #当前的binlog(更新操作日志)文件索引号
| | |__binlog.xxx #存放更新操作记录(日志)
| | |__${ip_addr}_${port}.mark #存放向目标服务器同步的完成情况
| |__一级目录 #256个存放数据文件的目录,目录名为十六进制字符,如:00, 1F
| | |__二级目录 #256个存放数据文件的目录,目录名为十六进制字符,如:0A, CF |__logs
|__storaged.log #storage server日志文件
重点了解sync 目录及文件结构。 (1)binlog.index中只有一个数据项:当前binlog的文件索引号 binlog.###。 (2)binlog.###为索引号对应的3位十进制字符,不足三位,前面补0。索引号基于0,最大为999。一个binlog文件最大为1GB。记录之间以换行符(\n)分隔,字段之间以英文空格分隔。字段依次为:
(3)$ {ip_addr}_${port}.mark:ip_addr为同步的目标服务器IP地址,port为本组storage server端口。例如:10.0.0.1_23000.mark。各个参数如下:
(4)如果还有其他storage,则有更多的KaTeX parse error: Expected group after '_' at position 10: {ip_addr}_̲{port}.mark,比如10.0.0.2_23000.mark 。
思考:文件上传成功后,其它的storage server才开始同步,其它的storage server怎么去感知?tracker server是怎么通知storage server?
storage定时发送心跳包到tracker,并附带同步的时间节点,tracker会返回其他storage的状态。
正常文件上传完成后,就记录进binlog缓存中,系统定时刷入binlog文件。 系统有线程定时读取binlog文件,当有新增行时,判断该记录是源文件记录还是副本文件记录。 系统只主动发送源文件,副本文件不做处理(非启动时流程)。
线程:
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.0.104服务器的sync log:
192.168.0.105_23000.mark # 同步状态文件,对应发送同步的storage,记录本机到192.168.0.105的同步状态, 文件名由同步源IP_端口组成。
binlog.000 # 本地的binglog日志,文件大小最大1G,超过1G,会重新写下个文件,可以binlog.001,binlog.002,...,同时更新 binlog.index 文件中索引值
binlog_index.dat # 记录了当前写binlog的索引id。
如果有不只2个storage的时候,则该目录还有更多的 .mark文件。
FastDFS文件同步采用binlog异步复制方式。storage server使用binlog文件记录文件上传、删除等操作,根据binlog进行文件同步。binlog中只记录文件ID和操作,不记录文件内容。 例如:
1646123002 C M00/00/00/oYYBAF285cOIHiVCAACI-7zX1qUAAAAVgAACC8AAIkT490.txt
1646123047 c M00/00/00/oYYBAF285luIK8jCAAAJeheau6AAAAAVgABI-cAAAmS021.xml
1646123193 A M00/00/00/rBMYd2IaLXqASSVXAAAHuj79dAY65.txt 6 6
1646123561 d M00/00/00/oYYBAF285luIK8jCAAAJeheau6AAAAAVgABI-cAAAmS021.xml
可以看到,binlog文件有三列,依次为:时间戳,操作类型,文件ID(不带group名称)。
文件操作类型采用单个字母编码,其中源头操作用大写字母表示,被同步的操作为对应的小写字母。文件操作字母含义如下:
源 | 副本 |
---|---|
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都为副本。
同组内的storage server之间是对等的,文件上传、删除等操作可以在任意一台storage server上进行。 文件同步只在同组内的storage server之间进行,采用push方式,即源头服务器同步给本组的其他存储服务器。对于同组的其他storage server,一台storage server分别启动一个线程进行文件同步。
文件同步采用增量方式,记录已同步的位置到mark文件中。mark文件存放路径为:
$base_path/data/sync/
mark文件内容示例:
binlog_index=0 //binlog索引id 表示上次同步给114.215.169.67机器的最后一条binlog文件索引
binlog_offset=3944 //当前时间binlog 大小 (单位是字节)表示上次同步给其他机器的最后一条binlog偏移量,若程序重启了,也只要从这个位置开始向后同步即可。
need_sync_old=1 //是否需要同步老数据
sync_old_done=1 //是否同步完成
until_timestamp=1621667115 //同步已有数据文件的截至时间
scan_row_count=68 //扫描记录数
sync_row_count=53 //同步记录数
(1)只在同组内的storage server之间进行同步。 (2) 源头数据才需要同步,备份数据不需要再次同步,否则就构成环路了,源数据和备份数据区 分是用binlog的操作类型来区分,操作类型是大写字母,表示源数据,小写字母表示备份数据。 (3)当新增一台storage server时,由已有的一台storage server将已有的所有数据(包括源头数据和备份数据)同步给该新增服务器。
增量同步:storage server之间已经在运行,它们之间的数据同步就是增量同步发。 全量同步:新增一台storage server时,由已有的一台storage server将已有的所有数据(包括源头数据和备份数据)同步给该新增服务器,这就是全量同步。
在FastDFS之中,每个Storaged之间的同步都是由一个独立线程负责的,该线程中的所有操作都是以同步方式执行的。比如一组服务器有A、B、C三台机器,那么在每台机器上都有两个线程负责同步,如A机器,线程1负责同步数据到B,线程2负责同步数据到C。
tracker_report_thread_entrance 线程负责向tracker上报信息。 在Storage.conf配置文件中,只配置了Tracker的IP地址,并没有配置组内其他的Storage。因此同组的其他Storage必须从Tracker获取。具体过程如下:
storage_sync_thread_entrance 同步线程。每个同步线程负责到一台Storage的同步,以阻塞方式进行。
(1)打开对应Storage的mark文件,如负责到192.168.0.104的同步则打开192.168.0.104_23000.mark文件,从中读取binlog_index、binlog_offset两个字段值,如取到值为:0、100,那么就打开binlog.000文件,seek到100这个位置。 (2)进入一个while循环,尝试着读取一行,若读取不到则睡眠等待。若读取到一行,并且该行的操作方式为源操作,如C、A、D、T(大写的都是),则将该行指定的操作同步给对方(非源操作不需要同步),同步成功后更新binlog_offset标志,该值会定期写入到192.168.0.104_23000.mark文件之中。
假如同步较为缓慢,那么有可能在开始同步一个文件之前,该文件已经被客户端删除,此时同步线程将打印一条日志,然后直接接着处理后面的Binlog。
举个例子: 一个group内有Storage-A、Storage-B、Storage-C三台机器。对于A这台机器来说,B与C机器都会同步Binlog(包括文件)给他,A在接收同步时会记录每台机器同步给他的最后时间(Binlog中的第一个字段timpstamp,这个时间也会更新到storage_stat.dat的last_sync_update)。比如B最后同步给A的Binlog-timestamp为100,C最后同步给A的Binlog-timestamp为200,那么A机器的最后最早被同步时间就为100。也就是取最小值。
这个值的意义在于,判断一个文件是否存在某个Storage上。 比如这里A机器的最后最早被同步时间为100,那么如果一个文件的创建时间为99,就可以肯定这个文件在A上肯定有。
Storage会定期将每台机器同步给他的最后时间告诉给Tracker,Tracker在客户端要下载一个文件时,需要判断一个Storage是否有该文件,只要解析文件的创建时间,然后与该值作比较,若该值大于创建创建时间,说明该Storage存在这个文件,可以从其下载。
Tracker也会定期将该值写入到一个文件之中,Storage_sync_timestamp.dat,内容如下:
group1,192.168.0.104, 0, 1408524351, 1408524352
group1,192.168.0.105, 1408524353, 0, 1408524354
group1,192.168.0.106, 1408524355, 1408524356, 0
每一行记录了对应Storage同步给其他Storage的最后时间。
机器 | 同步时间 | 同步时间 | 同步时间 |
---|---|---|---|
group1,192.168.0.104 | 0 | 1408524351 | 1408524352 |
group1,192.168.0.105 | 1408524353 | 0 | 1408524354 |
group1,192.168.0.106 | 1408524355 | 1408524356, | 0 |
如第一行含义:0表示自己同步给自己,没有记录;1408524351表示192.168.0.104同步给192.168.0.105的最后最早被同步时间;1408524352 表示192.168.0.104同步给192.168.0.106的最后最早被同步时间。其他行同理。
比如在已有A、B节点上,新增节点storage C。
(1)在同group下,获取最小的一个同步时间点(各个storage在同一时间,同步完成的时间点不一样)。 (2)在最小同步时间点之前的文件,按照用户的规则随意选择一个storage。 (3)在最小同步时间点之后的文件,选择源storage提供给客户端。
binlog_index=0 //binlog索引id 表示上次同步给其他机器的最后一条binlog文件索引
binlog_offset=3944 //当前时间binlog 大小 (单位是字节)表示上次同步给其他机器的最后一条binlog偏移量,若程序重启了,也只要从这个位置开始向后同步即可。
need_sync_old=1 //是否需要同步老数据
sync_old_done=1 //是否同步完成
until_timestamp=1621667115 //同步已有数据文件的截至时间
scan_row_count=68 //扫描记录数
sync_row_count=53 //同步记录数
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。