MogileFS部署文档
简介
MogileFS 是一个开源的分布式文件系统,用于组建分布式文件集群,由 LiveJournal 旗下 DangaInteractive 公司开发,Danga 团队开发了包括 Memcached、MogileFS、Perlbal 等不错的开源项目(注:Perlbal 是一个强大的 Perl 写的反向代理服务器)。 目前使用 MogileFS 的公司非常多,比如国外的一些公司,日本前几名的公司基本都在使用这个,国内所知道的使用 MogileFS 的公司有图片托管网站 yupoo 又拍、digg、 土豆、 豆瓣、1 号店、大众点评、搜狗、安居客等等网站。基本很多网站容量,图片都超过 30T 以上。
特性
- 应用层提供服务,不需要使用核心组件
- 无单点:三大组件(tracker、mogstore,database)皆可实现高可用
- 自动文件复制:复制的最小单位不是文件,而是 class,文件可以被自动复制到多个有足够存储空间的存储节点上
- 传输中立:无特殊协议,可以通过 NFS 或 HTTP 实现通信
- 简单的命名空间:文件通过一个给定的 key 来确定,是全局的命名空间,没有目录基于域实现文件隔离
- 不共享任何数据:无需通过昂贵的 SAN 来共享磁盘,每个存储节点只需维护自己所属的存储设备(device)
原理
组成部分
Trackers(跟踪器)
mogilefsd 即 trackers 程序,是整套系统的核心,trackers 负责调度工作,职责:Replication ,Deletion,Query,Reaper,Monitor 等等。mogadm,mogtool 的所有操作都要跟 trackers 打交 道,Client 的一些操作也需要定义好 trackers,因此最好同时运行多个 trackers 来做负载均衡。trackers 也可以只运行在一台机器 上,也可以跟其他程序运行在一起,只要你配置好他的配置文件即可,默认在/etc/mogilefs/mogilefsd.conf。
Storage(存储节点)
mogstored 程序的启动将使本机成为一个存储节点。启动时默认去读/etc/mogilefs/mogstored.conf ,具体配置可以参考配置部分。mogstored 启动后,便可以通过 mogadm 增加这台机器到 cluster 中。一台机器可以只运行一个 mogstored 作为存储节点即可,也可以同时运行其他程序。
Database(数据库)
数据库保存了 Mogilefs 的所有元数据。这部分非常重要,类似邮件系统的认证中心,如果这部分挂了,那么整个 Mogilefs 将处于不可用状态。这应该设置一个高可用性(HA)的环境以防止单点失败。
术语解释
设备(device) 一个存储节点,可以有多个 device,就是用来存放文件的目录,每个设备都有一个设备 ID,需要在 mogstored 配置文件中 docroot 配置,设备不能删除,只能将设备的状态置为 dead,置为 dead 之后数据就无法恢复了,并且设备 ID 也无法使用。(建议每个节点只有一个 device,文件存储多份时,有多余数据备份在当前节点其他设备,等于没有备份,若只备份2份,节点发生故障,数据就会丢失)
**域(domain) ** 一个域中的键值是惟一的,一个 MogileFS 可以有多个域,域可以用来存储不同应用类型的数据的容器。
类(class) 复制文件的最小单位 (最大为64M,如果一个单文件超出此大小将拆分为多个 class 存储)。在一个域中可以有多个类,主要是用来控制复制单元的,类是用来做属性管理的,类是比域 domain 低一个级别,可以定义一个文件存储在不同 device 中的份数。一个文件必须通过 domain、class 和 key 才能定位到。
部署过程
安装环境说明
系统环境:CentOS release 6.9 (Final)
注意:以下所有步骤均在 CentOS Release 6.9下执行通过。服务使用源码编译安装,理论上具有通用性。
角色划分:
| 角色 | hostname | IP | 安装软件 |
|---|---|---|---|
| 存储节点 storage01 | Rybh101 | 172.16.1.101 | MogileFS |
| 存储节点 storage02 | Rybh102 | 172.16.1.102 | MogileFS |
| Tracker,Database | Rybh103 | 172.16.1.103 | MogileFS,MariaDB |
安装过程
1. 安装 MogileFS 服务(所有主机)
- 安装环境依赖
RedHat/CentOS
yum install -y epel-release
yum -y install make gcc unzip perl-DBD-MySQL perl perl-CPAN perl- YAML perl-Time-HiRes perl-ExtUtils-MakeMaker perl-Net-Netmask perl-IO-AIO
- MogileFS 是基于 Perl 语言构建的项目,因此需要从 CPAN 上面下载 MogileFS 的模块,因此需要保证被部署的机器能够直接或者通过代理连接至互联网,如果无法联网,则需要梳理模块的依赖关系,通过其他途径下载所有所需要的 perl 的模块,并且手工编译安装。
首先,在两台机器上面安装 cpanm 工具,用于安装模块:
curl -L https://cpanmin.us/ -o /usr/bin/cpanm
chmod +x /usr/bin/cpanm
设置环境变量:
export LC_ALL=C
alias cpanm='cpanm --sudo --mirror http://mirrors.163.com/cpan --mirror-only'
cpanm 安装完毕之后,在两台机器上面安装 MogileFS 所需要的模块
cpanm App::cpanminus
cpanm IO::AIO
cpanm IO::WrapTie
cpanm Danga::Socket
cpanm DBD::mysql
cpanm MogileFS::Server
cpanm MogileFS::Client
cpanm MogileFS::Utils
安装完成后,生成的相关命令如下图所示:

