关于分布式文件系统 之前已经写过一些随笔 不过没怎么用心 本篇详细的整理一下


背景

  海量存储、系统负载的迁移、服务器吞吐的瓶颈等等 让文件系统独立于业务系统 提高整个项目的扩展性以及可维护性

  目前主流的方案 MFS FASTDFS GFS LUSTRE HADOOP等等

  我选择的是FASTDFS 用一句广告语来说 “免费、快速、找得到”。FASTDFS的作者是淘宝的资深架构师余庆,很诙谐、很有爱!!!其他方案还没玩过 暂不评论。


简介 

  FastDFS是一款开源的轻量级分布式文件系统纯C实现,支持Linux、FreeBSD等UNIX系统类google FS,不是通用的文件系统,只能通过专有API访问,目前官方提供了C、Java和PHP API为互联网应用量身定做,追求高性能和高扩展性,FastDFS可以看做是基于文件的key value pair存储系统,称作分布式文件存储服务更为合适。

  特点:

  分组存储,灵活简洁
  对等结构,不存在单点
  文件ID由FastDFS生成,作为文件访问凭证。FastDFS不需要传统的name server
  和流行的web server无缝衔接,FastDFS已提供apache和nginx扩展模块
  大中小文件均可以很好支持,支持海量小文件存储
  存储服务器上可以保存文件附加属性

  名词解释:

  Tracker Server:跟踪服务器,主要做调度工作,在访问上起负载均衡的作用。在内存中记录集群中group和storage server的状态信息,是连接Client和Storage server的枢纽。 因为相关信息全部在内存中,Tracker server的性能非常高,一个较大的集群(比如上百个group)中有3台就足够了。
   Storage Server:存储服务器,文件和文件属性(meta data)都保存到存储服务器上。


实践-服务端

  系统:ubuntu

  开发工具:vim

  web服务:nginx

  基于socket自定义通信协议

  服务端的安装参考官方文档 有不懂的可以联系虫子 这里说下问题比较多的2个地方 一个是libevent的版本问题 另一个是ubuntu最新版本中对于libpthread等库文件的存放位置问题

  安装完fastdfs以后 假设你的服务端程序安装在/usr/local目录 

  我们会在bin目录下找到以下文件

  【C#|.NET】利用FastDFS打造分布式文件系统_c# .net

  storage服务器启动命令 /usr/local/bin/fdfs_storaged /FastDFS/conf/storage.conf

  tracker服务器启动命令 /usr/local/bin/fdfs_trackerd /FastDFS/conf/tracker.conf

  我们运行monitor查看下配置信息

group count: 1

Group 1:
group name = test
free space = 5 GB
storage server count = 2
active server count = 2
storage_port = 23000
storage_http_port = 0
store path count = 1
subdir count per path= 3
current write server index = 0

	Host 1:
		ip_addr = 192.168.234.139 (ubuntu)  ACTIVE
		total storage = 9GB
		free storage = 5GB
		total_upload_count = 2
		success_upload_count = 2
		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
		last_heart_beat_time = 2012-01-05 18:45:50
		last_source_update = 2012-01-05 01:20:28
		last_sync_update = 1969-12-31 16:00:00
		last_synced_timestamp= 1969-12-31 16:00:00
	Host 2:
		ip_addr = 192.168.234.140  ACTIVE
		total storage = 18GB
		free storage = 12GB
		total_upload_count = 16
		success_upload_count = 16
		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
		last_heart_beat_time = 2012-01-05 18:45:50
		last_source_update = 2012-01-05 01:54:02
		last_sync_update = 1969-12-31 16:00:00
		last_synced_timestamp= 1969-12-31 16:00:00

 storage.conf整理汉化版

disabled=false
#配置是否生效
group_name=g1
#storage所在组(卷)
bind_addr=
# 绑定IP,另一太 storage IP为 192.168.6.101
client_bind=true
#bind_addr通常是针对server的。当指定bind_addr时,本参数才有效。
port=13334
# 是storage 服务端口
connect_timeout=30
# 连接超时时间,针对socket套接字函数connect
network_timeout=60
# storage server 网络超时时间,单位为秒。
heart_beat_interval=30
# 心跳间隔时间,单位为秒
stat_report_interval=60
# storage server向tracker server报告磁盘剩余空间的时间间隔,单位为秒。
base_path=/opt/fastdfs/storage
# base_path 目录地址,根目录必须存在  子目录会自动生成
# 会产生data(数据存储地方)、 logs日志文件
max_connections=256
# 最大连接数
buff_size = 256KB
# 设置队列结点的buffer大小。
work_threads=1
# 工作线程数
disk_rw_separated = true
# 磁盘IO读写是否分离,缺省是分离的。
disk_reader_threads = 1
# 针对单个存储路径的读线程数,缺省值为1
disk_writer_threads = 1
# 针对单个存储路径的写线程数,缺省值为1
sync_wait_msec=200
# 同步文件时,如果从binlog中没有读到要同步的文件,休眠N毫秒后重新读取,0表示不休眠,立即再次尝试读取。
sync_interval=0
#  同步上一个文件后,再同步下一个文件的时间间隔,单位为毫秒,0表示不休眠,直接同步下一个文件。
sync_start_time=00:00
sync_end_time=23:59
# 允许系统同步的时间段 (默认是全天) 。一般用于避免高峰同步产生一些问题而设定,相信sa都会明白。
write_mark_file_freq=500
# 把storage的mark文件定期同步到磁盘的时间间隔,单位为秒
store_path_count=1
# 存放文件时storage server支持多个路径(例如磁盘)。这里配置存放文件的基路径数目,通常只配一个目录。
store_path0=/opt/fastdfs

