项目地址:https://code.google.com/p/weed-fs/
weed-fs是一个简单且高性能的分布式存储系统, 它有两个目标:
weed-fs选择了 key~file 映射的方式实现文件寻址, 而不是POSIX文件系统已有的机制, 这有点类似于nosql系统, 你可以称之为“NoFS”
weed-fs的实现机制是管理volumes服务器, 而不是在一个中心阶段管理所有的元文件, volumes服务器可以管理文件及其元文件, 这种机制可以大大的缓解了中心节点的压力, 并且可以将元文件保存在volumes服务器的内存中, 而且文件自动采用Gzip 压缩 , 从而保证了文件的访问速度
weed-fs的理论模型可参考 Weed-FS models after Facebook's Haystack design paper. http://www.usenix.org/event/osdi10/tech/full_papers/Beaver.pdf
使用方式
weed-fs的master节点默认运行在9333端口,而volume节点运行在 8080 端口, 比如可以通过以下方式启动一个master节点和两个volume节点, 这里所有节点跑在localhost上, 但你可以跑在多台机器上
启动master节点./weed master
启动volume节点
weed volume -dir="/tmp" -volumes=0-4 -mserver="localhost:9333" -port=8080 -publicUrl="localhost:8080" & weed volume -dir="/tmp/data2" -volumes=5-7 -mserver="localhost:9333" -port=8081 -publicUrl="localhost:8081" &
写文件
一个简单的保存文件的例子 curl http://localhost:9333/dir/assign {"fid":"3,01637037d6","url":"127.0.0.1:8080","publicUrl":"localhost:8080"}
第一步发送http GET请求获得文件的fid和volume服务器的url: curl -F file=@/home/chris/myphoto.jpg http://127.0.0.1:8080/3,01637037d6 {"size": 43234}
第二步发送http的 multipart POST请求(url+'/'+fid) 存储实际的文件
保存文件ID
你可以保存文件fid,3,01637037d6到任何一个数据库中, 3表示volume服务器id,这是一个无符号的32位整型数字, 逗号后面的 01表示文件id,这是一个无符号的64位整型 ,最后的637037d6表示文件cookie, 它是一个无符号的32位整型, 用户保护url的安全访问 文件ID和cookie ID都是十六进制编码, 你可以按照你自己的格式对元组进行保存, 比如把fid当作字符串,理论上你需要 8+1+16+8=33 bytes个字节
读取文件
这里有一个如何根据url访问的例子
curl http://localhost:9333/dir/lookup?volumeId=3 {"Url":"127.0.0.1:8080","PublicUrl":"localhost:8080"}
首先通过volumeId查询 volume 服务器的url,由于通常情况下, volume 服务器不会很多, 也不会经常变动,所以你可以缓存查询结果 现在你可以通过url从volume服务器上加载所需要的文件: http://localhost:8080/3,01637037d6.jpg
架构
对于大部分的分布式存储系统, 会把文件分成很多chunk,中心节点保存文件名与chunk索引的映射,chunk索引中包含chunk server 和chunk handler等信息, 这种方式不能处理有效的处理大量的小文件,而且访问请求也会通过master节点, 在高并发的情况下, 响应会很慢。
在weed-fs中, 采用volumes server管理数据, 每个volume的大小为32GB,并且能够持有大量的文件,每个存储节点有多个volume节点,master节点只需要管理volume的元数据即可,而实际文件的元文件则储存在各个 volume 中, 每个元文件的大小为16 bytes,所有的文件访问均可在内存中处理,而硬盘操作仅仅是在实际的文件读取时才开始
Master Server and Volume Server
架构非常简单,实际数据存储在volumes里, 一个volume服务器包含多个volumes,可同时支持读写操作,所有的volumes被 master server管理, master server包含了volume与volume server的映射关系,这种静态的对应关系可以很轻松的被缓存
对于每次的写请求, master server也会生成文件的key,因为写没有读那么频繁, 所以一个master server可就可以应对大量的请求
读写文件
但客户端发出写请求, master server 返回, 之后客户端想 volume 节点发出POST请求, 以REST的方式传送文件内容,当客户端需要读取文件, 它需要向master server或者缓存中获取, 最后用过public url获取内容
存储大小
在当前的设计中, 每个volume可以存储32GB的数据, 所以单个文件的大小是受制于volume的大小的, 但这个容量是可以在代码中调整的
内存储存
所有 volume server上的元文件信息是存储在内存中的, 而不需要从硬盘中读取, 每个元文件都是16字节大小的映射表
同类产品比较
HDFS的特点是分割大文件, 能很完美的读写大文件 WeedFS的特点是偏向于小文件, 追求更高的速度和并发能力
MogileFS有三层组件: tracers,database,storage nodes. WeedFS有两层组件:directory server,storage nodes. 多一层组件就意味着:很慢的访问、很复杂的操作以及更高的出错几率
GlusterFS是跟POSIX规范完全兼容的, 所以更复杂 WeedFS只有一部分兼容POSIX
Mongo's GridFS 采用MongoDB管理分隔后的chunks, 每次的读写请求都需要数据的查询元文件信息,对于少量请求是没有问题的, 但对于高并发的场景, 它很容易挂掉 WeedFS采用volume管理实际的数据, 查询任务分摊到各个volume节点, 所以很容易应对高负载的场景