什么是SeaweedFS

SeaweedFS是一种简单的、高度可扩展的分布式文件系统。SeaweedFS是一个非常优秀的由 go语言开发的分布式存储开源项目。它是用来存储文件的系统,并且与使用的语言无关,使得文件储存变得非常方便,它有两个优势:

  1. 存储数十亿的文件!
  2. 查看文件速度快!

SeaweedFS设计用来有效地存储处理小文件,较大文件可以分块拆分为小文件进行上传。所有文件的元数据不存储在Master节点,而是分散存储在Volume(逻辑卷,存储数据的逻辑结构)中,Master节点只保存卷 ID 到卷服务器的映射,这样一来,Master节点的查询压力就被分散到volume节点了。这些文件卷服务器各自管理各自的元数据,存储在卷服务器上的所有文件元信息都可以从内存中读取,而无需访问磁盘。所以这样在高并发的情况下减少了主节点的压力和网络通信,同时定位文件也更迅速。其主要应用场景是存储海量的图片信息并且可以快读定位。

weed是使用Go语言开发的,Github主页为:https://github.com/chrislusf/seaweedfs,使用weed可以通过源码编译,需要提前安装Go环境;也可以使用编译好的二进制包,不依赖Go环境直接执行。
Githup地址: https://github.com/chrislusf/seaweedfs
官方文档:https://github.com/chrislusf/seaweedfs/wiki

Gitee文档地址:https://gitee.com/mirrors/SeaweedFS/wikis/Home
相关背景技术博客:

seaweedfs源码解析:https://www.bbsmax.com/A/6pdDYXQKzw/

seaweedfs部署相关:https://www.bbsmax.com/A/n2d9Gw84JD/

http://www.wjhsh.net/quchunhui-p-14086075.html

http://www.diyhi.com/seaweedfs.html


相关定义说明

master 存储文件和fid映射关系(fid类似FastDFS的存储path)

Node 系统抽象的节点,抽象为DataCenter、Rack、DataNode

DataCenter 数据中心,对应现实中的不同机房

Rack 机柜,对应现实中的机柜,一个机柜属于特定的数据中心,一个数据中心可以包含多个机柜。

Datanode 存储节点,相当于服务器,用于管理、存储逻辑卷

Volume 逻辑卷,存储的逻辑结构,逻辑卷下存储Needle

Needle 逻辑卷中的Object,对应存储的文件, Needle 属于 Volume 里面的一个单元

Collection 文件集,可以分布在多个逻辑卷上,如果在存储文件的时候没有指定collection,那么使用默认的""

SeaweedFS工作原理

拓扑结构

DataNode 是树的叶子节点, DataCenter 和 Rack 是树的非叶子节点, DataCenter 是 Rack 的父母节点,每次查找对应的DataNode,都需要从 DataCenter -> Rack -> DataNode 依次找下去。

角色

Master Server:主控服务器,主要用来存储文件和fid映射关系,相当于一个调度中心,对多个数据卷服务器(Volume Server)进行统一的调度,分配文件ID(增加,删除,查找,定位等操作)。

Volume Server:数据卷服务器,提供存储和备份文件功能,数据卷服务器保存了文件元数据,通过访问文件元数据就可以操作数据卷中的文件。

  • 每个 MasterServer 维护多个 VolumeServer 。
  • 每个 VolumeServer 维护多个 Volume 。
  • 每个 Volume 包含多个 Needle ,Needle 即文件。

上传过程

当服务启动后,volume服务会定时的向master服务发送心跳信息。

如果Master是集群服务,则客户端上传文件时请求任意一个Master服务即可。这时Master服务会根据Volume服务的情况,分配生成Fid和Fid对应的Volume服务的URL。客户端根据返回的信息上传文件,通过volume服务完成文件写入到磁盘,并返回给客户端文件名称,文件大小等信息。

对应的流程图如下:

同步过程

流程图如下

下载过程

流程图如下


包含模块

Weed master 开启一个master服务器

Weed volume 开启一个volume 服务器

Weed filer 开启一个指向一个或多个master服务器的file服务器

Weed upload 上传一个或多个文件

Weed server 启动一个服务器,包括一个volume服务器和自动选举一个master服务器

......

1.Weed master

查看master的帮助

./weed help master  

实例

nohup ./weed master -ip=10.254.193.105 > /home/work/service/weedfs/master/master.log 2>&1&

参数

说明

-cpuprofile

输出cpu使用的统计信息

-defaultReplication

默认的副本类型(默认为000)

000: 只存储一份,默认设置
001: 在相同的Rack复制一份
010: 在同一DC的不同rack上复制一次
100: 在不同的DC复制一次
200: 在另外两个不同的DC上复制两次
110: 在不同的rack上复制一次,并在不同的DC上复制一次。

-disableHttp

关闭http接口,只使用gRPC来访问

-garbageThreshold

回收空间的阈值(默认为0.3)

-ip

master服务的ip地址,默认为localhost

-ip.bind

服务绑定的ip地址,默认为0.0.0.0

-mdir

存储元数据的目录,默认为/tmp

-memprofile

输出内存使用的统计信息

-metrics.address

性能指标统计工具的地址,seaweedfs使用prometheus来存储性能统计信息

-metrics.intervalSeconds

性能统计信息推送的间隔时间

-peers

所有的master节点列表。比如127.0.0.1:9093,127.0.0.1:9094

-port

master服务监听的端口,默认为9333

-pulseSeconds

心跳的间隔时间,默认为5秒

-volumePreallocate

为volumes预分配空间

-volumeSizeLimitMB

停止向超出大小限制的volume写入数据,默认为30000

-whiteList

ip白名单,只有在白名单中的ip才拥有写入权限

defaultReplication说明

000 不备份, 只有一份数据

001 在相同的rack(机架)里备份一份数据

010 在相同数据中心内不同的rack(机架)间备份一份数据

100 在不同的数据中心备份一份数据

200 在两个不同的数据中心各复制2次

110 在不同的rack备份一份数据, 在不同的数据中心备份一次

副本策略是x y z 形式的数字,其含义如下:

含义

x

在其他数据中心的副本数量

y

在相同数据中心,其他机架的副本数量

z

在相同机架,不同服务器的副本数量

2.Weed volume

./weed help volume 查看volume帮助

实例:

nohup ./weed volume -port=10001 -dir=/home/work/service/weedfs/volume01  -mserver=10.254.193.105:9333  > /home/work/service/weedfs/master/volume1.log 2>&1&