# 逐一配置store_path个路径,索引号基于0。注意配置方法后面有0,1,2 ......,需要配置0到store_path - 1。
# 如果不配置base_path0,那边它就和base_path对应的路径一样。
subdir_count_per_path=32
# FastDFS存储文件时,采用了两级目录。这里配置存放文件的目录个数
tracker_server=192.168.234.139:13333
# tracker_server 的列表 要写端口的哦
log_level=info
# 日志级别
run_by_group=root
# 运行storage 用户组
run_by_user=root
# 运行storage 用户
allow_hosts=*
# 允许连接IP列表
file_distribute_path_mode=0
# 文件在data目录下分散存储策略。
# 0: 轮流存放
# 1: 随机存储
file_distribute_rotate_count=100
# 当上面的参数file_distribute_path_mode配置为0(轮流存放方式)时,本参数有效。
#当一个目录下的文件存放的文件数达到本参数值时,后续上传的文件存储到下一个目录中
fsync_after_written_bytes=0
# 当写入大文件时,每写入N个字节,调用一次系统函数fsync将内容强行同步到硬盘。0表示从不调用fsync
sync_log_buff_interval=10
# 同步或刷新日志信息到硬盘的时间间隔,单位为秒
sync_binlog_buff_interval=60
# 同步binglog(更新操作日志)到硬盘的时间间隔,单位为秒
sync_stat_file_interval=300
# 把storage的stat文件同步到磁盘的时间间隔,单位为秒。
thread_stack_size=512KB
#线程栈的大小。FastDFS server端采用了线程方式。
#线程栈越大,一个线程占用的系统资源就越多。
upload_priority=10
#本storage server作为源服务器,上传文件的优先级,可以为负数。值越小,优先级越高。这里就和 tracker.conf 中store_server= 2时的配置相对应了
if_alias_prefix=
check_file_duplicate=0
#是否检测上传文件已经存在。如果已经存在,则不存在文件内容,建立一个符号链接以节省磁盘空间。 结合 fastdfh使用的。 1是检测,0是不检测,我们不使用fastdfh 当然 0 
key_namespace=FastDFS
# 当上个参数设定为1 或 yes时 (true/on也是可以的) , 在FastDHT中的命名空间
keep_alive=0
# 与FastDHT servers 的连接方式 (是否为持久连接) 

# 下面是http的配置了就不多说了
http.disabled=true
http.domain_name=
http.server_port=80
http.trunk_size=256KB
http.need_find_content_type=true

 tracker.conf整理汉化版

