分布式文件系统MogileFS简介
非常感谢 http://maoqiu.blog.51cto.com/8570467/1409382/
大纲:
当下我们处在一个互联网飞速发展的信息社会,在海量并发连接的驱动下每天所产生的数据量必然以几何方式增长,随着信息连接方式日益多样化,数据存储的结构也随着发生了变化。在这样的压力下使得人们不得不重新审视大量数据的存储所带来的挑战,例如:数据采集、数据存储、数据搜索、数据共享、数据传输、数据分析、数据可视化等一系列问题。
传统存储在面对海量数据存储表现出的力不从心已经是不争的事实,例如:纵向扩展受阵列空间限制、横向扩展受交换设备限制、节点受文件系统限制。
然而分布式存储的出现在一定程度上有效的缓解了这一问题,之所以称之为缓解是因为分布式存储在面对海量数据存储时也并非十全十美毫无压力,依然存在的难点与挑战例如:节点间通信、数据存储、数据空间平衡、容错、文件系统支持等一系列问题仍处在不断摸索和完善中。
在理论计算机科学中,CAP定理(CAP theorem),又被称作布鲁尔定理(Brewer's theorem),它指出对于一个分布式计算系统来说,不可能同时满足以下三点:
* 一致性(Consistency)---所有节点在同一时间具有相同的数据
* 可用性(Availability)---保证每个请求不管成功或者失败都有响应
* 分隔容忍(Partition tolerance)---系统中任意信息的丢失或失败不会影响系统的继续运作
对于大型站点,可用性(Availability)与分隔容错性(Partition Tolerance)的优先级会高于一致性(Consistency),这里并不是指完全舍弃一致性,而是通过其他手段实现数据的弱一致性,例如:用户微博的浏览数和评论可以容忍相对长时间的不一致,几乎不会影响用户体验,而股票价格的数据则异常敏感,即便是10秒钟的数据不一致也无法容忍下面列出了"各种一致性".
* 一致性(Consistency)---所有节点在同一时间具有相同的数据
* 可用性(Availability)---保证每个请求不管成功或者失败都有响应
* 分隔容忍(Partition tolerance)---系统中任意信息的丢失或失败不会影响系统的继续运作
对于大型站点,可用性(Availability)与分隔容错性(Partition Tolerance)的优先级会高于一致性(Consistency),这里并不是指完全舍弃一致性,而是通过其他手段实现数据的弱一致性,例如:用户微博的浏览数和评论可以容忍相对长时间的不一致,几乎不会影响用户体验,而股票价格的数据则异常敏感,即便是10秒钟的数据不一致也无法容忍下面列出了"各种一致性".
Google Filesystem | GFS+MapReduce擅长处理单个大文件 |
Hadoop Distributed Filesystem | GFS的山寨版+MapReduce,擅长处理单个大文件 |
ClusterFS | 擅长处理单个大文件 |
Taobao Filesystem | 擅长处理海量小文件 |
MogileFS | 擅长处理海量小文件 |
Ceph | PB级别的分布式文件系统 |
MooseFS | 通用简便,适用于研发能力不强的公司 |
Lustre | 一种平行分布式文件系统 |
三、Mogilefs基本原理
MogileFS是一个开源的分布式文件系统,用于组建分布式文件集群,由LiveJournal旗下DangaInteractive公司开发,Danga团队开发了包括 Memcached、MogileFS、Perlbal等不错的开源项目:(注:Perlbal是一个强大的Perl写的反向代理服务器)。MogileFS是一个开源的分布式文件系统。主要特性包括:应用层的组件、无单点故障、自动文件复制、具有比RAID更好的可靠性、无需RAID支持等……核心角色如下:
tracker节点:MgileFS的核心,借助数据库保存各节点文件的元数据信息保存每个域中所有键的存储位置分布,方便检索定位数据位置的同时监控各节点,告诉客户端存储区位置并指挥storage节点复制数据副本,服务进程名为mogilefsd(7001);除此之外它还负责数据的删除、复制、监控、查询等、可以作为负载均衡.
database节点:为tracker节点提供数据存取服务。
storage节点:数据存储的位置、将指定域中的键转换为其特有的文件名存储在指定的设备文件中,转换后的文件名为值,storage节点自动维护键值的对应关系,storage节点由于使用http进行数据传输,因此依赖于perlbal,storage节点前端可以使用nginx进行反向代理,但需要安装nginx-mogilefs-module-master模块进行名称转换,进程名mogstored(7501),perbal(7500)。
MogileFS是一个开源的分布式文件系统,用于组建分布式文件集群,由LiveJournal旗下DangaInteractive公司开发,Danga团队开发了包括 Memcached、MogileFS、Perlbal等不错的开源项目:(注:Perlbal是一个强大的Perl写的反向代理服务器)。MogileFS是一个开源的分布式文件系统。主要特性包括:应用层的组件、无单点故障、自动文件复制、具有比RAID更好的可靠性、无需RAID支持等……核心角色如下:
tracker节点:MgileFS的核心,借助数据库保存各节点文件的元数据信息保存每个域中所有键的存储位置分布,方便检索定位数据位置的同时监控各节点,告诉客户端存储区位置并指挥storage节点复制数据副本,服务进程名为mogilefsd(7001);除此之外它还负责数据的删除、复制、监控、查询等、可以作为负载均衡.
database节点:为tracker节点提供数据存取服务。
storage节点:数据存储的位置、将指定域中的键转换为其特有的文件名存储在指定的设备文件中,转换后的文件名为值,storage节点自动维护键值的对应关系,storage节点由于使用http进行数据传输,因此依赖于perlbal,storage节点前端可以使用nginx进行反向代理,但需要安装nginx-mogilefs-module-master模块进行名称转换,进程名mogstored(7501),perbal(7500)。
Client libray、tracker、Database、mogstore的关系图 |
|
MofileFS工作流程图 |
|
1.拓扑图
各角色和服务之间都是基于套接字来进行通信的,就服务本身就没有耦合性,所以可以在服务器设备有限的场景下运行多种服务或角色.
1)应用层发起GET请求到Nginx。
(1).安装、配置mysql
安装过程请参考:http://maoqiu.blog.51cto.com/8570467/1399876中的第"十一"小节.
1
2
3
4
5
6
7
8
9
10
|
MariaDB
[(none)]> use mysql
#删除有安全隐患的账户
MariaDB
[mysql]> DELETE FROM user WHERE host = '::1' ;
MariaDB
[mysql]> DELETE FROM user WHERE user = '' ;
#授权root用户能远程登录
MariaDB
[mysql]> GRANT ALL ON *.* TO 'root' @ '172.16.%.%' IDENTIFIED
BY '123.com'
#授权moguser用户
MariaDB
[mysql]> GRANT ALL ON mogdb.* TO 'moguser' @ '172.16.%.%' IDENTIFIED
BY '123.com' ;
#刷新授权表
MariaDB
[mysql]> FLUSH PRIVILEGES;
|
(2)在后端各节点安装tracker以及storege
<1>下载相应软件包.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
#→下面三个是Tracker和Storage端必装的程序包.
MogileFS-Server-2.46-2.el6.noarch.rpm
MogileFS-Server-mogilefsd-2.46-2.el6.noarch.rpm
MogileFS-Server-mogstored-2.46-2.el6.noarch.rpm
#→这是在维护MogileFS时使用的工具包
MogileFS-Utils-2.19-1.el6.noarch.rpm
#→MogileFS客户端程序
perl-MogileFS-Client-1.14-1.el6.noarch.rpm
#→这个软件包是在跨网络或者跨机房是所使用的包
perl-Net-Netmask-1.9015-8.el6.noarch.rpm
#→这是用perl所编写的web程序,它是在mostored上提供webDAV的方式接受客户web服务请求的.
perl-Perlbal-1.78-1.el6.noarch.rpm
#这是perl程序所依赖的包
perl-IO-AIO.x86_64
#→说明如果在配置安装过程当中遇依赖关系时,解决就行了.
#→然后将几个软件包都拷贝至其它两个节点上.
[[email protected]
~] #
scp *.rpm 172.16.41.2:/root/
[[email protected]
~] #
scp *.rpm 172.16.41.3:/root/
|
<2>安装.
1
2
|
[[email protected]
~] #
yum install *.rpm perl-IO-AIO
#→其他两个节点的安装过程在node1上面的一样.
|
<1>配置tracker
1
2
|
#→安装好tracker后会在/var/run/下面生成该目录,改变目录属主.属组
[[email protected]
~] #
chown -R mogilefs.mogilefs /var/run/mogilefsd
|
<2>初始数据库设置
1
|
[[email protected]
~] #
mogdbsetup --dbrootuser=root --dbname=mogdb --dbhost=172.16.41.5 --dbport=3306 --dbrootpass=123.com --dbuser=moguser --dbpass=123.com --yes
|
1
2
3
4
5
6
|
[[email protected]
~] #
vim /etc/mogilefs/mogilefsd.conf
#→修改下面4项即可其它参数根据工作环境自定
db_dsn
= DBI:mysql:mogdb:host=172.16.41.5
db_user
= moguser
db_pass
= 123.com
listen
= 172.16.41.1:7001
|
1
2
3
4
5
6
7
8
|
[[email protected]
~] #
vim /etc/mogilefs/mogstored.conf
maxconns
= 10000 #→存储系统的最大连接数.
httplisten
= 0.0.0.0:7500 #→这个就是webDAV服务使用的端口,但是这里我们不知使用它.
mgmtlisten
= 0.0.0.0:7501 #→mogilefs的管理端口.
docroot
= /data/mogdata #→该项决定了数据的在storage上存储的实际位置,建议使用的是一个单独挂载使用的磁盘.这里我就不用演示了.
[[email protected]
~] #
mkdir -p /data/mydata/dev1
#→这里一定要改变数据存放目录的属主属组,应为mogilefs服务程序必须是以普通用户来运行的,否则服务启动将失败!
[[email protected]
~] #
chown -R mogilefs.mogilefs /data/mogdata/dev1
|
1
2
3
4
5
|
[[email protected]
~] #
service mogilefsd start
Starting
mogilefsd [ OK ]
[[email protected]
~] #
service mogstored start
Starting
mogstored [ OK ]
[[email protected]
~] #
|
1
|
[[email protected]
~] #
mogadm --trackers=172.16.41.1:7001 host add 172.16.41.1 --ip=172.16.41.1 --status=alive
|
此时,node1.example.com这个节点既是tracker也是storage服务端了.
1
2
3
4
5
6
7
|
[[email protected]
~] #
scp /etc/mogilefs/* 172.16.41.2:/etc/mogilefs/
mogilefsd.conf
100% 1462 1.4KB /s 00:00
mogstored.conf
100% 93 0.1KB /s 00:00
[[email protected]
~] #
scp /etc/mogilefs/* 172.16.41.3:/etc/mogilefs/
mogilefsd.conf
100% 1462 1.4KB /s 00:00
mogstored.conf
100% 93 0.1KB /s 00:00
[[email protected]
~] #
|
1
2
|
#→安装好tracker后会在/var/run/下面生成该目录,改变目录属主.属组
[[email protected]
~] #
chown -R mogilefs.mogilefs /var/run/mogilefsd
|
1
2
3
4
5
6
|
[[email protected]
~] #
vim /etc/mogilefs/mogilefsd.conf
#→修改下面4项即可其它参数根据工作环境自定
db_dsn
= DBI:mysql:mogdb:host=172.16.41.5
db_user
= moguser
db_pass
= 123.com
listen
= 172.16.41.2:7001
|
1
2
3
4
5
6
7
8
|
[[email protected]
~] #
vim /etc/mogilefs/mogstored.conf
maxconns
= 10000
httplisten
= 0.0.0.0:7500
mgmtlisten
= 0.0.0.0:7501
docroot
= /data/mogdata #→该项决定了数据的在storage上存储的实际位置,建议使用的是一个单独挂载使用的磁盘.这里我就不用演示了.
[[email protected]
~] #
mkdir -p /data/mydata/dev2
#→这里一定要改变数据存放目录的属主属组,应为mogilefs服务程序必须是以普通用户来运行的,否则服务启动将失败!
[[email protected]
~] #
chown -R mogilefs.mogilefs /data/mogdata/dev2
|
1
2
3
4
5
|
[[email protected]
~] #
service mogilefsd start
Starting
mogilefsd [ OK ]
[[email protected]
~] #
service mogstored start
Starting
mogstored [ OK ]
[[email protected]
~] #
|
1
|
[[email protected]
~] #
mogadm --trackers=172.16.41.2:7001 host add 172.16.41.2 --ip=172.16.41.2 --status=alive
|
<1>添加device
1
2
3
4
5
6
7
|
#→添加的第一个设备,设备号不能重名
[[email protected]
~] #
mogadm --trackers=172.16.41.1:7001 device add 172.16.41.1 1
#→添加的第二个设备
[[email protected]
~] #
mogadm --trackers=172.16.41.2:7001 device add 172.16.41.2 2
#→添加的第三个设备
[[email protected]
~] #
mogadm --trackers=172.16.41.3:7001 device add 172.16.41.3 3
[[email protected]
~] #
mogadm --trackers=172.16.41.3:7001 device list
|
1
2
3
4
5
|
#→创建的图片存放域
[[email protected]
~] #
mogadm --trackers=172.16.41.1:7001 domain add images
#→创建的html等文件存放域
[[email protected]
~] #
mogadm --trackers=172.16.41.1:7001 domain add files
[[email protected]
~] #
mogadm --trackers=172.16.41.1:7001 domain list
|
1
2
3
4
5
6
7
|
[[email protected]
~] #
mogadm --trackers=172.16.41.1:7001 class add images class0 --mindevcount=2
[[email protected]
~] #
mogadm --trackers=172.16.41.1:7001 class add images class1 --mindevcount=2
[[email protected]
~] #
mogadm --trackers=172.16.41.1:7001 class add images class3 --mindevcount=2
[[email protected]
~] #
mogadm --trackers=172.16.41.1:7001 class add files class0 --mindevcount=2
[[email protected]
~] #
mogadm --trackers=172.16.41.1:7001 class add files class1 --mindevcount=2
[[email protected]
~] #
mogadm --trackers=172.16.41.1:7001 class add files class2 --mindevcount=2
[[email protected]
~] #
mogadm --trackers=172.16.41.1:7001 class list
|
1
2
3
|
[[email protected]
~] #
mogupload --trackers=172.16.41.1:7001 --domain=images --key='tux_1.jpg' --file='/root/my_test_data/1.jpg'
#→--key='tux_1.jgp'
是我要上传后的键是什么
#→
--file 指的是我要上传的文件
|
1.编译安装Nginx.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
#这里需要安装个pcre-devel包
[[email protected]
~] #
yum install -y pcre-devel
#解压获取到的mogilefs模块包
[[email protected]
~] #
unzip nginx-mogilefs-module-master.zip
#解压、编译安装nginx
[[email protected]
~] #
tar -xf nginx-1.4.7.tar.gz -C /usr/src/
[[email protected]
~] #
cd /usr/src/nginx-1.4.7/
[[email protected]
nginx-1.4.7] #
. /configure \
--prefix= /usr \
--sbin-path= /usr/sbin/nginx \
--conf-path= /etc/nginx/nginx .conf
\
--error-log-path= /var/log/nginx/error .log
\
--http-log-path= /var/log/nginx/access .log
\
--pid-path= /var/run/nginx/nginx .pid
\
--lock-path= /var/lock/nginx .lock
\
--user=nginx
\
--group=nginx
\
--with-http_ssl_module
\
--with-http_flv_module
\
--with-http_stub_status_module
\
--with-http_gzip_static_module
\
--http-client-body-temp-path= /var/tmp/nginx/client/ \
--http-proxy-temp-path= /var/tmp/nginx/proxy/ \
--http-fastcgi-temp-path= /var/tmp/nginx/fcgi/ \
--http-uwsgi-temp-path= /var/tmp/nginx/uwsgi \
--http-scgi-temp-path= /var/tmp/nginx/scgi \
--with-pcre
\
--with-debug
\
--add-module= /root/nginx-mogilefs-module-master
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
[[email protected]
~] #
vim /etc/rc.d/init.d/nginx
#!/bin/sh
#
#
nginx - this script starts and stops the nginx daemon
#
#
chkconfig: - 85 15
#
description: Nginx is an HTTP(S) server, HTTP(S) reverse \
#
proxy and IMAP/POP3 proxy server
#
processname: nginx
#
config: /etc/nginx/nginx.conf
#
config: /etc/sysconfig/nginx
#
pidfile: /var/run/nginx.pid
#
Source function library.
. /etc/rc .d /init .d /functions
#
Source networking configuration.
. /etc/sysconfig/network
#
Check that networking is up.
[ "$NETWORKING" = "no" ]
&& exit 0
nginx= "/usr/sbin/nginx"
prog=$( basename $nginx)
NGINX_CONF_FILE= "/etc/nginx/nginx.conf"
[
-f /etc/sysconfig/nginx ]
&& . /etc/sysconfig/nginx
lockfile= /var/lock/subsys/nginx
make_dirs()
{
#
make required directories
user=`nginx
-V 2>&1 | grep "configure
arguments:" | sed 's/[^*]*--user=\([^
]*\).*/\1/g' -`
options=`$nginx
-V 2>&1 | grep 'configure
arguments:' `
for opt in $options; do
if [
` echo $opt
| grep '.*-temp-path' `
]; then
value=` echo $opt
| cut -d "=" -f
2`
if [
! -d "$value" ]; then
#
echo "creating" $value
mkdir -p
$value && chown -R
$user $value
fi
fi
done
}
start()
{
[
-x $nginx ] || exit 5
[
-f $NGINX_CONF_FILE ] || exit 6
make_dirs
echo -n
$ "Starting
$prog: "
daemon
$nginx -c $NGINX_CONF_FILE
retval=$?
echo
[
$retval - eq 0
] && touch $lockfile
return $retval
}
stop()
{
echo -n
$ "Stopping
$prog: "
killproc
$prog -QUIT
retval=$?
echo
[
$retval - eq 0
] && rm -f
$lockfile
return $retval
}
restart()
{
configtest
|| return $?
stop
sleep 1
start
}
reload()
{
configtest
|| return $?
echo -n
$ "Reloading
$prog: "
killproc
$nginx -HUP
RETVAL=$?
echo
}
force_reload()
{
restart
}
configtest()
{
$nginx
-t -c $NGINX_CONF_FILE
}
rh_status()
{
status
$prog
}
rh_status_q()
{
rh_status
> /dev/null 2>&1
}
case "$1" in
start)
rh_status_q
&& exit 0
$1
;;
stop)
rh_status_q
|| exit 0
$1
;;
restart|configtest)
$1
;;
reload)
rh_status_q
|| exit 7
$1
;;
force-reload)
force_reload
;;
status)
rh_status
;;
condrestart|try-restart)
rh_status_q
|| exit 0
;;
*)
echo $ "Usage:
$0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|configtest}"
exit 2
esac
[[email protected]
~] #
chmod +x /etc/rc.d/init.d/
[[email protected]
~] #
chkconfig --add nginx
[[email protected]
~] #
chkconfig nginx on
#启动nginx
[[email protected]
~] #
service nginx start
Starting
nginx: [ OK ]
[[email protected]
~] #
ss -tnl | grep :80
LISTEN
0 128 *:80 *:*
[[email protected]
~] #
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
[[email protected]
~]# vim /etc/nginx/nginx.conf
worker_processes 2 ;
events
{
worker_connections 1024 ;
}
http
{
include mime.types;
default_type
application/octet-stream;
sendfile
on;
keepalive_timeout 65 ;
gzip
on;
server
{
listen 80 ;
server_name
www.magelinux.com;
location
/ {
root
html;
index
index.html index.htm;
}
################About
images###############
location
/images/ {
mogilefs_tracker 172.16 . 41.1 : 7001 ;
mogilefs_domain
images;
mogilefs_pass
{
proxy_pass
$mogilefs_path;
proxy_hide_header
Content-Type;
proxy_buffering
off;
}
}
################About
files###############
location
/files/ {
mogilefs_tracker 172.16 . 41.1 : 7001 ;
mogilefs_domain
images;
mogilefs_pass
{
proxy_pass
$mogilefs_path;
proxy_hide_header
Content-Type;
proxy_buffering
off;
}
}
error_page 404 / 404 .html;
error_page 500 502 503 504 /50x.html;
location
= /50x.html {
root
html;
}
}
}
|
保存退出、重新加载nginx、再次访问测试:
重新上传测试文件:
朋友们大概注意到了我在nginx的配置文件中,只是配置了将客户端请求代理到后端的一台tracker上面,如果要将多个tracker基于负载均衡的方式来提供服务,于是我们就需要定义upstream啦;请看以下配置:
如果我将某两个(不止一个),tracker+storage模拟宕机后一样能访问到!这应该就叫"分布式文件系统"的功能吧!
最后在介绍一下mogilefs的常用命令:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
####################################################################
#→显示当前mogilefs的配置信息(host,domain,class)状态,如果加上--stats="domains"可以只显示domian相关的信息.
[[email protected]
~] #
mogstats --config=/etc/mogilefs/mogilefsd.conf
####################################################################
#→显示一个具体文件的信息,包括所在域、副本数、文件ID、key、复制到了哪些tracker上面.
[[email protected]
~] #
mogfileinfo --trackers=172.16.41.1:7001 --domain=images --key="tux_1.jpg"
####################################################################
#→上传一个本地文件到指定的域内,同时必须指定key.
[[email protected]
~] #
mogupload --trackers=172.16.41.1:7001 --domain=images --key='tux_1.jpg' --file='/root/my_test_data/1.jpg'
####################################################################
#→删除指定域内的一个key.
[[email protected]
~] #
mogdelete --trackers=172.16.41.1:7001 --domain=images --key='test1.html
####################################################################
#→查看指定域内的文件有哪些.
[[email protected]
~] #
moglistkeys --trackers=172.16.41.1:7001 --domain=files
####################################################################
#→检查整个mogilefs系统.
[[email protected]
~] #
mogadm --trackers=172.16.41.1:7001 check
####################################################################
................................
................................
#→以上工具使用较为方便,其他工具使用请找"man"!
|