通常卷服务器分布在不同的计算机上。它们可以有不同的磁盘空间,甚至不同的操作系统。通常需要指定可用磁盘空间、Weed Master 位置和存储文件夹。

参数

说明

-compactionMBps

限制后台压缩以及拷贝的速度

-cpuprofile

输出cpu使用的统计信息

-dataCenter

volume服务的数据中心名称

-dir

存储数据文件的目录(可以指定多个目录,以逗号分隔),默认/tmp

-idleTimeout

闲置连接的超时时间,默认30秒

-images.fix.orientation

上传时调整图片文件的方向

-index

选择索引存储类型。可选memory leveldb leveldbMedium leveldbLarge,默认为memory。选择memory则索引的存取比较快,但是volume的启动会比较慢,因为启动时需要将文件的索引加载到内存中。如果选择leveldb索引的存取会稍微变慢一点,但是volume的启动会快很多

-ip

volume服务的ip地址

-ip.bind

volume服务绑定的ip地址

-max

volume的最大数量,默认为7。本机volumes的最大值,在master上我们定义的每个卷为30G,可是我们的磁盘不可能就这么点,而max的作用就是表示这个磁盘上可以分多少个卷,默认是7,也就是30G * 7 = 210G,很明显磁盘被浪费了很多空间,因此我们需要指定一个大max值,保证volumeSizeLimitMB * max >= 磁盘容量,当然你可以直接100,简单粗暴

-memprofile

输出内存使用的统计信息

-mserver

master服务,以逗号分隔,默认为localhost:9333

-port

http服务的监听端口,默认8080

-port.public

公共服务的端口

-publicUrl

公共服务的地址

-pulseSeconds

心跳的间隔时间,必须小于master的设置。默认5秒

-rack

volume服务的机架名称

-read.redirect

重定向

-whiteList

ip白名单,只有在白名单中的ip才拥有写入权限

3.Weed filer

参数              类型     说明

collection          String 所有数据将存储在这个集合中

dataCenter          String 首选在此数据中心写入volumes

defaultReplicaPlacement String 如果没有指定默认复制类型(默认000)

dirListLimit        Int   限制子目录列表大小

disableDirListing      无    关闭目录清单

ip               String Filter服务器http监听ip地址

master            String 用逗号分隔的master服务器(默认localhost:9333)

maxMB             Int 分割文件大于限制(默认32)

port             Int   Filer服务器htp监听端口(默认8888)

port.grpc          Int   Filer grpc服务器监听端口,默认为 http的端口+10000

port.public         Int   对外开放的端口

redirectOnRead       无    在文件GET请求期间是代理还是重定向到volumes服务器

secure.secret        String 加密Json Web令牌(JWT)的密钥

4.Weed upload

实例:

./weed upload -dir="/some/big/folder" -include=*.txt

此命令将递归上传所有文件。或者您可以指定要包含的文件。通常,如果要上传大量文本文件,由于文本文件会自动压缩,因此消耗的磁盘大小会小得多。

参数      类型     说明collection string 可选的集合名称

dataCenter String 可选的数据中心名称

debug     无   显示debug信息

dir      String 如果指定,则递归地上传整个文件夹。

include   String 需要上传的文件,跟-dir配合使用,例如*.pdf,*.html,ab?d.txt等

master    String Seaweedfs master服务器地址(默认”localhost:9333”)

maxMB     Int 如果文件超过指定大小则进行分割

replication string 备份类型

secure.secret string 加密Json Web令牌(JWT)的密钥

ttl      string 存活时间 1m,1h,1d,1M,1y

安装与配置

1、下载源码包

官网:https://github.com/chrislusf/seaweedfs/releases

根据操作系统进行选择,操作系统选择的是linux centos7,选择了下载linux_amd64.tar.gz

2、上传并解压缩

tar -zxvf linux_amd64.tar.gz

可以先查看一下weed命令的支持参数

命令:

./weed -h

3、启动 master

nohup ./weed master -ip=10.254.193.105  -mdir=/home/work/service/weedfs/master -defaultReplication=000   > /home/work/service/weedfs/master/master.log 2>&1&

命令解析:

master : master 服务

mdir : 存储元数据的数据目录

注意:

当单机启动多个master实例来管理多个存储时,一定要使用-mdir参数指定master服务元数据目录,如果不指定默认是/tmp,当多个实例分开时就会出现交叉的情况,当请求其中一个master时,会返回另外master管理的volume,引起很多问题,所以单节点部署多master一定要注意。

(1)-pulseSeconds
这个值越小, 当DataNode宕机后隔离出去的时间就越短, 同时多个master时这个值越小, master之间的故障切换时间就越短
(2)-ip
这个选项也特别重要, 尤其是在有多个master, 要设置peers时. 该参数设置为所在服务器的出口ip即可, 相当于表明自己是谁
(3)-peers
比如A,B,C共有3个master, 这3个的peers参数都可以设置为其中一个的ip地址,比如ABC这3个master启动时都设置peers参数为A的ip地址。同时volume在启动的时候也可以只到一个固定的ip,同样可以都设置为A服务器的ip地址。且需要特别注意:实测如果有3个master,则只允许一个master down机, 3个中宕一个, 可以自动切换,如果再宕一个,则无法切换了。 且3个master必须同时存在过,不能先启动A,B, 等A宕机以后再启动C,这样则会有问题,必须ABC都启动,完成以后如果有其中一台宕机,则是没有问题的。
实测发现, master启动前把日志和相关配置清理掉才最好, 否则重新启动时可能会有影响, 比如通过api查看到的peers信息不正确
另外:关于Replication其实有很多需要思考的地方, 但是这个与具体的应用场景关系比较密切。个人偏向于使用001这种备份方式,因为逻辑层次浅,结构清晰,扩展和管理也非常方便。

4、启动 volume

nohup ./weed volume -port=8081 -dir=/home/work/service/weedfs/volume01 -max=7 -fileSizeLimitMB=200 -mserver=10.254.193.105:9333  -dataCenter=dc1 -rack=rack1 >/home/work/service/weedfs/master/volume1.log 2>&1&

命令解析:volume端口默认指定为8080,-max指定是最大的卷个数,即这一个Volume服务管理几个卷

volume:volume服务

-dir:表示该DataNode数据存储的目录

-fileSizeLimitMB : 限制最大上传文件大小

-mserver :指定master服务地址

