0%

一步步教你使用 MogileFS

关于 MogileFS 系列其他文章的传送门

  1. 《 一步步教你使用 MogileFS 》      您当前所在位置

  2. 《 生产环境中如何使用 Nginx 反代 MogileFS 》



logo

一、了解分布式文件系统

1. 为什么要使用分布式文件系统?

在一个网站中,网站的架构、页面的排版格式可能会发生变化,但是商品的图片可能很久都不会变化的。一般情况下这些静态内容会存放在一个单独的存储设备内,在对这写静态内容做缓存时也是比较容易加速的,当然也可以通过互联网 CDN 加速。

为什么不把图片这种静态文件保存在 Redis 或 Memcached 中呢?

对于 Redis 或 Memcached,它们都属于对象存储,对象存储的意思是每一个数据流的元数据和数据本身都在一个文件体中存放,能够自我描述,自我解析,不需要依赖外部。
而图片的格式、种类等千差万别,很难全部塞进 Redis 中,所以一般会将图片保存在文件系统形式的存储设备中。
一般用来保存这种静态文件的服务器,为了高可用和更好的性能,会使用分布式存储系统。

2. 分布式文件系统的组织逻辑

分布式存储系统有两种组织逻辑,分为 无中心节点有中心节点

无中心节点:必须能够通过任意一台主机,获取到整个集群中的所有元数据,再通过元数据中关于数据的存储位置来找到数据。

  • GlusterFS 就属于无中心节点的结构。但是在分布式存储中最常见的是有中心节点。

有中心节点:是同一时刻只有一个节点负责提供元数据查询,这个节点存放了所有的元数据,其他节点是辅助节点,数据会保持同步。

  • Hadoop 的分布式文件系统 HDFS 就是属于有中心节点的典型代表。

3. 一些分布式文件系统程序的对比说明

  • HDFS:HDFS 会将元数据放置在中心节点的内存中,并定期同步至磁盘,这点和 Redis 很相似。但是带来的问题是:能够存储的数据容量大小会受限于内存的容量,所以这并不适合存放海量数据。于是就有了另一个解决办法,就是把元数据存储在其他地方,比如磁盘,甚至是 MariaDB 数据库中,而内存中只加载一部分热区数据用来提速。

  • MogileFS:是一种把元数据存储在 MariaDB 数据库中的解决办法,这样就可以适用在存储海量文件的场景中。但是如果数据量非常大,MariaDB 运行起来也会非常吃力,好在文件大部分是一次建立,多次读取,也就是读多写少的,所以可以把 MariaDB 构建成一主多从的模式,来缓解请求的压力。但是既然选择 MariaDB 这样的数据库,就不适合规模太大的场景,比较适合中小或者略具规模的企业使用。

  • TFS:淘宝在 HDFS 基础上做了二次研发了,突破了对文件数量的限制,支持对上亿级文件的存储支持。

  • FastDFS:国内的开源软件,是在 MogileFS 的基础上加以改进,使其不再依赖外部的数据库组件,而是将元数据放置在内存中。

  • HeyStack:Facebook 的图片存储,已经开源了。

  • SeaweedFS:一个性能强劲的分布式文件系统,可以存储数十亿的文件,特别适合存储图片文件,但是现在还少有在生产环境中使用的,不过以后可能会比较流行,甚至可能会替代 MogileFS。

本文主要讲解 MogileFS。

二、什么是 MogileFS ?

MogileFS 是一个开源的分布式文件存储系统,是由 LiveJournal 旗下的 Danga Interactive 公司开发。Danga 团队还开发了包括 Memcached、Perlbal 等不错的开源项目。

1. MogileFS 的特性

(1). 无单点故障

MogileFS 分布式文件存储系统安装的三个组件(存储节点、跟踪器、跟踪用的数据库),均可运行在多个机器上,因此没有单点故障。(你也可以将跟踪器和存储节点运行在同一台机器上,这样你就没有必要用4台机器)推荐至少两台机器。

  • 跟踪器(Tracker Nodes):中心节点;
  • 跟踪用的数据库:用于存储元数据,一般将数据放置在 MySQL 或 MariaDB 中;
  • 存储节点(Storage Nodes):只用于存储数据;