disabled=false
#配置是否生效
bind_addr=
#绑定IP
port=13333
#服务端口
connect_timeout=30
#连接超时时间
network_timeout=60
#  tracker server的网络超时,单位为秒。
base_path=/opt/fastdfs/tracker
#目录地址,里面会创建data(存放存储服务器信息)、logs,日志文件
max_connections=256
#系统提供服务最大连接数
work_threads=4
#线程数,通常设置CPU数
store_lookup=2
#上传组(卷) 的方式 0:轮询方式 1: 指定组 2: 平衡负载(选择最大剩余空间的组(卷)上传)这里如果在应用层指定了上传到一个固定组,那么这个参数被绕过
store_group=g1
#当上一个参数设定为1 时 (store_lookup=1,即指定组名时),必须设置本参数为系统中存在的一个组名。如果选择其他的上传方式,这个参数就没有效了
store_server=0
#选择哪个storage server 进行上传操作(一个文件被上传后,这个storage server就相当于这个文件的storage server源,会对同组的storage server推送这个文件达到同步效果)
# 0: 轮询方式
# 1: 根据ip 地址进行排序选择第一个服务器(IP地址最小者)
# 2: 根据优先级进行排序(上传优先级由storage server来设置,参数名为upload_priority)
store_path=0
#选择storage server 中的哪个目录进行上传。storage server可以有多个存放文件的base path(可以理解为多个磁盘)。
# 0: 轮流方式,多个目录依次存放文件
# 2: 选择剩余空间最大的目录存放文件(注意:剩余磁盘空间是动态的,因此存储到的目录或磁盘可能也是变化的)
download_server=0
#选择哪个 storage server 作为下载服务器
# 0: 轮询方式,可以下载当前文件的任一storage server
# 1: 哪个为源storage server 就用哪一个 (前面说过了这个storage server源 是怎样产生的) 就是之前上传到哪个storage server服务器就是哪个了
reserved_storage_space = 0.1GB
#storage server 上保留的空间,保证系统或其他应用需求空间(指出 如果同组的服务器的硬盘大小一样,以最小的为准,也就是只要同组中有一台服务器达到这个标准了,这个标准就生效,原因就是因为他们进行备份)
log_level=info
#选择日志级别
run_by_group=
#操作系统运行FastDFS的用户组
run_by_user=
#操作系统运行FastDFS的用户
allow_hosts=*
#可以连接到此 tracker server 的ip范围(对所有类型的连接都有影响,包括客户端,storage server)
sync_log_buff_interval = 10
# 同步或刷新日志信息到硬盘的时间间隔,单位为秒
# 注意:tracker server 的日志不是时时写硬盘的,而是先写内存。
check_active_interval = 120
# 检测 storage server 存活的时间隔,单位为秒。
# storage server定期向tracker server 发心跳,如果tracker server在一个check_active_interval内还没有收到storage server的一次心跳,那边将认为该storage server已经下线。所以本参数值必须大于storage server配置的心跳时间间隔。通常配置为storage server心跳时间间隔的2倍或3倍。
thread_stack_size = 64KB
# 线程栈的大小。FastDFS server端采用了线程方式。更正一下,tracker server线程栈不应小于64KB,不是512KB。
# 线程栈越大,一个线程占用的系统资源就越多。如果要启动更多的线程(V1.x对应的参数为max_connections,V2.0为work_threads),可以适当降低本参数值。
storage_ip_changed_auto_adjust = true
# 这个参数控制当storage server IP地址改变时,集群是否自动调整。注:只有在storage server进程重启时才完成自动调整。
storage_sync_file_max_delay = 86400
# V2.0引入的参数。存储服务器之间同步文件的最大延迟时间,缺省为1天。根据实际情况进行调整
storage_sync_file_max_time = 300
# V2.0引入的参数。存储服务器同步一个文件需要消耗的最大时间,缺省为300s,即5分钟。
http.disabled=true
# HTTP服务是否不生效 当然编译的时候我已经把 with_httpd宏去掉了,
http.server_port=80
# HTTP服务端口
# 下列参数只有 开启http服务才有用
http.check_alive_interval=30
http.check_alive_type=tcp
http.check_alive_uri=/status.html
http.need_find_content_type=true

 Web服务

  FastDfs本身提供了组的概念,不同的组可以用不同的域名,如果是图片等类型资源,利用多个子域名在网站优化中是很有帮助的。不过如果你想在一个域名下实现多个服务器的分布式方案,可以利用nignx的反向代理来做urlrewrite。

  举个简单的例子

 server {
         listen       80;
         server_name 192.168.234.140;
	index index.html index.htm index.php;	
	root  /app/test;

	location /g1{
         proxy_pass http://192.168.234.139;	
       }
}

 分布式算法

  和memcached这些分布式系统不同。Fastdfs的分布式算法是在服务端实现,Fish也在不断改良着算法。最新的是avl树。不过貌似有整rbtree的趋势。

 负载均衡,同步

  fastdfs还内置了组内的同步功能,不过我觉得对于我的项目可用性不大,因为我要实现的是狭义的分布式文件系统只要能保证海量的可扩展存储方案就可以了,同步、负载均衡之类的就交给专业的运维们吧。

  同步功能没有开关配置,在同步时间设置上作手脚就可以了。

  sync_start_time,sync_end_time


 实践-客户端  

  系统:windowsXP

  开发工具:VS2008

 首先我们来看下基本功能

找张mm图片  -_____-

【C#|.NET】利用FastDFS打造分布式文件系统_c# .net_02

 上传成功 对比一下

【C#|.NET】利用FastDFS打造分布式文件系统_c# .net_03

  然后再看看分布式结果

【C#|.NET】利用FastDFS打造分布式文件系统_c# .net_04

192.168.234.139上

【C#|.NET】利用FastDFS打造分布式文件系统_c# .net_05

192.168.234.140上

【C#|.NET】利用FastDFS打造分布式文件系统_c# .net_06

web上浏览

【C#|.NET】利用FastDFS打造分布式文件系统_c# .net_07

性能方面 和服务器本身的带宽 吞吐都有关系 不过作为文件系统 对稳定性的要求更大 而fastdfs的很多实例都证明了这一点


看完上面 是不是觉得很容易入手 当然 fastdfs的深度应用还有很多 

对于.net下 fastdfs的应用 大家有什么疑问可以联系我

本篇先到此 希望对大家有帮助