2. 配置 MogileFS 服务(所有主机)
首先在三台机器上面创建/etc/mogilefs 这个目录,用于存放配置文件。其次在两台机器上面创建 mogilefs 组和 mogilefs 用户,用于运行 mogileFS 相关的进程(笔者将上述用户和组创建为系统用户和系统组)。之后再在两台机器上面创建/alidata 目录,用于模拟 storage 的设备目录的父目录,并赋予 mogilefs 用户和 mogilefs 用户组权限。
mkdir /etc/mogilefs
groupadd -r mogilefs
useradd -r -g mogilefs -d /home/mogilefs -s /bin/bash -m mogilefs
mkdir /alidata/
chown mogilefs.mogilefs /alidata
由于利用 CPAN 安装的 MogileFS 并未涉及到配置文件,因此这里使用了 GitHub 上面提供的 mogilefsd.conf 文件和 mogstored.conf 文件作为 MogileFS 系统的配置文件。mogilefsd.conf 文件作为 tracker 的配置,而 mogstored.conf 为 storage 进行配置。将上述两个文件下载,并拷贝到两台机器的/etc/mogilefs 目录下面:
wget https://github.com/hachi/MogileFS-Server/archive/master.zip -O /opt/MogileFS-Server-master.zip
cd /opt
unzip MogileFS-Server-master.zip
cp MogileFS-Server-master/conf/* /etc/mogilefs
- 数据库节点配置(172.16.1.103)
配置 mariadb 的 yum 安装源
cat >>/etc/yum.repos.d/MariaDB.repo<<'EOF'
[mariadb]
name = MariaDB
baseurl = http://yum.mariadb.org/10.0/centos7-amd64
gpkgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1
EOF
yum 安装 mariadb,启动数据库服务
yum install -y MariaDB-server MariaDB-client
创建 mogilefs 的连接用户,这里的账号和密码在 tracker 服务里需要用到
MariaDB [(none)]> USE mysql;
Database changed
MariaDB [mysql]> GRANT ALL ON mogilefs.* TO 'moguser'@'172.16.%.%' IDENTIFIED BY 'mogpass';
Query OK, 0 rows affected (0.00 sec)
MariaDB [mysql]> GRANT ALL ON *.* TO 'root'@'172.16.%.%' IDENTIFIED BY 'rootpass';
Query OK, 0 rows affected (0.00 sec)
MariaDB [mysql]> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)
- Tracker 节点配置(172.16.1.103
初始化 mogilefs 数据库。
mogdbsetup --dbhost=172.16.1.103 --dbrootuser=root \
--dbrootpass=rootpass --dbuser=moguser --dbpass=mogpass --dbname=mogilefs --yes
数据库初始化完毕之后,登录数据库查看是否生成数据表。
MariaDB [(none)]> use mogilefs;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
MariaDB [mogilefs]>> show tables;
+----------------------+
| Tables_in_mogilefs |
+----------------------+
| checksum |
| class |
| device |
| domain |
| file |
| file_on |
| file_on_corrupt |
| file_to_delete |
| file_to_delete2 |
| file_to_delete_later |
| file_to_queue |
| file_to_replicate |
| fsck_log |
| host |
| server_settings |
| tempfile |
| unreachable_fids |
+----------------------+
17 rows in set (0.00 sec)
修改 trakcer 的主配置文件:
# cat /etc/mogilefs/mogilefsd.conf
daemonize = 1 #是否以守护进程运行
pidfile = /home/mogilefs/mogilefsd.pid
db_dsn = DBI:mysql:mogilefs:host=172.16.1.103 #定义数据库名及主机
db_user = moguser #数据库用户名
db_pass = mogpass #数据库用户密码
listen = 172.16.1.103:7001 #监听地址
conf_port = 7001
query_jobs = 10
delete_jobs = 1
replicate_jobs = 5
reaper_jobs = 1
启动 trakcer 服务
su - mogilefs -c "/usr/local/bin/mogilefsd -c /etc/mogilefs/mogilefsd.conf --daemon"
- Storage 节点配置(172.16.1.101和172.16.1.102)
修改 storage 节点的主配置文件,定义根目录(所有设备目录的父目录)为/alidata。
# cat /etc/mogilefs/mogstored.conf
maxconns = 10000
httplisten = 0.0.0.0:7500
mgmtlisten = 0.0.0.0:7501
docroot = /alidata/
启动 storage 服务
su - mogilefs -c "/usr/local/bin/mogstored -c /etc/mogilefs/mogstored.conf --daemon"
亦可以将启动命令封装成启动脚本:
Mogilefsd 启动脚本:
#!/bin/bash
#
# chkconfig: - 85 15
# description: MogileFS tracker
# processname: mogilefsd
# config: /etc/mogilefs/mogilefsd.conf
# pidfile: /home/mogilefs/mogilefsd.pid
. /etc/rc.d/init.d/functions
lockfile=${LOCKFILE-/var/lock/subsys/mogilefsd}
RETVAL=0
pidfile='/home/mogilefs/mogilefsd.pid'
start() {
ulimit -n 65535
echo -n $"Starting mogilefsd"
su - mogilefs -c "/usr/local/bin/mogilefsd -c /etc/mogilefs/mogilefsd.conf --daemon" &> /dev/null
RETVAL=$?
[ $RETVAL = 0 ] && success && touch ${lockfile} && pidof /usr/local/bin/mogilefsd > $pidfile || failure
echo
return $RETVAL
}
stop() {
echo -n $"Stopping mogilefsd"
netstat -nlp|grep "mogilefsd"|grep -v grep|awk '{print $7}' |awk -F"/" '{print $1}'|xargs kill -9
RETVAL=$?
[ $RETVAL = 0 ] && success && rm -f ${lockfile} || failure
echo
}
reload() {
echo -n $"Reloading mogilefsd: "
killall mogilefsd -HUP
RETVAL=$?
[ $RETVAL = 0 ] && success || failure
echo
}
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status mogilefsd
RETVAL=$?
;;
restart)
stop
sleep 1
start
;;
reload)
reload
;;
*)
echo $"Usage: mogilefsd {start|stop|restart|reload|status}"
exit 1
esac
exit $RETVAL
Mogstored 启动脚本:
#!/bin/bash
#
# chkconfig: - 86 14
# description: MogileFS storage
# processname: mogstored
# config: /etc/mogilefs/mogstored.conf
# pidfile: /home/mogilefs/mogstored.pid
. /etc/rc.d/init.d/functions
lockfile=${LOCKFILE-/var/lock/subsys/mogstored}
RETVAL=0
configfile="/etc/mogilefs/mogstored.conf"
pidfile="/home/mogilefs/mogstored.pid"
prog=$(which mogstored)
start() {
ulimit -n 65535
echo -n $"Starting mogstored"
su - mogilefs -c "/usr/local/bin/mogstored -c $configfile --daemon" &> /dev/null
RETVAL=$?
[ $RETVAL = 0 ] && success && touch ${lockfile} && pidof /usr/local/bin/mogstored > $pidfile || failure
echo
return $RETVAL
}
stop() {
echo -n $"Stopping mogstored"
netstat -nlp|grep "mogstored"|grep -v grep|awk '{print $7}'|awk -F"/" '{print $1}'|xargs kill -9
RETVAL=$?
[ $RETVAL = 0 ] && success && rm -f ${lockfile} ${pidfile} || failure
echo
}
reload() {
echo -n $"Reloading mogstored: "
killall mogstored -HUP
RETVAL=$?
[ $RETVAL = 0 ] && success || failure
echo
}
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status mogstored
RETVAL=$?
;;
restart)
stop
sleep 1
start
;;
reload)
reload
;;
*)
echo $"Usage: mogstored {start|stop|restart|reload|status}"
exit 1
esac
exit $RETVAL
服务启动后,可用 netstat 命令检查相关端口是否正常监听,7001是 mogilefsd 的端口,7500是 mogstored 的端口:
netstat -lntup|egrep "7500|7001"
3. 管理 MogileFS 集群
- 使用 mogadm 命令检测集群状态,指定 tracker 节点为172.16.1.103
$ mogadm --trackers=172.16.1.103:7001 check
Checking trackers...
172.16.1.103:7001 ... OK
Checking hosts...
No devices found on tracker(s).
- 添加 Storage 节点
添加 hosts,即 storage 节点。将添加的 storage 节点分别命名为 store1和 store2。添加完毕之后分别利用 check 和 host list 子命令来查看状态,正常情况下可以看到 storage 节点已经添加完毕,并且状态为 alive。
$ mogadm --trackers=172.16.1.103:7001 host add store1 --ip=172.16.1.101 --status=alive
$ mogadm --trackers=172.16.1.103:7001 host list
store1 [1]: alive
IP: 172.16.1.101:7500
$ mogadm --trackers=172.16.1.103:7001 host add store2 --ip=172.16.1.102 --status=alive
$ mogadm --trackers=172.16.1.103:7001 host list
store1 [1]: alive
IP: 172.16.1.101:7500
store2 [2]: alive
IP: 172.16.1.102:7500
$ mogadm --trackers=172.16.1.103:7001 check
Checking trackers...
172.16.1.103:7001 ... OK
Checking hosts...
[ 1] store1 ... OK
[ 2] store2 ... OK
Checking devices...
host device size(G) used(G) free(G) use% ob state I/O%
---- ------------ ---------- ---------- ---------- ------ ---------- -----
---- ------------ ---------- ---------- ---------- ------
total: 0.000 0.000 0.000 0.00%
- 给 Storage 节点添加设备 device
目前集群的 docroot 定义为/alidata,首先在节点上创建对应目录,并都赋予 mogilefs 用户权限和 mogilefs 组权限:
1)节点 storage01:/alidata/dev1
2)节点 storage02:/alidata/dev2
节点 storage01:
$ mkdir -pv /alidata/dev1
$ chown mogilefs.mogilefs /alidata/dev1
节点 storage02:
$ mkdir -pv /alidata/dev2
$ chown mogilefs.mogilefs /alidata/dev2
通过 mogadm 的 device add 子命令,在节点 storage01上面添加 dev1,在节点 storage02上面添加 dev2。添加完毕之后,用 device list 子命令进行查看。正常情况下,可以看到 store1和 store2下面分别多出了 dev1和 dev2设备,以及 dev1和 dev2设备的可用情况。 注:在添加的时候,dev1的节点编号为1,dev2的节点编号为2,以此类推,devn 的节点编号为 n…
$ mogadm --trackers=172.16.1.103:7001 device add store1 1
$ mogadm --trackers=172.16.1.103:7001 device add store2 2
$ mogadm --trackers=172.16.1.103:7001 device list
store1 [1]: alive
used(G) free(G) total(G) weight(%)
dev1: alive 1.072 36.378 37.450 100
store2 [2]: alive
used(G) free(G) total(G) weight(%)
dev2: alive 1.010 36.440 37.450 100
执行完成后,在设备目录下生成了一系列文件,结构如下:

- 创建 Domain
MogileFS 使用 Domain 来存放文件。每一个 Domain 的实例,管理了一组 key-value 的”元数据-数据”对象,可以创建一个 Domain 的实例,名称为 text,用于专门存储文本文件;可以创建另一个 Domain 的实例,名称为 images,用于专门存储图片文件。每一 Domain 实例下面的 key 代表了一个被存储的文件的元数据索引,对应着被存储的文件本身,即 value。
$ mogadm --trackers=172.16.1.103:7001 domain add images
$ mogadm --trackers=172.16.1.103:7001 domain add text
$ mogadm --trackers=172.16.1.103:7001 domain list
domain class mindevcount replpolicy hashtype
-------------------- -------------------- ------------- ------------ -------
images default 2 MultipleHosts() NONE
text default 2 MultipleHosts() NONE
在每一个区域中建立 class,即文件复制的最小单位:
$ mogadm --trackers=172.16.1.103:7001 class add images class1 --mindevcount=2
$ mogadm --trackers=172.16.1.103:7001 class add images class2 --mindevcount=2
$ mogadm --trackers=172.16.1.103:7001 class add text class1 --mindevcount=2
$ mogadm --trackers=172.16.1.103:7001 class add text class2 --mindevcount=2
$ mogadm --trackers=172.16.1.103:7001 class list
domain class mindevcount replpolicy hashtype
-------------------- -------------------- ------------- ------------ -------
images class1 2 MultipleHosts() NONE
images class2 2 MultipleHosts() NONE
images default 2 MultipleHosts() NONE
text class1 2 MultipleHosts() NONE
text class2 2 MultipleHosts() NONE
text default 2 MultipleHosts() NONE
- 使用 mogupload 上传文件测试,并使用 mogfileinfo 命令进行查看文件信息
## 上传图片
$ mogupload --trackers=172.16.1.103:7001 --domain=images --key='/images/1k.jpg' \
--file='/root/wings.jpg'
$ moglistkeys --trackers=172.16.1.103:7001 --domain=images
/images/1k.jpg
$ mogfileinfo --trackers=172.16.1.103:7001 --domain=images --key=/images/1k.jpg
- file: /images/1k.jpg
class: default
devcount: 1
domain: images
fid: 2
key: /images/1k.jpg
length: 96225
- http://172.16.1.102:7500/dev2/0/000/000/0000000002.fid
## 上传文本
$ mogupload --trackers=172.16.1.103:7001 --domain=text --key='/text/hosts.html' --file='/etc/hosts'
$ moglistkeys --trackers=172.16.1.103:7001 --domain=text
/text/hosts.html
$ mogfileinfo --trackers=172.16.1.103:7001 --domain=text --key=/text/hosts.html
- file: /text/hosts.html
class: default
devcount: 1
domain: text
fid: 4
key: /text/hosts.html
length: 158
- http://172.16.1.101:7500/dev1/0/000/000/0000000004.fid
在 storage 节点上相关路径下可以看到文件信息:
## 节点 storage01
$ /alidata/dev1/0/000/000/0000000004.fid: ASCII text
## 节点 storage02:
$ file /alidata/dev2/0/000/000/0000000002.fid
/alidata/dev2/0/000/000/0000000002.fid: JPEG image data, JFIF standard 1.01
- 通过浏览器访问资源上面的 HTTP 地址:


使用 Nginx 代理 MogileFS 集群
默认情况下是直接以 fid 形式的标识符去访问资源,这样很不方便。使用 Nginx 的第三方模块 mogilefs-module,可以将 Nginx 作为 tracker 和 storage 的反向代理,实现通过访问定义的 key 值获取到指定的资源。由于要静态编译第三方模块,所以这里的 nginx 需要使用源码编译安装。
cd /tmp
wget http://nginx.org/download/nginx-1.9.1.tar.gz
wget http://www.grid.net.ru/nginx/download/nginx_mogilefs_module-1.0.4.tar.gz
①编译前确保安装依赖
yum install pcre-devel openssl-devel -y
yum install make zlib zlib-devel gcc-c++ libtool
groupadd www && useradd www -g www -M -s /sbin/nologin
cd /tmp
wget http://nginx.org/download/nginx-1.8.1.tar.gz
git clone https://github.com/vkholodkov/nginx-mogilefs-module.git
tar zxf nginx-1.8.1.tar.gz
cd nginx-1.8.1
②编译安装 nginx(这里提供一份自己常用的编译参数)
./configure --prefix=/usr/local/nginx \
--sbin-path=${prefix}/sbin/nginx \
--conf-path=${prefix}/conf/nginx.conf \
--error-log-path=${prefix}/logs/error.log \
--http-log-path=${prefix}/logs/access.log \
--pid-path=${prefix}/logs/nginx.pid \
--lock-path=${prefix}/logs/nginx.lock \
--http-client-body-temp-path=${prefix}/cache/client_temp \
--http-proxy-temp-path=${prefix}/cache/proxy_temp \
--http-fastcgi-temp-path=${prefix}/cache/fastcgi_temp \
--http-uwsgi-temp-path=${prefix}/cache/uwsgi_temp \
--http-scgi-temp-path=${prefix}/cache/scgi_temp \
--user=www \
--group=www \
--with-pcre \
--with-http_ssl_module \
--with-http_spdy_module \
--with-http_stub_status_module \
--with-http_realip_module \
--with-http_addition_module \
--with-http_sub_module \
--with-http_dav_module \
--with-http_flv_module \
--with-http_mp4_module \
--with-http_gunzip_module \
--with-http_gzip_static_module \
--with-http_random_index_module \
--with-http_secure_link_module \
--with-http_degradation_module \
--with-http_auth_request_module \
--with-file-aio \
--add-module=../nginx-mogilefs-module
这里有一个 bug,需要手动修改编译生成的 Makefile 文件:
$ vim objs/Makefile
CFLAGS = -pipe -O -W -Wall -Wpointer-arith -Wno-unused-parameter -Werror -g
修改为
CFLAGS = -pipe -O -W -Wall -Wpointer-arith -Wno-unused-parameter -g
修改完成后再行编译安装:
make -j8 && make install
③nginx 配置,配置文件如下:
具体可参考:
http://www.grid.net.ru/nginx/mogilefs.en.html
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
upstream mogfs_cluster {
server 172.16.1.103:7001;
}
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
location ~* ^(/images/.*)$ {
mogilefs_tracker mogfs_cluster;
mogilefs_domain images;
mogilefs_noverify on;
mogilefs_pass $1 {
proxy_pass $mogilefs_path;
proxy_hide_header Content-Type;
proxy_buffering off;
}
}
location ~* ^(/text/.*)$ {
mogilefs_tracker mogfs_cluster;
mogilefs_domain text;
mogilefs_noverify on;
mogilefs_pass $1 {
proxy_pass $mogilefs_path;
proxy_hide_header Content-Type;
proxy_buffering off;
}
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
Nginx 配置完成并启动后,即可通过自定义的 key 值访问资源了:


251

被折叠的 条评论
为什么被折叠?