(2). 传输中立,无特殊协议

  • MogileFS 分布式文件系统的客户端可以通过 WebDAV/HTTP 协议来和 MogileFS 的存储节点来通信,但首先需要告知跟踪器。这样带来的好处是每个存储节点其实就是一个 web 服务器,用户可以通过 URL 的形式来追踪每一个文件名,并支持使用 WebDAV。

  • WebDAV 支持使用以 PUT 的形式来创建文件,以 DELETE 来删除文件,以 GET 来访问文件,但是如果想修改文件就要先删除再上传,不支持在线修改,最多可以支持在文件的尾部追加数据。

  • 这样前端就可以使用 Nginx 作为反代来响应客户端的请求,但是获取数据需要先去 Tracker Node 节点获取元数据,然后根据元数据提供的路径再去 Storage Node 节点去读取数据,但是 Nginx 本身并不支持这样的操作,需要安装第三方插件来实现。另一个好处是因为访问 Tracker Node 节点的时候也使用了 HTTP 协议,这样就可以用 Nginx 对多个 Tracker Node 节点做负载均衡,然后使用 Keepalived 对两个 Nginx 做冗余,整个图片集群就实现了高可用。

(3). 自动的文件复制

基于不同的文件“分类”,文件可以被自动的复制到多个有足够存储空间的存储节点上,这样可以满足这个“类别”的最少复制要求。比如你有一个图片网站,你可以设置原始的 JPEG 图片需要复制至少三份,但实际只有 1or2 份拷贝,如果丢失了数据,那么 MogileFS 分布式文件存储系统可以重新建立遗失的拷贝数。用这种办法,MogileFS(不做RAID)可以节约磁盘,否则你将存储同样的拷贝多份,完全没有必要。

(4). 简单的命名空间

文件通过一个给定的 key 来确定,是一个全局的命名空间。为防止在同一 MogileFS 中会造成 key 冲突,可以自己生成多个域来作为命名空间,而域都是同级的。

(5). 不需要 RAID

  • 在一个非存储区域网络的 RAID(non-SAN RAID)的建立中,磁盘是冗余的,但主机不是,如果你整个机器坏了,那么文件也将不能访问。而 MogileFS 分布式文件存储系统在不同的机器之间进行文件复制,因此文件始终是可用的。

  • 在 MogileFS 中的磁盘可以是做了 RAID 的也可以是没有,如果是为了安全性着想的话 RAID 没有必要买了,因为 MogileFS 分布式文件存储系统已经提供了。

2. MogileFS 的组成部件

MogileFS 由三个组件组成:

  • (1): Tracker Nodes
  • (2): 数据库
  • (3): Storage Nodes

下面分别介绍这三个组件:

(1) Tracker 跟踪器、调度器

Tracker 是 MogileFS 的核心部分,表现为运行的一个守护进程 MogileFSd,负责的工作有:

  • Replication:负责节点文件复制,确保每个文件有指定文件的副本,默认是 2 个;
  • Deletion:文件删除,因为删除一个文件只需要删掉元数据就好了;
  • Query:元数据查询,提供文件的查询功能;
  • Reaper:存储失败重置,当存储文件副本失败时进行重置;
  • Monitor:健康监测,对各个 Storage Nodes 节点做健康检测;

(2) 数据库

数据库用来存放 MogilefS 的元数据(包括命名空间,文件在哪里的信息),由 Trackers 来操作和管理它,你可以用 mogdbsetup 程序来初始化数据库的表结构。因为数据库保存了 MogileFS 的所有元数据,如果此数据库挂了,那么整个 MogileFS 都将处于不可用的状态,因此最好是 HA 结构的。

(3) Storage Nodes 存储节点

存储节点其实就是实际存放数据的地方,用来做删除、存放、重命名等事情。对数据的读取可通过 Web 协议来实现,所以实际上存储节点就是一个 Web 服务器,使用任何支持 HTTP 协议的程序都可以,默认使用一个基于 perl 语言开发的支持 HTTP 协议的程序,这里推荐使用 Nginx。

request

3. MogileFS 的工作逻辑

首先了解两个概念

  • Domain:一个 MogileFS 内可以有多个 Domain,每个 Domain 是一个名称空间,可以对应给不同的项目,在同一个 Domain 内,文件是不允许重名的。
  • Class:负责文件属性管理,定义文件存储在不同设备上的份数。

在一个 Domain 内可以划分出多个 Class,Class 为最小复制单元,每个 Class 用于维护一部分文件,可以理解为一个个分片,冗余时是对每个 Class 做副本。

request

客户端访问时的逻辑

每个文件都有一个 ID,也就是 FID,客户端访问时是通过 Domain 的名称加 FID 来查找。Class 只是用来做复制的,Domain 的名称才是真正标记 FID 位置的。