-dataCenter:当前volume服务的数据中心名称

-rack: 当前volume服务器的rack 名称

启动后可访问浏览器:

http://10.254.193.105:9333/

有几个重要选项:
-mserver
假设有A,B,C共3个master, 和5个volume, 则volume启动的时候都可以只指向A这一个master即可, 也完全正常的。

-rack

如果master启动时指定replication策略是001,那么就必须最少启动两个volume服务,实现对数据的备份,一个rack中至少要有2台服务器。为方便管理其实也只建议用2台服务器, 然后其它的服务器以新的rack加入。启动的volume01 和volume02 同属于一个机架rack1,那么volume01和volume02的数据是相同的两份。

建议在启动服务时都指定一下log_dir, 否则使用的默认值是/tmp目录, 生成的文件较多, 很难看.

文件的上传、查看、更新、删除、下载

(1)文件上传

获取fid,使用GET或POST访问路径http://localhost:9333/dir/assign,获取fid和上传文件地址,seaweedfs会返回json的结果。

如下

curl -X POST http://localhost:9333/dir/assign

得到结果:

{"fid":"8,06ca4883a0","url":"1ocalhost:8081","publicUrl":"localhost:8081","count":1}

fid就是上传的标志。

PostMan进行调用

Fid介绍

"fid":"14,f4187c8fdb" 就是 Fid,Fid 由三个部分组成 【VolumeId, NeedleId, Cookie】。

  • VolumeId: 14 32bit 存储的物理卷的Id
  • NeedleId: f4 64bit 全局唯一NeedleId,每个存储的文件都不一样(除了互为备份的)。
  • Cookie: 187c8fdb 32bit Cookie值,为了安全起见,防止恶意攻击。

其中8为卷id,是无符号的32位整数;后面的06为文件密钥,是64位无符号整数,以16进制编码;然后后面的ca4883a0是文件 Cookie值,32位无符号整数,这里用的4组16进制字符串表示长度为8,为了安全起见,防止恶意攻击。

VolumeId 是由 MasterServer 分配给 VolumeServer, 每个 VolumeServer 都维护个 n 个 Volume , 每个 Volume 都有一个专属 VolumeId,Needle 属于 Volume 里面的一个单元。

这个fid需要我们自己存储,第一种方式可以按照结构拆分为整数类型存储,最多占用4 + 8 + 4 = 16个字节;另一种方式我们直接可以存储这个串,字符串长度最多也就是是8 + 1 + 16 + 8 = 33,所以一个char 33的数组就够了,并且通常也没有卷编号能够达到2的32次方;这里是两种常用的存储方式,可以根据需要选择。

然后可以根据卷返回的url上传文件的,这里8对应的是8081端口这个服务,下面可以上传文件,使用url或者publicUrl加上fid,就是文件上传的地址。

如下:http://localhost:8081/14,f4187c8fdb

接着就可以发起一个PUT或POST请求到上面的地址,把文件上传上去。

curl -X PUT -F file=@/home/back.png http://localhost:8081/14,f4187c8fdb

http://localhost:8081为某个volume的部署地址。上传成功之后会返回文件名和大小,现在就上传成功了,原来的文件名不需要记录。

结果如下:

{"name": "back.png","size": 64300 }

可以使用PostMan进行调用上传

注意:这里上传文件调用的URL为获取fid后返回的地址

还可以上传整个目录,比如

./weed upload -master=localhost:9333 -dir=one_directory -include=*.pdf

-include:指定一类文件

因为默认情况下,VolumeServer 启动时, 未申请任何 Volume,当第一次 /dir/assign 的时候, 会分配 Volume,因为 weed volume 的参数 -max=7所以一次性分配 7个 Volume

(2)更新一个文件

直接发起POST或者PUT请求到url+fid的地址即可。fid就是保存图片使用的fid。

curl -X PUT -F file=@/home/back2.png http://localhost:8081/14,f4187c8fdb

PostMan进行调用

(3) 查看文件

当有多个Volume集群时,可以通过参数指定查看某个卷。

得到具体的地址:首先根据fid的卷编号(fid的第一位)获得卷对应的服务器地址

curl http://127.0.0.1:9333/dir/lookup?volumeId=14

返回json结果

{"volumeOrFileId":"14","locations":[{"url":"10.254.193.183:8081","publicUrl":"10.254.193.183:8081"}]}

卷对应的服务器地址 :10.254.193.183:8081

然后通过浏览器访问具体的路由:

http://localhost:8081/fid

比如:http://localhost:8081/14,f4187c8fdb
可以带后缀,也可以不带。
http://localhost:8081/14,f4187c8fdb.jpg

还可以带一些限定参数

http://localhost:8081/8,06ca4883a0.jpg
http://localhost:8081/8,06ca4883a0.jpg?height=200&width=200
http://localhost:8081/8,06ca4883a0.jpg?height=200&width=200&mode=fit
http://localhost:8081/18,06ca4883a0.jpg?height=200&width=200&mode=fill

PostMan调用

还可以

./weed download -server="localhost:9333"-dir="D:\data3"8,06ca4883a0

-dir指定要下载到本地的路径,fid就是文件id

(4)删除图片

发起一个DELETE请求即可。

curl -X DELETE http://localhost:8081/8,06ca4883a0

当删除成功是返回实际的大小,文件不存在时返回0

注意:小写不适应

也可以使用PostMan进行调用

从这里可以看出,SeaweedFS的接口调用支持REST规范的

(5)存储一个有效时限的文件

Seaweedfs按 Volume 来进行分块,当每次用户上传一个自带TTL的文件(需要定时删除的文件)时, 会把这个文件存储在合适的 Volume 里面, 存储的时候每个文件会带有 TTL 这个属性, 当读取出来之后发现该文件已经过期(超时时间到),则会返回一个 Not Found 结果, 而每个 Volume 维护一个最大超时时间,当这个时间抵达时,说明整个 Volume 所有的文件都超时了, 然后 VolumeServer 通知 MasterServer 这个 Volume 已经被标识为 Dead 状态, 意味着 MasterServer 不会再为这个 Volume 分配新的 Fid。 然后再经过一段合适的时间后由 VolumeServer 将这个 Volume 从磁盘上安全的删除掉。 详细请看在Seaweedfs自带的文档TTL。

假设我们要存储一个 TTL 为 1 分钟的文件。

首先,让 master 为一个 TTL 为 1 分钟的卷分配一个文件 id:

