FastDFS之集群部署
http://blog.51niux.com/?id=137 已经对FastDFS做了一个基本介绍,这里来用测试环境搭建一套集群,然后会在部署操作过程中去捋顺一下原理性知识点。
一、环境规划与配置文件修改
1.1 环境规划
IP地址 | 主机名 | 主机角色 |
192.168.1.103 | dfs-tracker-1 | 跟踪服务器1+存储服务器1 |
192.168.1.104 | dfs-tracker-2 | 跟踪服务器2+存储服务器2 |
192.168.1.105 | dfs-storage-group2-1 | 存储服务器3 |
192.168.1.106 | dfs-storage-group2-1 | 存储服务器4 |
#当然实际环境可能最少也在10台R720XD这种机器,满存储盘,一般有两台机器即当Tracker Server又当Storage Server,当然主机名我这里就简单设置一下方便区分。
1.2 软件安装
软件安装一模一样,不一样的就是配置文件。
1.3 配置文件分配
192.168.1.103和192.168.1.104上面要部署跟踪服务器
所以192.168.1.103和192.168.1.104首先要配置tracker.conf
# vim /etc/fdfs/tracker.conf #大部分保持默认,只粘贴修改的地方
base_path=/opt/fastdfs/tracker max_connections=2048 work_threads=8 log_level=warn
#mkdir /opt/fastdfs/tracker -p
192.168.1.103、192.168.1.104和192.168.1.105、192.168.1.106上面部署存储服务器
所以上面四个IP的配置文件为:
# vim /etc/fdfs/storage.conf #大部分保持默认,只粘贴修改的地方
group_name=group1 #这里要注意,192.168.1.103和192.168.1.104这里是属于group1,192.168.1.105和192.168.1.106这里要设置为group_name=group2 base_path=/opt/fastdfs/storage max_connections=2048 buff_size = 2048KB work_threads=8 store_path_count=2 #这个数字随着盘数的增加而增加,正常这里应该是11或者12,因为存储的满盘一般是12块盘,可以两块盘做raid1做系统盘就是11块盘,但是大部分清空就12块盘全做raid0来当存储了。 store_path0=/data01 #我这里做测试就绑定了两块盘,正常的话应该是11块盘到12块盘,照着这个配置加下去就可以了 store_path1=/data02 tracker_server=192.168.1.103:22122 tracker_server=192.168.1.104:22122 log_level=warn
# mkdir /opt/fastdfs/storage -p
所有的机器上都可以配置客户端文件
# cat /etc/fdfs/client.conf #大部分保持默认,只粘贴修改的地方
base_path=/opt/fastdfs/client tracker_server=192.168.1.103:22122 tracker_server=192.168.1.104:22122 log_level=warn
# mkdir /opt/fastdfs/client -p
博文来自:www.51niux.com
1.4 启动相关服务
#fdfs_trackerd /etc/fdfs/tracker.conf #启动tracker服务(只在tracker服务器上面执行也就是192.168.1.103和192.168.1.104)
#fdfs_storaged /etc/fdfs/storage.conf #启动storaged服务(所有服务器都执行)
在192.168.1.103和192.168.1.104上面执行查看命令:
# netstat -lntup|grep fdfs #通过下面的结果可以看到服务已经启动并且对应的端口也已经监听上了
# lsof -i :22122 #查看下端口的连接状态(可以看到所有的storage服务器都跟tracker服务器的22122端口有连接)
# lsof -i :23000 #查看下storage的端口连接状态发现它与组内的另外一台机器有连接
好的下面是结合上面的现象的理论阐述:
对等结构:FastDFS集群中的Tracker server也可以有多台,Tracker server和Storage server均不存在单点问题。Tracker server之间是对等关系,组内的Storage server之间也是对等关系。传统的Master-Slave结构中的Master是单点,写操作仅针对Master。如果Master失效,需要将Slave提升为Master,实现逻辑会比较复杂。和Master-Slave结构相比,对等结构中所有结点的地位是相同的,每个结点都是Master,不存在单点问题。
Tracker server之间相互独立,不存在直接联系。
客户端和Storage server主动连接Tracker server。Storage server主动向Tracker server报告其状态信息,包括磁盘剩余空间、文件同步状况、文件上传下载次数等统计信息。Storage server会连接集群中所有的Tracker server,向他们报告自己的状态。Storage server启动一个单独的线程来完成对一台Tracker server的连接和定时报告。需要说明的是,一个组包含的Storage server不是通过配置文件设定的,而是通过Tracker server获取到的。
不同组的Storage server之间不会相互通信,同组内的Storage server之间会相互连接进行文件同步。
博文来自:www.51niux.com
二、相关命令使用及相关理论介绍
2.1 fdfs_test和fdfs_test1
Usage: fdfs_test1 <config_file> <operation> operation: upload, download, getmeta, setmeta, delete and query_servers
上传文件:
# fdfs_test /etc/fdfs/client.conf upload 1.jpg #用fast_test命令指定客户端文件然后选择upload,然后将本地的1.jpg上传上去。
tracker_query_storage_store_list_without_group: server 1. group_name=, ip_addr=192.168.1.103, port=23000 group_name=group1, ip_addr=192.168.1.103, port=23000 #第一个上传到了group1组的192.168.1.103:23000 storage_upload_by_filename #上传主文件 group_name=group1, remote_filename=M00/00/00/wKgBZ1ld3-aABZwCAAVIZEHwqlg477.jpg #传到了group1组,remote_filename就是上传文件的位置 source ip address: 192.168.1.103 #源IP是192.168.1.103,它负责把这个上传的文件同步到同组的其他机器 file timestamp=2017-07-06 14:59:50 #文件的创建时间 file size=346212 #文件的大小,单位是字节。 file crc32=1106291288 #文件crc32的验证码 example file url: #通过这个url链接就可以访问此文件 storage_upload_slave_by_filename #上传一个从文件,可以是缩略图之类的。 group_name=group1, remote_filename=M00/00/00/wKgBZ1ld3-aABZwCAAVIZEHwqlg477_big.jpg source ip address: 192.168.1.103 file timestamp=2017-07-06 14:59:50 file size=346212 file crc32=1106291288 example file url: http://192.168.1.103/group1/M00/00/00/wKgBZ1ld3-aABZwCAAVIZEHwqlg477_big.jpg
# fdfs_test1 /etc/fdfs/client.conf upload 1.jpg #古国文件不在当前目录下就要指定全路径了
tracker_query_storage_store_list_with_group: server 1. group_name=group1, ip_addr=192.168.1.103, port=23000 group_name=group1, ip_addr=192.168.1.103, port=23000 storage_upload_by_filename source ip address: 192.168.1.103 file timestamp=2017-07-06 15:00:31 file size=346212 file crc32=1106291288 example file url: http://192.168.1.103/group1/M00/00/00/wKgBZ1ld4A-ACkk7AAVIZEHwqlg858.jpg storage_upload_slave_by_filename source ip address: 192.168.1.103 file timestamp=2017-07-06 15:00:31 file size=346212 file crc32=1106291288 example file url: http://192.168.1.103/group1/M00/00/00/wKgBZ1ld4A-ACkk7AAVIZEHwqlg858_big.jpg
通过上面的信息来简述下上传的过程:
选择tracker server:
一般集群中不止一个tracker server,由于tracker之间是完全对等的关系,客户端在upload文件时可以任意选择一个trakcer。
选择存储的group:
当tracker接收到upload file的请求时,会为该文件分配一个可以存储该文件的group,这个配置文件里面已经定义了选择的规则。
选择storage server:
当选定group后,tracker会在group内选择一个storage server给客户端,当然也是配置文件里面定义好的选择规则,当时就是一台服务器,来作为为组内其他服务器同步的源机器。
选择storage 存储位置:
当分配好storage server后,客户端将向storage发送写文件请求,storage将会为文件分配一个挂载盘下面的二级目录,也是配置文件中已经定义好的。
生成文件名:
文件名:采用Base64编码,包含字段:源storage ip、文件创建UNIX时间戳、文件大小、文件内容crc32检验码、随机数。
生成FileID:
根据组名、磁盘、目录、文件名来生成一个File ID。
下面我们拿上面的一个File ID来分析一下:
group1/M00/00/00/wKgBZ1ld3-aABZwCAAVIZEHwqlg477_big.jpg #首先group1是组名.M00就是00为十六进制字符,表示存放的base path磁盘序号,如果文件要存放在/data02下面,这里就是M01,以此类推。/00/00就是存放到了store指定的挂载盘下面的/00/00下面。 #wKgBZ1ld3-aABZwCAAVIZEHwqlg477_big.jpg就是文件名了。 而还有个wKgBZ1ld3-aABZwCAAVIZEHwqlg477_big.jpg-m文件用来存储图片的元数据。
通过配置文件来查看下文件同步设置到的文件:
源192.168.1.103上面的查看:
#/opt/fastdfs/storage/data/sync
# cat 192.168.1.104_23000.mark
binlog_index=0 #对应于哪个binlog binlog_offset=1952 #偏移量,同步机器如果当前是文件同步完成状态,这里的值是一样的 need_sync_old=0 #是否需要同步旧文件给对方 sync_old_done=0 #若需要同步旧文件,那么旧文件是否同步完成 until_timestamp=0 #上次同步时间结点 scan_row_count=32 #总记录数 sync_row_count=32 #已同步记录数
被同步对象192.168.1.104上面的查看:
#/opt/fastdfs/storage/data/sync
# cat 192.168.1.103_23000.mark
binlog_index=0 binlog_offset=1952 need_sync_old=1 #是否获得了源主机的IP sync_old_done=1 until_timestamp=1499321435 #源主机负责的旧数据截止时间 scan_row_count=32 #总记录数 sync_row_count=0 #已同步记录数
两个主机都查看# cat binlog.000(内容是一样的):
1499324390 C M00/00/00/wKgBZ1ld3-aABZwCAAVIZEHwqlg477.jpg 1499324390 C M00/00/00/wKgBZ1ld3-aABZwCAAVIZEHwqlg477.jpg-m 1499324390 C M00/00/00/wKgBZ1ld3-aABZwCAAVIZEHwqlg477_big.jpg 1499324390 C M00/00/00/wKgBZ1ld3-aABZwCAAVIZEHwqlg477_big.jpg-m 1499324431 C M00/00/00/wKgBZ1ld4A-ACkk7AAVIZEHwqlg858.jpg 1499324431 C M00/00/00/wKgBZ1ld4A-ACkk7AAVIZEHwqlg858.jpg-m 1499324431 C M00/00/00/wKgBZ1ld4A-ACkk7AAVIZEHwqlg858_big.jpg 1499324431 C M00/00/00/wKgBZ1ld4A-ACkk7AAVIZEHwqlg858_big.jpg-m 1499324739 C M01/00/00/wKgBZ1ld4UOAKp7aAAVIZEHwqlg836.jpg 1499324738 C M01/00/00/wKgBZ1ld4UOAKp7aAAVIZEHwqlg836.jpg-m 1499324739 C M01/00/00/wKgBZ1ld4UOAKp7aAAVIZEHwqlg836_big.jpg 1499324738 C M01/00/00/wKgBZ1ld4UOAKp7aAAVIZEHwqlg836_big.jpg-m 1499328042 C M01/00/00/wKgBZ1ld7iqAUsaGAAVIZEHwqlg558.jpg 1499328042 C M01/00/00/wKgBZ1ld7iqAUsaGAAVIZEHwqlg558.jpg-m 1499328042 C M01/00/00/wKgBZ1ld7iqAUsaGAAVIZEHwqlg558_big.jpg 1499328042 C M01/00/00/wKgBZ1ld7iqAUsaGAAVIZEHwqlg558_big.jpg-m 1499328092 C M01/00/00/wKgBZ1ld7lyAZQNZAAVIZEHwqlg531.jpg 1499328092 C M01/00/00/wKgBZ1ld7lyAZPp-AAVIZEHwqlg680.jpg 1499328092 C M01/00/00/wKgBZ1ld7lyAAApkAAVIZEHwqlg111.jpg 1499328092 C M01/00/00/wKgBZ1ld7lyAQRn7AAVIZEHwqlg548.jpg 1499328092 C M01/00/00/wKgBZ1ld7lyAZQNZAAVIZEHwqlg531.jpg-m 1499328092 C M01/00/00/wKgBZ1ld7lyAZPp-AAVIZEHwqlg680.jpg-m 1499328092 C M01/00/00/wKgBZ1ld7lyAZQNZAAVIZEHwqlg531_big.jpg 1499328092 C M01/00/00/wKgBZ1ld7lyAAApkAAVIZEHwqlg111.jpg-m 1499328092 C M01/00/00/wKgBZ1ld7lyAQRn7AAVIZEHwqlg548.jpg-m 1499328092 C M01/00/00/wKgBZ1ld7lyAZPp-AAVIZEHwqlg680_big.jpg 1499328092 C M01/00/00/wKgBZ1ld7lyAAApkAAVIZEHwqlg111_big.jpg 1499328092 C M01/00/00/wKgBZ1ld7lyAQRn7AAVIZEHwqlg548_big.jpg 1499328092 C M01/00/00/wKgBZ1ld7lyAZQNZAAVIZEHwqlg531_big.jpg-m 1499328092 C M01/00/00/wKgBZ1ld7lyAZPp-AAVIZEHwqlg680_big.jpg-m 1499328092 C M01/00/00/wKgBZ1ld7lyAQRn7AAVIZEHwqlg548_big.jpg-m 1499328092 C M01/00/00/wKgBZ1ld7lyAAApkAAVIZEHwqlg111_big.jpg-m
#第一列:是同步时间戳
#第二列:是标记文件类型:C是源创建(c表示副本创建)、A是源追加(a表示副本追加)、D源删除(d表示副本删除)、T源Truncate(t表示副本Truncate)
#第三列:为文件路径及文件名
两个主机都查看# cat binlog.index (结果一般是0,表示现有binlog日志数,一般就一份)
来看一下文件同步的过程:
写文件时,客户端将文件写至group内一个storage server即认为写文件成功,storage server写完文件后,会由后台线程将文件同步至同group内其他的storage server。
每个storage写文件后,同时会写一份binlog,binlog里不包含文件数据,只包含文件名等元信息,这份binlog用于后台同步,storage会记录向group内其他storage同步的进度,以便重启后能接上次的进度继续同步;进度以时间戳的方式进行记录,所以最好能保证集群内所有server的时钟保持同步。
storage的同步进度会作为元数据的一部分汇报到tracker上,tracke在选择读storage的时候会以同步进度作为参考。源头数据才需要同步,备份数据不需要再次同步,否则就构成环路了。源头服务器会有专门的线程负责同步。
同一组内的storage server之间是对等的,文件上传、删除等操作可以在任意一台storage server上进行。文件同步只在同组内的storage server之间进行,采用push方式,即源服务器同步给目标服务器。
2.2 fdfs_upload_file和fdfs_upload_appender上传文件的使用
#一般用fdfs_upload_file命令上传文件,而且也不会像上面test命令似得,再产生一份从文件上去,就是一份主文件。
# fdfs_upload_appender
Usage: fdfs_upload_appender <config_file> <local_filename>
#fdfs_upload_file
Usage: fdfs_upload_file <config_file> <local_filename> [storage_ip:port] [store_path_index]
#从上面的显示已经可以看出差别的,上面的只能是最简单的上传,而后面的可以选择store服务器以及放到哪个目录下面。
# fdfs_upload_file /etc/fdfs/client.conf 1.jpg 192.168.1.104:23000
group1/M00/00/00/wKgBaFleCbuAA_6EAAVIZEHwqlg087.jpg
# fdfs_upload_file /etc/fdfs/client.conf 1.jpg 192.168.1.105:23000
group2/M00/00/00/wKgBaVleCdyAPvBdAAVIZEHwqlg557.jpg
# fdfs_upload_file /etc/fdfs/client.conf /root/3.jpg #当然这是最常用的方式
group1/M00/00/00/wKgBZ1leCgWANoqmAAFzy0pIUiM684.jpg
#当然fdfs_upload_file和fdfs_upload_appender还有一个差别就是fdfs_upload_appender可以文件附件,而前者上传的文件不支持文件附加。
2.3 fdfs_file_info查看文件信息
# fdfs_file_info
Usage: fdfs_file_info <config_file> <file_id>
如:# fdfs_file_info /etc/fdfs/client.conf group1/M00/00/00/wKgBZ1leCgWANoqmAAFzy0pIUiM684.jpg
source storage id: 0 source ip address: 192.168.1.103 file create timestamp: 2017-07-06 17:59:33 file size: 95179 file crc32: 1246253603 (0x4A485223)
2.4 fdfs_append_file文件附加
# cat 1.txt #创建了两个简单的文件
123
# cat 2.txt
321
# fdfs_upload_appender /etc/fdfs/client.conf /root/1.txt #先将1.txt上传上去
group1/M01/00/00/wKgBZ1leDD-EDYeZAAAAAFqCAvc803.txt
# fdfs_append_file /etc/fdfs/client.conf group1/M01/00/00/wKgBZ1leDD-EDYeZAAAAAFqCAvc803.txt /root/2.txt #然后再将/root/2.txt追加进去
# cat /data02/data/00/00/wKgBZ1leDD-EDYeZAAAAAFqCAvc803.txt
123 321
2.5 fdfs_delete_file 删除文件
# fdfs_delete_file
Usage: fdfs_delete_file <config_file> <file_id>
# fdfs_delete_file /etc/fdfs/client.conf group1/M01/00/00/wKgBZ1leDD-EDYeZAAAAAFqCAvc803.txt #删除刚才我们追加过的文件
# cat /data02/data/00/00/wKgBZ1leDD-EDYeZAAAAAFqCAvc803.txt #发现已经删除
cat: /data02/data/00/00/wKgBZ1leDD-EDYeZAAAAAFqCAvc803.txt: 没有那个文件或目录
2.6 fdfs_download_file下载文件
# fdfs_download_file
Usage: fdfs_download_file <config_file> <file_id> [local_filename] [<download_offset> <download_bytes>]
# fdfs_download_file /etc/fdfs/client.conf group1/M00/00/00/wKgBZ1leBySAbatmAACaihkibds085.jpg #直接将wKgBZ1leBySAbatmAACaihkibds085.jpg下载到本地不改名字
# fdfs_download_file /etc/fdfs/client.conf group1/M00/00/00/wKgBZ1leBySAbatmAACaihkibds085.jpg /tmp/2.jpg #也可以下载到指定的目录下更换为指定的名字
下载文件交互过程:
1. client询问tracker下载文件的storage,参数为文件标识(卷名和文件名);
2. tracker返回一台可用的storage;
3. client直接和storage通讯完成文件下载。
为了尽量避免访问到这样的storage,tracker按照如下规则选择group内可读的storage:
1. 该文件上传到的源头storage - 源头storage只要存活着,肯定包含这个文件,源头的地址被编码在文件名中。
2. 文件创建时间戳==storage被同步到的时间戳 且(当前时间-文件创建时间戳) > 文件同步最大时间(如5分钟) - 文件创建后,认为经过最大同步时间后,肯定已经同步到其他storage了。
3. 文件创建时间戳 < storage被同步到的时间戳。 - 同步时间戳之前的文件确定已经同步了。
4. (当前时间-文件创建时间戳) > 同步延迟阀值(如一天)。 - 经过同步延迟阈值时间,认为文件肯定已经同步了。
博文来自:www.51niux.com
2.7 fdfs_monitor查看fastdfs运行状态及操作
# fdfs_monitor
Usage: fdfs_monitor <config_file> [-h <tracker_server>] [list|delete|set_trunk_server <group_name> [storage_id]]
# fdfs_monitor /etc/fdfs/client.conf #查看fastdfs集群里面所有的storege的信息。
# fdfs_monitor /etc/fdfs/client.conf list group2 #也可以加list后面跟组名,只看某一个组的信息
[2017-07-07 10:53:25] DEBUG - base_path=/opt/fastdfs/client, connect_timeout=30, network_timeout=60, tracker_server_count=2, anti_steal_token=0, anti_steal_secret_key length=0, use_connection_pool=0, g_connection_pool_max_idle_time=3600s, use_storage_id=0, storage server id count: 0 ######tracker server情况部分: server_count=2, server_index=1 #server_count=2总共有两台tracker,server_index=1表示这台server的编号是1,说明前面还有一台tracker,第一台的编号是从0开始的。 tracker server is 192.168.1.104:22122 #这台tracker的IP地址是192.168.1.104端口是22122 #######组(卷)的情况部分: group name = group2 #所在卷组的名字,这里是group2 disk total space = 102350 MB #这个组的空间总大小 (以组中存储空间最小的节点为准),我是两块50G的盘,所以这里是100G。 disk free space = 102205 MB #剩余空间大小,基本也就是单个服务器所有挂载磁盘加起来的剩余空间 trunk free space = 0 MB #小文件合并,0MB就表示没有做小文件合并 storage server count = 2 #表示这个组一共由2台storage节点组成 active server count = 1 #存活的storage节点这里是1表示只有一台处于存活状态。 storage server port = 23000 #storage的端口 storage HTTP port = 8888 #这个没有意义因为我们编译安装的时候没加参数,storage就没开启http服务 store path count = 2 #这里是2表示有两个存储路径,也就是我们挂载了两块盘,线上一般是11到12 subdir count per path = 256 #每个目录下面有256个目录 current write server index = 0 #没做合并 current trunk file id = 0 #没做合并 #######storage(存储节点)的情况部分: Storage 1: #第一个存储节点 id = 192.168.1.105 #id,这里Id是用的默认用IP表示 ip_addr = 192.168.1.105 ACTIVE #此节点的IP地址,这里才是IP地址哦。主要是后面的ACTIVE这个表示该节点正常是存活状态 http domain = version = 5.10 #程序的版本号 join time = 2017-07-06 14:08:30 #该节点加入组的时间 up time = 2017-07-06 14:09:01 #该节点的启动时间 total storage = 102350 MB #该节点的存储空间总大小 free storage = 102205 MB #该节点的存储空间剩余情况 upload priority = 10 #上传优先级 store_path_count = 2 #有几个存储路径,也就是挂了几块存储盘 subdir_count_per_path = 256 #每级目录创建多少子目录 storage_port = 23000 #storage服务的端口号 storage_http_port = 8888 #Http端口号没用 current_write_path = 0 #合并没用 source storage id = #这里为空说明这个节点是源storage负责给别人分发 if_trunk_server = 0 connection.alloc_count = 256 connection.current_count = 1 connection.max_count = 3 total_upload_count = 16 #上传的总次数,如线上:3100139 success_upload_count = 16 #上传文件的总次数,如线上:3100139 total_append_count = 0 success_append_count = 0 total_modify_count = 0 success_modify_count = 0 total_truncate_count = 0 success_truncate_count = 0 total_set_meta_count = 10 #更改meta data次数 success_set_meta_count = 10 #成功更改meta data次数 total_delete_count = 0 #删除文件的总次数,会有数值,如47但是一般不多 success_delete_count = 0 #成功删除文件的总次数 total_download_count = 0 #下载文件总次数,如:5282446 success_download_count = 0 #成功下载文件总次数 total_get_meta_count = 0 #获取meta data次数,一般为0 success_get_meta_count = 0 #成功获取meta data次数 total_create_link_count = 0 #一般为0 success_create_link_count = 0 total_delete_link_count = 0 success_delete_link_count = 0 total_upload_bytes = 44005340 #总共上传了多少字节的文件,一般比使用量/2,稍小一点,一般文件上传了都会再产生一个从文件嘛。 success_upload_bytes = 44005340 total_append_bytes = 0 #附加操作使用了多少字节,一般为0或者很少,很少附加,因为一般都是存的图片什么的 success_append_bytes = 0 total_modify_bytes = 0 #修改的字节数,一般为0 success_modify_bytes = 0 stotal_download_bytes = 0 #下载的总字节,因为没有下载所以这里是0,但是一般这里很大的,如:4006784730483就表示下载量是4T左右。 success_download_bytes = 0 total_sync_in_bytes = 0 success_sync_in_bytes = 0 total_sync_out_bytes = 0 success_sync_out_bytes = 0 total_file_open_count = 16 success_file_open_count = 16 total_file_read_count = 0 success_file_read_count = 0 total_file_write_count = 34 success_file_write_count = 34 last_heart_beat_time = 2017-07-07 10:53:05 #最后存活检测时间 last_source_update = 2017-07-06 17:58:52 #最后源更新时间 last_sync_update = 1970-01-01 08:00:00 #最后同步更新时间,这就代表没同步,如果同步过或者正常情况下,这个值会比上面的值晚1到几秒而已。 last_synced_timestamp = 1970-01-01 08:00:00 Storage 2: id = 192.168.1.106 ip_addr = 192.168.1.106 OFFLINE #检测为离线状态 http domain = version = 5.10 join time = 2017-07-06 14:08:50 up time = 2017-07-06 14:08:50 total storage = 102350 MB free storage = 102246 MB upload priority = 10 store_path_count = 2 subdir_count_per_path = 256 storage_port = 23000 storage_http_port = 8888 current_write_path = 0 source storage id = 192.168.1.105 #获得了源storage id if_trunk_server = 0 connection.alloc_count = 256 connection.current_count = 0 connection.max_count = 0 total_upload_count = 0 success_upload_count = 0 total_append_count = 0 success_append_count = 0 total_modify_count = 0 success_modify_count = 0 total_truncate_count = 0 success_truncate_count = 0 total_set_meta_count = 0 success_set_meta_count = 0 total_delete_count = 0 success_delete_count = 0 total_download_count = 0 success_download_count = 0 total_get_meta_count = 0 success_get_meta_count = 0 total_create_link_count = 0 success_create_link_count = 0 total_delete_link_count = 0 success_delete_link_count = 0 total_upload_bytes = 0 success_upload_bytes = 0 total_append_bytes = 0 success_append_bytes = 0 total_modify_bytes = 0 success_modify_bytes = 0 stotal_download_bytes = 0 success_download_bytes = 0 total_sync_in_bytes = 0 success_sync_in_bytes = 0 total_sync_out_bytes = 0 success_sync_out_bytes = 0 total_file_open_count = 0 success_file_open_count = 0 total_file_read_count = 0 success_file_read_count = 0 total_file_write_count = 0 success_file_write_count = 0 last_heart_beat_time = 2017-07-07 10:52:56 last_source_update = 1970-01-01 08:00:00 last_sync_update = 1970-01-01 08:00:00 last_synced_timestamp = 1970-01-01 08:00:00 (never synced) #看最后的()里面的内容,从没有同步过
如果:# fdfs_monitor /etc/fdfs/storage.conf的话,还会多两个参数
group count: 2 #有几个组,这里表示有两个组 Group 1: #如group1组所在的组ID,从1开始
storage server有7个状态,如下:
# FDFS_STORAGE_STATUS_INIT #初始化,尚未得到同步已有数据的源服务器
# FDFS_STORAGE_STATUS_WAIT_SYNC #等待同步,已得到同步已有数据的源服务器
# FDFS_STORAGE_STATUS_SYNCING #同步中
# FDFS_STORAGE_STATUS_DELETED #已删除,该服务器从本组中摘除(注:本状态的功能尚未实现)
# FDFS_STORAGE_STATUS_OFFLINE #离线(当storage server的状态为FDFS_STORAGE_STATUS_ONLINE时,当该storage server向tracker server发起一次heart beat时,tracker server将其状态更改为FDFS_STORAGE_STATUS_ACTIVE。)
# FDFS_STORAGE_STATUS_ONLINE #在线,尚不能提供服务
# FDFS_STORAGE_STATUS_ACTIVE #在线,可以提供服务
三、fastdfs目录结构及相关文件
3.1 tracker server的目录及文件结构:
# tree -L 2 /opt/fastdfs/tracker/
/opt/fastdfs/tracker/ ├── data │ ├── fdfs_trackerd.pid #tracker的pid文件 │ ├── storage_changelog.dat #记录新加组之类的信息 │ ├── storage_groups_new.dat #存储分组的最基本信息,如有几个组,组名称什么的 │ ├── storage_servers_new.dat #存储服务器的详细信息 │ └── storage_sync_timestamp.dat #数据同步的主机以及时间戳 └── logs └── trackerd.log #tracker server日志文件,记录启动信息或者一些报错信息
3.2 storage server的目录及文件结构:
# tree -L 2 /opt/fastdfs/storage/
/opt/fastdfs/storage/ ├── data │ ├── fdfs_storaged.pid #storage的pid文件 │ ├── storage_stat.dat #当前storage server统计信息 │ └── sync #这个目录里面存放了数据同步相关文件上面已经介绍过了 └── logs └── storaged.log #storage server日志文件
# cat /opt/fastdfs/storage/data/.data_init_flag #这个文件tree看不出来
storage_join_time=1499321299 #本storage server创建时间 sync_old_done=1 #本storage server是否已完成同步的标志,1表示完成同步 sync_src_server=192.168.1.103 #向本服务器同步源数据的服务器IP,如果自己就是源数据服务器这里为空 sync_until_timestamp=1499321435 #同步已有数据文件截止时间(UNIX时间戳),如果这里是元数据服务器这里为0. last_ip_addr=192.168.1.104 last_server_port=23000 last_http_port=8888 current_trunk_file_id=0 trunk_last_compress_time=0
#注(fastdfs的监控):
监控基本也很简单,就是运行# fdfs_monitor /etc/fdfs/client.conf,主要是关注类似于ACTIVE这种的机器状态,查看是否是正常情况,不是ACTIVE这种状态就提示报警(除了新添加的机器要经历INIT==》WAIT_SYNC等,但很快就是ACTIVE状态了)。
四、FastDFS之磁盘恢复过程
既然作为存储频繁的磁盘大量读写,磁盘难免有损坏需要更换,下面来模拟一下这个磁盘更换的过程。FastDFS原生支持该过程,可以自动检测,并完成。FastDFS-Storaged程序在启动时会检查每个Store_path目录下的子目录个数,默认情况下,每个Store_path下面会创建两级256个子目录。当非首次启动时,发现某个Store_path下没有任何目录,则会进入磁盘恢复过程。该过程在代码的storage_disk_recovery.c之中。
4.1 模拟磁盘更换:
模拟磁盘替换:
# df -h #假设有个500G的盘坏了,我们现在将其换掉
/dev/vdc 500G 21G 480G 5% /data2
# fdfs_storaged /etc/fdfs/storage.conf stop #先要停止storage服务,不然进程会占用这块磁盘
waiting for pid [4357] exit ... pid [4357] exit.
# umount /data2
# mkfs.xfs /dev/vdc -f #如果是生产环境就是换块新盘上来然后格式化一下
# mount /dev/vdc /data2 #挂载一下
# mkdir /data2/fastdfs #现在/data2/fastdfs 目录下面空空如也没有那个2层的多级目录
# df -h
/dev/vdc 500G 52M 500G 1% /data2
# fdfs_storaged /etc/fdfs/storage.conf #将storage服务启动一下
# ls -la /data2/fastdfs/data/ #可以看到又两个隐藏文件,这也就是恢复过程产生的两个文件,恢复完这两个文件就会被删掉
total 3092 drwxr-xr-x 258 root root 8192 Apr 15 14:34 . drwxr-xr-x 3 root root 17 Apr 15 14:34 .. -rw-rw-rw- 1 root root 2742 Apr 15 14:34 .binlog.recovery -rw-r--r-- 1 root root 59 Apr 15 14:34 .recovery.mark drwxr-xr-x 258 root root 8192 Apr 15 14:34 00 drwxr-xr-x 258 root root 8192 Apr 15 14:34 01 drwxr-xr-x 258 root root 8192 Apr 15 14:34 02
磁盘恢复过程介绍:
磁盘恢复过程包括三个步骤:RecoveryStart、RecoveryStore、RecoveryFinish;这三个步骤之中的RecoveryStore可以多次执行,因此在恢复过程中记录了中间状态,因此即使在磁盘恢复过程中宕机或停止,下次再次启动时还是可以从上次的状态继续恢复数据。而RecoveryStart与RecoveryFinish都是只执行一次。
磁盘恢复过程的两个状态文件: .recovery.mark;.binlog.recovery,这两个状态文件保存与StorePath目录下,用于记录恢复过程的状态。
# cat .recovery.mark
saved_storage_status=5 #表示状态 binlog_offset=0 #表示恢复的binlog偏移量 fetch_binlog_done=1 #表示是否已经下载binlog
# cat .binlog.recovery #记录的是需要恢复的文件binlog,内容类似下面这样的记录:
1523772711 c M01/00/00/wKgOPVrS7SeAHfvwPoAAAIRrA200117980 1523772710 c M01/00/00/wKgOPVrS7SeAHfvwPoAAAIRrA200117980-m 1523772713 c M01/00/00/wKgOPVrS7SeAHfvwPoAAAIRrA200117980_big ...
# fdfs_monitor /etc/fdfs/client.conf #可以查看一下状态,可以看到提示是恢复状态
...... Storage 1: id = 192.168.1.105 ip_addr = 192.168.1.105 RECOVERY
# ls -la /data2/fastdfs/data/ #同步完成后那两个恢复文件会被删除掉
total 3084 drwxr-xr-x 258 root root 8192 Apr 15 14:37 . drwxr-xr-x 3 root root 17 Apr 15 14:34 .. drwxr-xr-x 258 root root 8192 Apr 15 14:34 00
4.2 文字描述这个过程
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。
#注意事项:
恢复过程中需要下载对应的binlog与文件,可能到A机器下载binlog,而到B机器下载文件。所有的文件只会在选择好的原Storage上下载,因此压力会集中到一台的Storage上。
下载文件的过程中是以单线程,同步的方式进行的,因此不能最大化磁盘IO或者网络性能。