Domain 的名称可以理解为是名称空间的 Key

数据存储逻辑

存储节点在存储数据时,是存放在 Class 中,再把 Class 存放在文件系统的某个目录上。Class 属于一个黑盒状态。

在每一个数据节点上找一个专用的存储空间来存放 Tracker 所指定的元数据,一般是一个目录,但是这个目录在 Tracker 中被标记为一个 Device,每个 Device 都有一个 DeviceID,是不能删除的,需要配置在 MogileFS 中,用于通知给 Tracker 节点。

其实上面所说的 Device 就像 Nginx 中的 DocmentRoot 一样,而真正的 Device 是位于 RocmentRoot 内部的子目录,为每一个 Device 存放数据,命名的方式为固定格式 dev$id

三、安装 MogileFS

在 CentOS 7 上安装 MogileFS 有两种方法,第一使用别人做好的适用于 CentOS 7 的 rpm 包,第二就是使用 Cpan 在线安装并解决依赖关系。

这里使用 rpm 的安装方式,先把需要用到的 rpm 包进行上传,并使用 yum 安装。

以下是适用于 CentOS 7 的 rpm 包:

1
2
3
4
5
6
7
8
9
[root@linux-node3 ~]# ls
MogileFS-Server-2.46-2.el7.centos.noarch.rpm # 公共组件
MogileFS-Server-mogilefsd-2.46-2.el7.centos.noarch.rpm # Tracker 守护进程
MogileFS-Server-mogstored-2.46-2.el7.centos.noarch.rpm # Storage Node 守护进程
MogileFS-Utils-2.19-1.el7.centos.noarch.rpm # MogileFS 的工具包
nginx_mogilefs_module-1.0.4.tar.gz
perl-Danga-Socket-1.61-1.el6.rf.noarch.rpm
perl-MogileFS-Client-1.14-1.el7.centos.noarch.rpm
perl-Perlbal-1.78-1.el6.noarch.rpm

1. 安装 Tracker 节点

实验环境的主机信息:

IP 主机名 用途
192.168.50.11 node1 Tracker node、Storage node
192.168.50.12 node2 Storage node
192.168.50.13 node3 MariaDB、Storage node

安装依赖环境

1
yum install perl-Net-Netmask perl-IO-stringy perl-Sys-Syslog perl-IO-AIO -y 

安装刚才上传的 rpm 包

1
yum install *.rpm -y

初始化数据库
授权 root 远程权限。

1
2
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'monster' WITH GRANT OPTION;
FLUSH PRIVILEGES;

再使用 mogdbsetup 程序初始化 mogilefs 的数据库,并指定要为 mogilefs 创建的账号名、密码、和数据库名。

1
~]# mogdbsetup --dbhost=192.168.50.13 --dbrootuser=root --dbrootpass=monster --dbname=mogilefs --dbuser=mogilefs --dbpass=mogilefs

编辑配置文件

  • vim /etc/mogilefs/mogilefsd.conf
    • db_dsn = DBI:mysql:mogilefs:host=192.168.50.13:使用基于 DBI 库连接哪个数据库的哪个库名;
    • db_user = mogilefs:这里写刚才创建的 mogilefs 账号;
    • db_pass = mogilefs:这里写刚才创建的 mogilefs 账号的密码;
    • listen = 0.0.0.0:7001:定义要监听的地址和端口;
    • conf_port = 7001:定义向 Storage 节点发送管理信息的端口;
    • query_jobs = 10:定义要启用几个线程负责查询;
    • delete_jobs = 1:定义要启用几个线程负责删除;
    • replicate_jobs = 5:定义要启用几个线程负责复制;
    • reaper_jobs = 1:定义要启用几个线程负责 reaper;
    • min_free_space = 200:最小空间;

创建 PID 目录

1
2
mkdir -pv /var/run/mogilefsd
chown mogilefs:mogilefs /var/run/mogilefsd

启动服务
我这里启动遇到了问题,后来改用 restart 而不是 start 解决了。

1
systemctl restart mogilefsd

2. 安装 Storage 节点

在每个 Storage 节点上都执行以下步骤。

安装依赖环境

1
yum install perl-Net-Netmask perl-IO-stringy perl-Sys-Syslog perl-IO-AIO -y 

安装刚才上传的 rpm 包

1
yum install *.rpm -y