curl http://localhost:9333/dir/assign?ttl=1m
{"count":1,"fid":"5,01637037d6","url":"127.0.0.1:8080","publicUrl":"localhost:8080"}

然后,使用文件id存储在卷服务器上

curl -F "file=@x.go" http://127.0.0.1:8080/5,01637037d6?ttl=1m

写入后,如果在 TTL 到期前读取文件内容,将照常返回文件内容。但是如果在 TTL 到期后读取,则该文件将报告为丢失并返回 http 响应状态为未找到。

注意,“ttl=1m”被使用了两次!一种用于分配文件 ID,一种用于上传实际文件。第一个是让 master 选择匹配的卷,而第二个是与文件一起写入的。这两个 TTL 值不需要相同。只要volume TTL大于file TTL就可以了。

TTL 的格式为一个整数后跟一个单位。单位可以是“m”、“h”、“d”、“w”、“M”、“y”。

支持的 TTL 格式示例:

  • 3m:3分钟
  • 4小时:4小时
  • 5天:5天
  • 6 周:6 周
  • 7M:7个月
  • 8岁:8年

配置运行Filer并挂载到本地目录

(1)启动 Filter

seaweedfs支持像传统文件系统那样,将文件放在目录下管理,并通过文件路径对文件进行存储、获取和删除操作。seaweedfs对目录的支持是 通过另外一个server实现的:filer server。也就是说如果想拥有对目录的支持,则必须启动一个(或若干个) filer server,并且所有的操作都要通过filer server进行。Filer是一个在seaweedfs之上的服务,它保存路径与文件id的映射关系,最终还是使用文件id来访问文件。

Filer服务支持多种数据库来保存路径与文件id的映射关系,包括:leveldb2、mysql、postgres、cassandra、redis、redis_cluster、etcd、tikv。

生成一个配置文件,如下图

./weed scaffold -config=filer -output=. 

修改filer.toml,把filer的数据目录指向导 /home/work/service/weedfs/filer/data下

然后启动

nohup ./weed filer -port=8888  -master=10.254.193.105:9333 -ip=10.254.193.105  >/home/work/service/weedfs/filter/filter.log 2>&1&

上传文件

curl -F "filename=@/home/work/service/weedfs/cat.jpg" "http://10.254.193.105:8888/test/file/"

查看文件

http://10.254.193.105:8888/path/to/sources/

同时可以用postman进行调用

需要注意的是,请求的URL不带‘/’,则最后的路径为文件名,带‘/’则是文件夹

(2)mount挂载

seaweedfs可以方便地挂载到本地,可以像普通文件一样操作其中的文件,可以将filer挂载到本地某个目录进行管理

首先安装fuse

yum install -y fuse

启动mount

./weed mount -filer=10.254.193.105:8888 -dir=/home/work/service/weedfs/mount >/home/work/service/weedfs/filter/mount.log 2>&1&

然后就能在对应服务器的/home/work/service/weedfs/mount路径下查看相应文件了

以上就是weed的基本配置和使用,实际使用中weed还支持分布式多主和跨数据中心管理等,操作都比较简单,并且任何的卷挂掉之后,写入仍然可以写入,剩余正常的而不受影响,读取正常的卷上面的文件也不受影响,甚至主节点挂了如果知道对应的卷地址,访问图片仍然不受影响,这样生产环境的使用弹性就非常好。

创建文件目录

mkdir -p /data/seaweedfs/logs /data/seaweedfs/master /data/seaweedfs/volume/volume01 /data/seaweedfs/volume/volume02 /home/work/service/seaweedfs/master

部署相关

单机部署(defaultReplication=000)

设置一台master服务器,两台volume。备份策略为不备份

1、启动master

nohup ./weed master -ip=10.74.106.118 -port=9333 -mdir=/data/seaweedfs/master  > /home/work/service/seaweedfs/master/master.log 2>&1&

2、启动volume

nohup ./weed volume -port=10001 -dir=/data/seaweedfs/volume/volume01 -max=7 -fileSizeLimitMB=200 -mserver=10.74.106.118:9333 -dataCenter=dc1 -rack=rack1 >/data/seaweedfs/logs/volume1.log 2>&1&nohup ./weed volume -port=10002 -dir=/data/seaweedfs/volume/volume02 -max=7 -fileSizeLimitMB=200 -mserver=10.74.106.118:9333 -dataCenter=dc1 -rack=rack1 >/data/seaweedfs/logs/volume1.log 2>&1&

2、单机部署(defaultReplication=001)

设置一台master服务器,四台volume。备份策略:相同的rack里备份一份数据

1、启动master

nohup ./weed master -ip=10.74.106.119 -port=9333 -defaultReplication=001 -mdir=/data/seaweedfs/master  > /data/seaweedfs/logs/master.log 2>&1&

2、启动volume

nohup ./weed volume -port=10001 -dir=/data/seaweedfs/volume/volume01 -max=7 -fileSizeLimitMB=200 -mserver=10.74.106.119:9333 -dataCenter=dc1 -rack=rack1 >/data/seaweedfs/logs/volume1.log 2>&1&nohup ./weed volume -port=10002 -dir=/data/seaweedfs/volume/volume02 -max=7 -fileSizeLimitMB=200 -mserver=10.74.106.119:9333 -dataCenter=dc1 -rack=rack1 >/data/seaweedfs/logs/volume1.log 2>&1&nohup ./weed volume -port=10003 -dir=/data/seaweedfs/volume/volume03 -max=7 -fileSizeLimitMB=200 -mserver=10.74.106.119:9333 -dataCenter=dc1 -rack=rack2 >/data/seaweedfs/logs/volume1.log 2>&1&nohup ./weed volume -port=10004 -dir=/data/seaweedfs/volume/volume04 -max=7 -fileSizeLimitMB=200 -mserver=10.74.106.119:9333 -dataCenter=dc1 -rack=rack2 >/data/seaweedfs/logs/volume1.log 2>&1&

3、单机部署(defaultReplication=010)

设置一台master服务器,四台volume。备份策略:不同的rack里备份一份数据

1、启动master

nohup ./weed master -ip=10.74.106.119 -port=9333 -defaultReplication="010" -mdir=/data/seaweedfs/master  > /data/logs/master.log 2>&1&

2、启动volume