编辑配置文件

  • vim /etc/mogilefs/mogilefsd.conf
    • maxconns = 10000:定义最大并发连接数;
    • httplisten = 0.0.0.0:7500:向客户端提供文件时监听的地址和端口;
    • mgmtlisten = 0.0.0.0:7501:定义接受 Tracker 管理时的地址和端口;
    • docroot = /var/mogdata:定义存放文件的 DocRoot 目录;

创建数据文件目录,并授权

1
2
mkdir /var/mogdata
chown -R mogilefs:mogilefs /var/mogdata

启动服务

我这里启动依然遇到了问题,还是改用 restart 而不是 start 解决了。

1
systemctl restart mogstored

到此程序已经安装成功了,接下来要使用管理工具来配置集群。

四、MogilFS 集群管理工具

MogileFS 提供了一个集群管理工具 modadm,使用 modadm [options] --help 可以查看详细帮助。

  • mogadm check:检查集群工作是否正常;可使用 --trackers=192.168.50.11:7001 指定连接哪个 Tracker 节点,如果不指默认连接本地的 127.0.0.1:7001
  • mogadm stats:显示集群状态信息;
  • mogadm host ...:关于 Storage Nodes 的相关命令;
  • mogadm device ...:关于 device 的相关命令;
  • mogadm domain ...:关于 domain 的相关命令;
  • mogadm class ...:关于 class 的相关命令;
  • mogadm slave ...:可以创建主从复制,关于 slave 的相关命令;
  • mogadm fsck ...:关于数据监测修复的相关命令;
  • mogadm rebalance ...:集群运行一段时间后可以重新平衡数据的相关命令;
  • mogadm settings ...:关于运行参数的相关命令;

配置集群

1. 添加 Storage 节点

使用 mogadm 向集群内添加三台 Storage 节点

语法:mogadm host add <hostname> [opts]

1
2
3
mogadm host add node1 --ip=192.168.50.11 --port=7500 --status=alive
mogadm host add node2 --ip=192.168.50.12 --port=7500 --status=alive
mogadm host add node3 --ip=192.168.50.13 --port=7500 --status=alive

2. 创建并添加 Device

语法:mogadm device add <hostname> <devid> [opts]

注意:下面这步要先手动在 Storage 节点中的 RocRoot 目录下创建 Device 目录,目录名必须为固定格式 dev$id,接下来添加 Device 时,devid$id 必须一致。

在每个 Storage 上创建 Device 目录;

1
2
3
ssh node1 'mkdir /var/mogdata/dev1 && chown -R mogilefs:mogilefs /var/mogdata/dev1' 
ssh node2 'mkdir /var/mogdata/dev2 && chown -R mogilefs:mogilefs /var/mogdata/dev2'
ssh node3 'mkdir /var/mogdata/dev3 && chown -R mogilefs:mogilefs /var/mogdata/dev3'

使用 mogadm 向集群内添加 Device,devid 和上边的 $id 必须一致。

1
2
3
mogadm device add node1 1
mogadm device add node2 2
mogadm device add node3 3

可以查看到刚才的配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
-> # mogadm check
Checking trackers...
127.0.0.1:7001 ... OK

Checking hosts...
[ 1] node1 ... OK
[ 2] node2 ... OK
[ 3] node3 ... OK

Checking devices...
host device size(G) used(G) free(G) use% ob state I/O%
---- ------------ ---------- ---------- ---------- ------ ---------- -----
[ 1] dev1 46.969 1.456 45.513 3.10% writeable N/A
[ 2] dev2 46.969 1.592 45.377 3.39% writeable N/A
[ 3] dev3 46.969 1.647 45.322 3.51% writeable N/A
---- ------------ ---------- ---------- ---------- ------
total: 140.908 4.696 136.212 3.33%

3. 添加 Domain

系统有一个默认 Domain,在写入文件时会显示,也可以手动添加一个新的。
这里自定义两个新的 Domain:

1
2
mogadm domain add images
mogadm domain add files

查看刚才创建的 Domain。可以看到 mindevcount 代表当前副本数量,class 使用了默认的 default,也可以自己添加 class。

1
2
3
4
5
6
-> # mogadm domain list      
domain class mindevcount replpolicy hashtype
-------------------- -------------------- ------------- ------------ -------
files default 2 MultipleHosts() NONE

images default 2 MultipleHosts() NONE

4. 添加 Class

使用 mogadm class add <domain> <class> --mindevcount=i 添加 Class,并可以 指定保存几个副本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
-> # mogadm class add files css --mindevcount=3
-> # mogadm class add files jsp --mindevcount=3
-> # mogadm class add images jpg
-> # mogadm class add images gif

-> # mogadm class list
domain class mindevcount replpolicy hashtype
-------------------- -------------------- ------------- ------------ -------
files css 3 MultipleHosts() NONE
files default 2 MultipleHosts() NONE
files jsp 3 MultipleHosts() NONE

images default 2 MultipleHosts() NONE
images gif 2 MultipleHosts() NONE
images jpg 2 MultipleHosts() NONE

配置到此就完成了,下面介绍一些工具,并使用工具管理文件。

五、文件管理工具

mogstats

mogstats:可以查看集群状态,因为是直接从数据库中获取信息的,所以需要指定数据库的认证信息;

1
mogstats --db_dsn="DBI:mysql:mogilefs:host=192.168.50.13" --db_user="mogilefs" --db_pass="mogilefs" --verbose --stats="all"

mogupload

使用 mogupload 可以把文件上传到集群;--key= 为访问此文件的 URL 路径。

语法:mogupload --trackers=host --domain=foo --key='hello.jpg' --file='./hello.jpg'

1
mogupload --trackers=192.168.50.11 --domain files --key='fstab.html' --file='/etc/fstab'

mogfileinfo

使用 mogfileinfo 查看我们刚刚上传的文件。

语法:mogfileinfo --trackers=host --domain=foo --key='hello.jpg'

1
2
3
4
5
6
7
8
9
-> # mogfileinfo --trackers=node1 --domain=files --key='fstab.html'
- file: /fstab.html
class: default
devcount: 1
domain: files
fid: 14
key: fstab.html
length: 465
- http://192.168.50.12:7500/dev2/0/000/000/0000000014.fid

使用文件的 URL http://192.168.50.12:7500/dev2/0/000/000/0000000014.fid 可直接在浏览器内打开文件。

六、简单介绍 FastDFS

与 MofileFS 的区别

  • 支持的文件操作:upload, download, append, delete;比 MogileFS 多了修改;
  • 元数据保存在内存中。

FastDFS 的组件

  • Tracker:调度器,负责维持集群的信息,例如各 group 及其内部的 storage node,这些信息也是 storage node 报告所生成;每个 storage node 会周期性向 tracker 发心跳信息;
  • storage server:以 group 为单位进行组织,任何一个 storage server 都应该属于某个 group,一个 group 应该包含多个 storage server;在同一个 group 内部,各 storage server 的数据互相冗余;

文件名的构成

  • group/M00/00/00/FILE_ID

上传文件的步骤

  1. 由 client 发起上传连接请求;
  2. 由 tracker 查找可用的 storage server;
  3. 找到可用的 storage server 后,将其(ip:port)返回给 client;
  4. 上传文件(文件的属性信息和文件内容);
  5. 生成文件的 fid,将 client 提交的内容写入选定位置;
  6. 返回 fid 给客户端;
  7. 同步存储文件信息至同组中的其它节点;

tracker 挑选组的方法有

  • rr;
  • 指定组;
  • 基于可用空间进行均衡,可用空间大者胜出;

在组中挑选 storage server 的方法有

  • rr;
  • 以 ip 为次序,找第一个;
  • 以优先级为序,找第一个;

选择磁盘(存储路径)的方法有

  • 多个目录进行 rr;
  • 剩余可用空间大者优先;

FID 的生成方式
由源头 storage server ip、创建时的时间戳、大小、文件的校验码和一个随机数进行 hash 计算后生成;最后基于 base64 进行文本编码,转换为可打印字符;

文件同步的方式
每个 storage server 在文件存储完成后,会将其信息存于 binlog, binlog 不包含数据,仅包含文件名等元数据信息;binlog 可用于同步;当主节点存储完毕就报告给客户端已完成,然后主节点会去和其他节点同步,但如果同步未完成,主节点就宕机了,那么数据就会丢失,这是设计缺陷。

下载文件的步骤

客户端上传文件完成后,会收到 storage server 返回的 FID,而后再次用到时,client 会可根据此文件发出请求;

  1. client 向 tracker 发请求;
  2. tracker 根据文件名定位到 group,并返回此 group 内的某一个 storage server 的信息(ip:port)给 client;
  3. client 向得到的 ip:port 发请求;
  4. storage server 查找文件,并返回其内容给 client;

参考文档:
http://www.tuicool.com/articles/YniEnyf
http://joelhy.github.io/2015/01/27/FastDFS-v5-06-deploy/