nohup ./weed volume -port=10001 -dir=/data/seaweedfs/volume/volume01 -max=7 -fileSizeLimitMB=200 -mserver=10.74.106.119:9333 -dataCenter=dc1 -rack=rack1 >/data/seaweedfs/volume1.log 2>&1&nohup ./weed volume -port=10002 -dir=/data/seaweedfs/volume/volume02 -max=7 -fileSizeLimitMB=200 -mserver=10.74.106.119:9333 -dataCenter=dc1 -rack=rack1 >/data/seaweedfs/volume1.log 2>&1&nohup ./weed volume -port=10003 -dir=/data/seaweedfs/volume/volume03 -max=7 -fileSizeLimitMB=200 -mserver=10.74.106.119:9333 -dataCenter=dc1 -rack=rack2 >/data/seaweedfs/volume1.log 2>&1&nohup ./weed volume -port=10004 -dir=/data/seaweedfs/volume/volume04 -max=7 -fileSizeLimitMB=200 -mserver=10.74.106.119:9333 -dataCenter=dc1 -rack=rack2 >/data/seaweedfs/volume1.log 2>&1&

集群部署(defaultReplication=000)

设置三台master服务器(必须为奇数),两台volume。备份策略为不备份

1、启动master

nohup ./weed master -ip=10.254.193.105 -port=9333 -mdir=/home/work/service/weedfs/master  -peers=10.254.193.183:9333,10.254.193.89:9333> /home/work/service/weedfs/master/master.log 2>&1&nohup ./weed master -ip=10.254.193.183 -port=9333 -mdir=/home/work/service/weedfs/master  -peers=10.254.193.105:9333,10.254.193.89:9333  > /home/work/service/weedfs/master/master.log 2>&1&nohup ./weed master -ip=10.254.193.89 -port=9333 -mdir=/home/work/service/weedfs/master  -peers=10.254.193.183:9333,10.254.193.105:9333,10.254.193.89:9333  > /home/work/service/weedfs/master/master.log 2>&1&

2、启动volume

nohup ./weed volume -port=10001 -dir=/home/work/service/seaweedfs/volume01 -max=7 -fileSizeLimitMB=200 -mserver=10.254.193.105:9333,10.254.193.183:9333,10.254.193.89:9333 -dataCenter=dc1 -rack=rack1 >/home/work/service/seaweedfs/master/volume1.log 2>&1&nohup ./weed volume -port=10002 -dir=/home/work/service/seaweedfs/volume02 -max=7 -fileSizeLimitMB=200 -mserver=10.254.193.105:9333,10.254.193.183:9333,10.254.193.89:9333 -dataCenter=dc1 -rack=rack1 >/home/work/service/seaweedfs/master/volume1.log 2>&1&

集群部署(defaultReplication=001)

设置多台台master服务器(必须为奇数),三台volume。备份策略:相同的rack里备份一份数据

1、启动master

nohup ./weed master -ip=10.74.106.119 -port=9333  -defaultReplication="001" -mdir=/data/seaweedfs/master  -peers=10.74.106.121:9333,10.74.106.122:9333  > /data/seaweedfs/logs/master.log 2>&1&nohup ./weed master -ip=10.74.106.121 -port=9333  -defaultReplication="001" -mdir=/data/seaweedfs/master  -peers=10.74.106.119:9333,10.74.106.122:9333  > /data/seaweedfs/logs/master.log 2>&1&nohup ./weed master -ip=10.74.106.122 -port=9333  -defaultReplication="001" -mdir=/data/seaweedfs/master  -peers=10.74.106.119:9333,10.74.106.121:9333  > /data/seaweedfs/logs/master.log 2>&1&

2、启动volume

nohup ./weed volume -ip=10.74.106.119 -port=10001 -dir=/data/seaweedfs/volume/volume01 -max=7 -fileSizeLimitMB=200 -mserver=10.74.106.119:9333,10.74.106.121:9333,10.74.106.122:9333 -dataCenter=dc1 -rack=rack1 >/data/seaweedfs/logs/volume1.log 2>&1&nohup ./weed volume -ip=10.74.106.119 -port=10002 -dir=/data/seaweedfs/volume/volume01 -max=7 -fileSizeLimitMB=200 -mserver=10.74.106.119:9333,10.74.106.121:9333,10.74.106.122:9333 -dataCenter=dc1 -rack=rack2 >/data/seaweedfs/logs/volume1.log 2>&1&nohup ./weed volume -ip=10.74.106.121 -port=10001 -dir=/data/seaweedfs/volume/volume01 -max=7 -fileSizeLimitMB=200 -mserver=10.74.106.119:9333,10.74.106.121:9333,10.74.106.122:9333 -dataCenter=dc1 -rack=rack1 >/data/seaweedfs/logs/volume1.log 2>&1&nohup ./weed volume -ip=10.74.106.122 -port=10001 -dir=/data/seaweedfs/volume/volume01 -max=7 -fileSizeLimitMB=200 -mserver=10.74.106.119:9333,10.74.106.121:9333,10.74.106.122:9333 -dataCenter=dc1 -rack=rack2 >/data/seaweedfs/logs/volume1.log 2>&1&

集群部署(defaultReplication=010)

设置多台台master服务器(必须为奇数),四台volume。备份策略:不同的rack里备份一份数据

1、启动master

nohup ./weed master -ip=10.254.193.105 -port=9333  -defaultReplication="001" -mdir=/home/work/service/weedfs/master  -peers=10.254.193.183:9333,10.254.193.89:9333> /home/work/service/weedfs/master/master.log 2>&1&nohup ./weed master -ip=10.254.193.183 -port=9333  -defaultReplication="001" -mdir=/home/work/service/weedfs/master  -peers=10.254.193.105:9333,10.254.193.89:9333  > /home/work/service/weedfs/master/master.log 2>&1&nohup ./weed master -ip=10.254.193.89 -port=9333  -defaultReplication="001" -mdir=/home/work/service/weedfs/master  -peers=10.254.193.183:9333,10.254.193.105:9333,10.254.193.89:9333  > /home/work/service/weedfs/master/master.log 2>&1&

2、启动volume

nohup ./weed volume -port=10001 -dir=/data/seaweedfs/volume/volume01 -max=7 -fileSizeLimitMB=200 -mserver=10.254.193.105:9333,10.254.193.183:9333,10.254.193.89:9333 -dataCenter=dc1 -rack=rack1 >/data/seaweedfs/volume1.log 2>&1&nohup ./weed volume -port=10002 -dir=/data/seaweedfs/volume/volume02 -max=7 -fileSizeLimitMB=200 -mserver=10.254.193.105:9333,10.254.193.183:9333,10.254.193.89:9333 -dataCenter=dc1 -rack=rack1 >/data/seaweedfs/volume1.log 2>&1&nohup ./weed volume -port=10003 -dir=/data/seaweedfs/volume/volume03 -max=7 -fileSizeLimitMB=200 -mserver=10.254.193.105:9333,10.254.193.183:9333,10.254.193.89:9333 -dataCenter=dc1 -rack=rack2 >/data/seaweedfs/volume1.log 2>&1&nohup ./weed volume -port=10004 -dir=/data/seaweedfs/volume/volume04 -max=7 -fileSizeLimitMB=200 -mserver=10.254.193.105:9333,10.254.193.183:9333,10.254.193.89:9333 -dataCenter=dc1 -rack=rack2 >/data/seaweedfs/volume1.log 2>&1&

配置volume启动脚本

[Unit]
Description=SeaweedFS Volume
After=network.target[Service]
Type=simple
User=root
Group=rootExecStart=/home/work/service/seaweedfs/master/weed volume -ip=10.74.106.119 -port=10001 -dir=/data/seaweedfs/volume/volume01 -max=7 -fileSizeLimitMB=200 -mserver=10.74.106.119:9333,10.74.106.121:9333,10.74.106.122:9333 -dataCenter=dc1 -rack=rack1
WorkingDirectory=/home/work/service/seaweedfs/master/
SyslogIdentifier=seaweedfs-volume[Install]
WantedBy=multi-user.target

使用配置好的系统服务管理seaweedfs-volume

systemctl enable seaweedfs-volume

配置开机启动

systemctl start seaweedfs-volume

启动

systemctl stop seaweedfs-volume

停止

systemctl restart seaweedfs-volume

重启

systemctl disable seaweedfs-volume

删除开机启动

systemctl daemon-reload

刷新

配置master启动脚本

10.74.106.119节点

[Unit]
Description=SeaweedFS Master
After=network.target[Service]
Type=simple
User=root
Group=rootExecStart=/home/work/service/seaweedfs/master/weed master -ip=10.74.106.119 -port=9333  -defaultReplication=001 -mdir=/data/seaweedfs/master  -peers=10.74.106.121:9333,10.74.106.122:9333
WorkingDirectory=/home/work/service/seaweedfs/master/
SyslogIdentifier=seaweedfs-master[Install]
WantedBy=multi-user.target

使用配置好的系统服务管理seaweedfs-master

systemctl enable seaweedfs-master

配置开机启动

systemctl start seaweedfs-master

启动

systemctl stop seaweedfs-master

停止

systemctl restart seaweedfs-master

重启

systemctl disable seaweedfs-master

删除开机启动

systemctl daemon-reload

刷新

其他相关知识了解

1、强一致性

Seaweedfs 的备份是强一致性的。 当一个 VolumeServer 接受到上传文件的 POST 请求时, 将该文件作为一个 Needle 写入本地 Volume 之后, 会根据该文件所分配的 VolumeId 判断是否需要备份, 如果需要备份,则进行备份(需要请求另外其它的 VolumeServer 服务器)。当备份完毕后,再对该 POST 请求进行答复。 所以用户每次上传图片时,当收到了答复之后, 则可以认为此备份已完成。这个和最终一致性不同,属于强一致性。类似的像FastDFS的文件备份采用的是后台线程将文件同步至其他的storage server,具体是每个storage写文件后,都会写一份binlog,binlog中包含文件数据,文件名等一些元信息,用于数据同步,同步数据的进度以时间戳的方式记录,所以,在集群环境下,要保证所有的server服务时钟的保持同步。

Seaweedfs的文件同步和RocketMQ的同步刷盘类似,先进行数据同步,在进行信息处理。

删除文件时,会在本地删除完成后,通过master获取副本的其他volume server,然后本机向其他volume server发起删除副本的操作。

实际上对于每台 VolumeServer 查找其它备份机器的时候, 也是通过如上 HTTP API 向 MasterServer 询问。 只不过不是每次都询问,因为只要询问过了之后就会缓存下来,只有在缓存里面找不到才询问。

即:存储文件时,当多个副本都存储成功后,才会返回成功;任何一个副本存储失败,此次存储操作则返回失败。
删除文件时,当所有副本都删除成功后,才返回成功;任何一个副本删除失败,则此次删除操作返回失败。

2、扩容

对于 Seaweedfs 来说,扩容非常简单。

当 VolumeServer1 因为抵达 Volume 大小上限而无法继续接受上传数据时, 此时继续 submit 上传数据 MasterServer 则会返回错误(因为在 MasterServer 内已经将 VolumeServer1 标记为不可写)。

此时直接再启动 VolumeServer2 即可。此时 VolumeServer2 启动之后会自动向 MasterServer 的 Topology 结构注册新的 DataNode , 当 MasterServer 接受到新的 submit 请求的时候,会将该上传文件写入 VolumeServer2 (因为此时 VolumeServer1 已经不可写)。

也就是说如果当线上出现容量问题的时候,扩容只需要加机器即可,简单有效。

3、Volume 的大小限制

在每次 VolumeServer 向 MasterServer 发送心跳信息的时候, 会在 storage.VolumeInfo.Size 里面注明当前 Volume 的大小信息(Size)。 所以可以以此来限制 Volume 的大小。当 VolumeInfo.Size 大于 VolumeLayout.volumeSizeLimit 时, 则将该 Volume 标记为不可写。 而VolumeLayout.volumeSizeLimit 的值可以在启动 MasterServer 的时候配置。

每个 Volume 的最大 Size 默认是 30G , 而每个 VolumeServer 可以配置 n 个 Volume,根据所在机器不同的硬盘大小配置不同的 n。所以默认情况下,当一个 VolumeServer 使用的磁盘超过 7 * 30G = 210G 之后, 该 VolumeServer 属于只读状态, MasterServer 不会再分配新的 Fid 给它。

但是其实这里会有漏洞,如果此时不通过请求 MasterServer 获取 Fid, 而是直接自己构造 Fid 向 VolumeServer POST 文件的话, VolumeServer 还是会一直接受上传的文件, 直到大小超过在 storage/needle.go 里面写死的一个常量。

其实在 VolumeServer 里面也有维护一个变量叫 volumeSizeLimit ,此变量的值是从 MasterServer 获取的, 当每次 VolumeServer 写入 Needle 到 Volume 的时候, 都会检查 Volume Size 是否超过 volumeSizeLimit , 当超过的时候会打错误日志, 但是不会停止写入,也就是不会拒绝上传的文件。 有且只有当大小超过 MaxPossibleVolumeSize 的时候才会拒绝写入磁盘。

4、副本策略

seaweedfs的副本机制是volume层面,而不是文件层面的。这意味着不同的节点存在相同的volume,其中的文件也是相同的。

volume启动时可以通过-dataCenter和-rack指定数据中心和机架。

seaweedfs的副本机制就是通过在不同的数据中心和机架创建相同的volume来实现的。

在master启动时可以指定副本的策略:

./weed master -defaultReplication=001

副本策略是xyz形式的数字,其含义如下:

含义

x

在其他数据中心的副本数量

y

在相同数据中心,其他机架的副本数量

z

在相同机架,不同服务器的副本数量

x,y,z分别可以是0,1,2,因此有9种副本类型组合。每种副本类型都创建了x+y+z+1个文件。

5、其他特性

可以选择是否使用数据副本,以及副本的级别

master servers失败自动漂移-杜绝单点故障

根据文件的mime类型自动进行gzip压缩(linux查看文件的mime类型,file --mime-type)

删除及更新操作之后通过压缩实现自动的磁盘空间回收

集群中的服务器之间可以存在不同的磁盘空间,文件系统,操作系统

seaweedfs一些有用的命令

查看集群信息:http://10.254.193.183:9333/cluster/status?pretty=y

查看集群toplogy结构:http://10.254.193.105:9333/dir/status?pretty=y

强制垃圾回收:curl “http://localhost:9333/vol/vacuum” curl “http://localhost:9333/vol/vacuum?garbageThreshold=0.4”

查看卷信息:curl http://10.254.193.105:8081/status?pretty=y

{"DiskStatuses": [{"dir": "/home/work/service/weedfs/volume01","all": 25040347136,"used": 1656799232,"free": 23383547904,"percent_free": 93.383484,"percent_used": 6.6165185}],"Version": "30GB 2.77 5cf332357bd0d006fb23d026abc632135ccb7114","Volumes": [{"Id": 1,"Size": 2168379,"ReplicaPlacement": {},"Ttl": {"Count": 0,"Unit": 0},"DiskType": "","Collection": "","Version": 3,"FileCount": 20,"DeleteCount": 1,"DeletedByteCount": 122279,"ReadOnly": false,"CompactRevision": 0,"ModifiedAtSecond": 0,"RemoteStorageName": "","RemoteStorageKey": ""},{"Id": 2,"Size": 111747516,"ReplicaPlacement": {},"Ttl": {"Count": 0,"Unit": 0},"DiskType": "","Collection": "","Version": 3,"FileCount": 15,"DeleteCount": 2,"DeletedByteCount": 1479139,"ReadOnly": false,"CompactRevision": 0,"ModifiedAtSecond": 0,"RemoteStorageName": "","RemoteStorageKey": ""},{"Id": 3,"Size": 103386548,"ReplicaPlacement": {},"Ttl": {"Count": 0,"Unit": 0},"DiskType": "","Collection": "","Version": 3,"FileCount": 17,"DeleteCount": 0,"DeletedByteCount": 0,"ReadOnly": false,"CompactRevision": 0,"ModifiedAtSecond": 0,"RemoteStorageName": "","RemoteStorageKey": ""},{"Id": 4,"Size": 13856237,"ReplicaPlacement": {},"Ttl": {"Count": 0,"Unit": 0},"DiskType": "","Collection": "","Version": 3,"FileCount": 9,"DeleteCount": 0,"DeletedByteCount": 0,"ReadOnly": false,"CompactRevision": 0,"ModifiedAtSecond": 0,"RemoteStorageName": "","RemoteStorageKey": ""}]
}

seaweedfs集群的负载均衡和高可用

负载均衡

通过Nginx的负载均衡机制实现集群的负载均衡

高可用

SeaweedFS自身具备Master Servers的失败自动漂移-杜绝单点故障,但是当客户端配置连接Master集群的某个节点时,后期这个节点挂掉后,我们就会无法正常的访问相应信息,所以我们需要配置Master节点高可用。

1、Nginx的主动健康检查实现集群的高可用

被动健康检查,Nginx本身有被动健康检查,只有当有访问时后,才发起对后端节点探测。如果本次请求中,节点正好出现故障,Nginx依然将请求转交给故障的节点,然后再转交给健康的节点处理。所以不会影响到这次请求的正常进行。但是会影响效率,因为多了一次转发,而且自带模块无法做到预警。

主动地健康检查。Nginx定时主动地去ping后端的服务列表,当发现某服务出现异常时,把该服务从健康列表中移除,当发现某服务恢复时,又能够将该服务加回健康列表中。淘宝有一个开源的实现nginx_upstream_check_module模块。官网:http://tengine.taobao.org/document_cn/http_upstream_check_cn.html

2、后台程序定时获取seaweedfs集群信息,自动判断集群leader进行处理

客户端可以设定每隔一段时间就请求一下当前连接的Master节点,判断当前节点是否是Leader,并将其他的Master节点服务缓存下来,当下次当前节点挂掉后,就会从缓存中获取任意一个节点进行请求,再次执行上面步骤。

/*** Fetch core server by seaweedfs Http API.* 获取seaweedfs集群的leader服务* @param masterUrl Core server url with scheme.* @return Cluster status.*/@SuppressWarnings("unchecked")private SystemClusterStatus fetchSystemClusterStatus(String masterUrl) throws IOException {MasterStatus leader;List<MasterStatus> peers;String resultString = null;try {resultString = RestTemplateUtils.getTemplateIp( masterUrl+ RequestPathStrategy.checkClusterStatus);}catch (Exception e){throw new SeaweedfsException("获取seaweedfs集群的leader服务异常 [" + masterUrl + "]");}log.info("seaweedfs cluster server info:{}",resultString);Map<String, Object> mapCluster = JSON.parseObject(resultString, Map.class);if (null == mapCluster) {throw new SeaweedfsException("获取seaweedfs集群的leader服务异常[" + masterUrl + "]");}//不应该直接指定leader,应该先判断是否leader//比如在docker环境中,masterUrl是leader,但是返回的Leader值是docker的容器ipif (mapCluster.get("IsLeader") != null && ((Boolean) mapCluster.get("IsLeader"))) {leader = new MasterStatus(masterUrl);} else {if (mapCluster.get("Leader") != null) {leader = new MasterStatus((String) mapCluster.get("Leader"));} else {throw new SeaweedfsException("not found seaweedfs core leader");}}peers = new ArrayList<MasterStatus>();if (mapCluster.get("Peers") != null) {List<String> rawPeerList = (List<String>) mapCluster.get("Peers");for (String url : rawPeerList) {MasterStatus peer = new MasterStatus(url);peers.add(peer);}}if (mapCluster.get("IsLeader") == null || !((Boolean) mapCluster.get("IsLeader"))) {peers.add(new MasterStatus(masterUrl.replace("http://", "")));peers.remove(leader);leader.setActive(ConnectionUtil.checkUriAlive(this.httpClient, leader.getUrl()));if (!leader.isActive()) {throw new SeaweedfsException("seaweedfs core leader is failover");}} else {leader.setActive(true);}for (MasterStatus item : peers) {item.setActive(ConnectionUtil.checkUriAlive(this.httpClient, item.getUrl()));}return new SystemClusterStatus(leader, peers);}

文件重复上传-校验 MD5值

将文件的MD5值与Fid存储在数据库中,每次上传前都先查询一下数据量是否存在此MD5值的Fid,如果存在,直接返回Fid,如果不存在,先上传文件,返回FId后将文件MD5值与Fid存储在数据库中,以便下次校验使用。

SeaweedFS介绍安装集群部署总结相关推荐

  1. 02_Storm集群部署

    1. 部署前的硬件及软件检查 硬件要求 1)storm集群部署包括zookeeper部署,而zookeeper集群最小为3台机器 2)storm的计算过程都在内存中完成,因此内存要尽量大 3)stor ...

  2. Nginx集群部署方案

    工作需要,记录一下 一.Nginx安装 集群部署需要在主服务器安装Nginx服务,以下为安装步骤: 1.访问Nginx官网(http://nginx.org/en/download.html),下载N ...

  3. elasticsearch2.3安装以及集群部署

    摘要: elasticsearch安装以及集群部署 一.下载 1.1安装elasticsearch-2.3.3要求是安装官方新版的Java,必须是JDK 1.7以上,1.7以下执行的时候会报以下错误. ...

  4. KubeOperator总体介绍(K8S集群部署管理工具)

    总体介绍⚓︎ KubeOperator 是一个开源的轻量级 Kubernetes 发行版,专注于帮助企业规划.部署和运营生产级别的 Kubernetes 集群. KubeOperator 提供可视化的 ...

  5. Kafka集群部署详细步骤(包含zookeeper安装步骤)

    Kafka集群部署 注意:如果jdk1.8和zookeeper都安装设置过之后可以直接安装kafka跳过其它步骤 kafka基础简介及基本命令 1.环境准备 1.1集群规划 node01  node0 ...

  6. Greenplum学习实践-【安装部署】-2、 5.10集群部署

    Greenplum学习实践-[安装部署]-2. 5.10集群部署 第 1 章** 环境说明 1.1 官方文档 Greenplum官方安装说明: https://gpdb.docs.pivotal.io ...

  7. 大数据介绍及集群安装

    大数据介绍及集群安装 第一部分 <大数据概述> 传统数据如何处理? 什么是大数据? 传统数据与大数据的对比 大数据的特点? 大数据前/后服务器系统安装部署区别是什么?. 大数据生态系统以及 ...

  8. Linux中级实战专题篇:rabbitmq(消息中间件p2p模式和pub模式,消息队列rabbitmq详解,单机安装,集群部署以及配置实战)

    一.消息中间件相关概念 1.简介 消息中间件也可以称消息队列,是指用高效可靠的消息传递机制进行与平台相关 的数据交流,并基于数据通信来进行分布式系统的集成.通过提供消息传递和消息 队列模型,可以在分布 ...

  9. Swarm集群搭建( docker安装、docker-compose安装、portainer可视化安装、基本使用命令总结、项目集群部署案例)

    docker安装.docker-compose安装.Swarm集群搭建.portainer可视化安装.和项目部署案例 四台服务器,我这里选用四台虚拟机1核2G,系统centos7,ip:192.168 ...

  10. 手动安装K8s第三节:etcd集群部署

    手动安装K8s第三节:etcd集群部署 准备安装包 https://github.com/coreos/etcd 版本:3.2.18 wget https://github.com/coreos/et ...

最新文章

  1. maven小节,Nexus私服,构件打包发布,动态资源过滤,自动部署到本地或远程服务器...
  2. 小程序【笔记002】逻辑层简介
  3. 1215 数组的宽度
  4. c语言删除一个字符指令,【C语言】实现一个基于命令行的文本编辑器
  5. IOS--Tableview选中一个cell
  6. OAuth 授权的工作原理是怎样的?
  7. 20200723每日一句
  8. odoo13 订单模板设置_ERP输出嵌入公章的采购订单电子档,其实真的不难
  9. 多元线性回归练习-预测房价
  10. 基于JavaWeb的小说阅读网站设计与实现 毕业论文+答辩PPT+项目源码及数据库文件
  11. ESP32笔记(2) flash使用
  12. 目前比较好用的同步网盘@2012
  13. activity工作流引擎
  14. oracle文章收藏
  15. 【GYM101409】2010-2011 ACM-ICPC, NEERC, Western Subregional Contest
  16. DataCamp课程 <Tidyverse> Chapter.3 分组和概括
  17. 2008521美赛E题
  18. 分布式锁,redisson是如何解决死锁问题
  19. 经颅聚焦超声信号仿真(MATLAB k-Wave仿真)
  20. 相遇,相知,相离 —《秒速5厘米》

热门文章

  1. Silvaco仿真学习
  2. 动手深度学习 李沐 pytorch版本 基于Win10环境配置
  3. 自学C语言的步骤--菜鸟篇
  4. idea安装教程(傻瓜式操作、永久使用)
  5. 工作中使用到的单词(软件开发)_2022-06-01备份
  6. android 模拟器好用哪个,安卓模拟器哪个好用 常用安卓模拟器性能大盘点
  7. 简约毕业论文答辩PPT模板
  8. matlab积分器,MATLAB_SIMULINK__积分器相关操作
  9. “驱动程序在 \Device\Harddisk0\D 上检测到控制器错误”的根本解决办法!
  10. 【Linux】文件系统及软硬连接