一、分布式文件系统
1.简介
分布式文件系统(Distributed File System)是指文件系统管理的物理存储资源不一定直接连接在本地节点上,而是通过计算机网络与节点相连。分布式文件系统的设计基于客户机/服务器模式。一个典型的网络可能包括多个供多用户访问的服务器。另外,对等特性允许一些系统扮演客户机和服务器的双重角色。例如,用户可以“发表”一个允许其他客户机访问的目录,一旦被访问,这个目录对客户机来说就像使用本地驱动器一样。
当下我们处在一个互联网飞速发展的信息社会,在海量并发连接的驱动下每天所产生的数据量必然以几何方式增长,随着信息连接方式日益多样化,数据存储的结构也随着发生了变化。在这样的压力下使得人们不得不重新审视大量数据的存储所带来的挑战,例如:数据采集、数据存储、数据搜索、数据共享、数据传输、数据分析、数据可视化等一系列问题。
传统存储在面对海量数据存储表现出的力不从心已经是不争的事实,例如:纵向扩展受阵列空间限制、横向扩展受交换设备限制、节点受文件系统限制。
然而分布式存储的出现在一定程度上有效的缓解了这一问题,之所以称之为缓解是因为分布式存储在面对海量数据存储时也并非十全十美毫无压力,依然存在的难点与挑战例如:节点间通信、数据存储、数据空间平衡、容错、文件系统支持等一系列问题仍处在不断摸索和完善中。
2.分布式文件系统的一些解决方案
Google Filesystem | 适合存储海量大个文件,元数据存储与内存中 |
HDFS(Hadoop Filesystem) | GFS的山寨版,适合存储大量大个文件 |
TFS(Taobao Filesystem) | 淘宝的文件系统,在名称节点上将元数据存储与关系数据库中,文件数量不在受限于名称节点的内容空间,可以存储海量小文件 |
Lustre | Oracle开发的企业级分布式系统,较重量级 |
MooseFS | 基于FUSE的格式,可以进行挂载使用 |
MogileFS |
擅长存储海量的小数据,元数据存储与关系型数据库中 |
二、MogileFS
1.简介
MogileFS是一个开源的分布式文件系统,用于组建分布式文件集群,由LiveJournal旗下DangaInteractive公司开发,Danga团队开发了包括 Memcached、MogileFS、Perlbal等不错的开源项目:(注:Perlbal是一个强大的Perl写的反向代理服务器)。MogileFS是一个开源的分布式文件系统。
目前使用 MogileFS 的公司非常多,比如国外的一些公司,日本前几名的公司基本都在使用这个.
国内所知道的使用 MogileFS 的公司有图片托管网站 yupoo又拍,digg, 土豆, 豆瓣,1 号店, 大众点评,搜狗,安居客等等网站.基本很多网站容量,图片都超过 30T 以上。
2.MogileFS特性
1) 应用层提供服务,不需要使用核心组件
2)无单点失败,主要有三个组件组成,分为tracker(跟踪节点)、mogstore(存储节点)、database(数据库节点)
3)自动复制文件,复制文件的最小单位不是文件,而是class
4)传输中立,无特殊协议,可以通过NFS或HTTP实现通信
5)简单的命名空间:没有目录,直接存在与存储空间上,通过域来实现
6)不用共享任何数据
3.MogileFS的组成
1)Tracker--跟踪器,调度器
MogileFS的核心,是一个调度器,mogilefsd进程就是trackers进程程序,trackers的主要职责有:删除数据、复制数据、监控、查询等等.这个是基于事件的( event-based ) 父进程/消息总线来管理所有来之于客户端应用的交互(requesting operations to be performed), 包括将请求负载平衡到多个"query workers"中,然后让 mogilefs的子进程去处理.
mogadm,mogtool的所有操作都要跟trackers打交道,Client的一些操作也需要定义好trackers,因此最好同时运行多个trackers来做负载均衡.trackers也可以只运行在一台机器上,使用负载均衡时可以使用搞一些简单的负载均衡解决方案,如haproxy,lvs,nginx等,
tarcker的配置文件为/etc/mogilefs/mogilefsd.conf,监听在TCP的7001端口
2)Database--数据库部分
主要用来存储mogilefs的元数据,所有的元数据都存储在数据库中,因此,这个数据相当重要,如果数据库挂掉,所有的数据都不能用于访问,因此,建议应该对数据库做高可用
3)mogstored--存储节点
数据存储的位置,通常是一个HTTP(webDAV)服务器,用来做数据的创建、删除、获取,任何 WebDAV 服务器都可以, 不过推荐使用 mogstored . mogilefsd可以配置到两个机器上使用不同端口… mogstored 来进行所有的 DAV 操作和流量,IO监测, 并且你自己选择的HTTP服务器(默认为 perlbal)用来做 GET 操作给客户端提供文件.
典型的应用是一个挂载点有一个大容量的SATA磁盘. 只要配置完配置文件后mogstored程序的启动将会使本机成为一个存储节点.当然还需要mogadm这个工具增加这台机器到Cluster中.
配置文件为/etc/mogilefs/mogstored.conf,监听在TCP的7500端口
4.基本工作流程
应用程序请求打开一个文件 (通过RPC 通知到 tracker, 找到一个可用的机器). 做一个 “create_open” 请求.
tracker 做一些负载均衡(load balancing)处理,决定应该去哪儿,然后给应用程序一些可能用的位置。
应用程序写到其中的一个位置去 (如果写失败,他会重新尝试并写到另外一个位置去).
应用程序 (client) 通过”create_close” 告诉tracker文件写到哪里去了.
tracker 将该名称和域命的名空间关联 (通过数据库来做的)
tracker, 在后台, 开始复制文件,知道他满足该文件类别设定的复制规则
然后,应用程序通过 “get_paths” 请求 domain+key (key == “filename”) 文件, tracker基于每一位置的I/O繁忙情况回复(在内部经过 database/memcache/etc 等的一些抉择处理), 该文件可用的完整 URLs地址列表.
应用程序然后按顺序尝试这些URL地址. (tracker’持续监测主机和设备的状态,因此不会返回死连接,默认情况下他对返回列表中的第一个元素做双重检查,除非你不要他这么做..)
三、Nginx+mogilefs的实现
1.拓扑图
说明:1.用户通过URL访问前端的nginx
2.nginx根据特定的挑选算法,挑选出后端一台tracker来响应nginx请求
3.tracker通过查找database数据库,获取到要访问的URL的值,并返回给nginx
4.nginx通过返回的值及某种挑选算法挑选一台mogstored发起请求
5.mogstored将结果返回给nginx
6.nginx构建响应报文返回给客户端
2.ip规划
角色 | 运行软件 | ip地址 |
反向代理 | nginx | 192.168.1.201 |
存储节点与调度节点1 |
mogilefs | 192.168.1.202 |
存储节点与调度节点2 |
mogilefs | 192.168.1.203 |
数据库节点 |
MariaDB | 192.168.1.204 |
3.数据库的安装操作并为授权
关于数据库的编译安装,请参照本人相关博文http://wangfeng7399.blog.51cto.com/3518031/1393146,本处将不再累赘,本处使用的为yum源的安装方式安装mysql
1
2
3
4
5
6
|
mysql> grant all on *.* to 'root' @ '192.168.1.%' identified by 'wangfeng7399' ;
Query OK, 0 rows affected ( 0.00 sec)
mysql> grant all on mgdb.* to 'mguser' @ '192.168.1.%' identified by 'wangfeng7399' ;
Query OK, 0 rows affected ( 0.00 sec)
mysql> flush privileges; Query OK, 0 rows affected ( 0.00 sec)
|
4.安装mogilefs.安装mogilefs,可以使用yum安装,也可以使用编译安装,本处通过yum安装
1
2
3
4
5
6
7
8
9
|
[root@node2 download]# ls 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-Utils- 2.19 - 1 .el6.noarch.rpm
perl-MogileFS-Client- 1.14 - 1 .el6.noarch.rpm
perl-Net-Netmask- 1.9015 - 8 .el6.noarch.rpm
perl-Perlbal- 1.78 - 1 .el6.noarch.rpm
[root@node2 download]# yum install *.rpm perl-IO-AIO -y |
5.初始化数据库
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
[root@node2 ~]# mogdbsetup --dbhost= 192.168 . 1.204 --dbname=mgdb --dbrootuser=root --dbrootpass=wangfeng7399 --dbuser=mguser --dbpass=wangfeng7399 --yes
mysql> show tables; +----------------------+ | Tables_in_mgdb | +----------------------+ | 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 | +----------------------+ |
可以看到在数据库中创建了一些表
6.修改配置文件,启动服务
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
修改/etc/mogilefs/mogilefsd.conf daemonize = 1 //是否已守护进程模式启动mogilefsd
pidfile = / var /run/mogilefsd/mogilefsd.pid //piad文件的存放位置
db_dsn = DBI:mysql:mgdb:host= 192.168 . 1.204 //数据库的存放位置
db_user = mguser //数据库的用户名
db_pass = wangfeng7399 //数据库的密码
listen = 0.0 . 0.0 : 7001 //监听的地址
[root@node2 ~]# ss -tnl |grep 7001
LISTEN 0 128 *: 7001 *:*
修改/etc/mogilefs/mogstored.conf maxconns = 10000 //最大连接数
httplisten = 0.0 . 0.0 : 7500 //http监听的地址
mgmtlisten = 0.0 . 0.0 : 7501 //mgm监听的地址
docroot = /mgdata //数据的存放位置
[root@node2 ~]# mkdir /mgdata/dev1 [root@node2 ~]# chown -R mogilefs.mogilefs /mgdata [root@node2 ~]# chown mogilefs.mogilefs /etc/mogilefs/mogstored.conf [root@node2 ~]# ss -tnl State Recv-Q Send-Q Local Address:Port Peer Address:Port LISTEN 0 128 *: 7500 *:*
LISTEN 0 128 *: 7501 *:*
|
7.配置mogilefs
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
|
[root@node2 ~]# mogadm Usage: (enter any command prefix, leaving off options, for further help)
mogadm check Check the state of the MogileFS world.
mogadm stats Show MogileFS system statistics. (DEPRECATED: use mogstats instead)
mogadm host ...
host add ... Add a host to MogileFS.
host delete ... Delete a host.
host list List all hosts.
host mark ... Change the status of a host. (equivalent to 'modify --status' )
host modify ... Modify a host's properties.
mogadm device ...
device add ... Add a device to a host.
device list ... List all devices, for each host.
device mark ... Mark a device as {alive,dead,down,drain,readonly}
device modify ... Modify a device's properties.
device summary ... List the summary of devices, for each host.
mogadm domain ...
domain add ... Add a domain ( namespace )
domain delete ... Delete a domain.
domain list List all hosts.
mogadm class ...
class add ... Add a file class to a domain.
class delete ... Delete a file class from a domain.
class list List all classes, for each domain.
class modify ... Modify properties of a file class .
mogadm slave ...
slave add ... Add a slave node for store usage
slave delete ... Delete a slave node for store usage
slave list List current store slave nodes.
slave modify ... Modify a slave node for store usage
mogadm fsck ...
fsck clearlog Clear the fsck log
fsck printlog Display the fsck log
fsck reset ... Reset fsck position back to the beginning
fsck start Start (or resume) background fsck
fsck status Show fsck status
fsck stop Stop (pause) background fsck
fsck taillog Tail the fsck log
mogadm rebalance ...
rebalance policy ... Add or adjust the current policy
rebalance reset Reset an existing policy
rebalance settings Display rebalance settings
rebalance start Start a rebalance job
rebalance status Show status of current rebalance job
rebalance stop Stop a rebalance job
rebalance test Show what devices the current policy would match
mogadm settings ...
settings list List all server settings
settings set ... Set server setting 'key' to 'value' .
|
添加存储主机
1
2
3
4
|
[root@node2 ~]# mogadm --trackers= 192.168 . 1.202 : 7001 host add 192.168 . 1.202 -ip= 192.168 . 1.202 --status=alive
[root@node2 ~]# mogadm --trackers= 192.168 . 1.202 : 7001 host list
192.168 . 1.202 [ 1 ]: alive
IP: 192.168 . 1.202 : 7500
|
添加存储设备
1
2
3
4
5
|
[root@node2 ~]# mogadm --trackers= 192.168 . 1.202 : 7001 device add 192.168 . 1.202 1
[root@node2 ~]# mogadm --trackers= 192.168 . 1.202 : 7001 device list
192.168 . 1.202 [ 1 ]: alive
used(G) free(G) total(G) weight(%)
dev1: alive 0.393 18.293 18.686 100
|
添加域
1
2
3
4
5
6
7
|
[root@node2 ~]# mogadm --trackers= 192.168 . 1.202 : 7001 domain add imgs
[root@node2 ~]# mogadm --trackers= 192.168 . 1.202 : 7001 domain add files
[root@node2 ~]# mogadm --trackers= 192.168 . 1.202 : 7001 domain list
domain class mindevcount replpolicy hashtype
-------------------- -------------------- ------------- ------------ ------- files default 2 MultipleHosts() NONE
imgs default 2 MultipleHosts() NONE
|
添加class
1
2
3
4
5
6
7
8
9
10
11
12
13
|
[root@node2 ~]# mogadm --trackers= 192.168 . 1.202 : 7001 class add imgs class1
[root@node2 ~]# mogadm --trackers= 192.168 . 1.202 : 7001 class add imgs class2
[root@node2 ~]# mogadm --trackers= 192.168 . 1.202 : 7001 class add files class1
[root@node2 ~]# mogadm --trackers= 192.168 . 1.202 : 7001 class add files class2
[root@node2 ~]# mogadm --trackers= 192.168 . 1.202 : 7001 domain list
domain class mindevcount replpolicy hashtype
-------------------- -------------------- ------------- ------------ ------- files class1 2 MultipleHosts() NONE
files class2 2 MultipleHosts() NONE
files default 2 MultipleHosts() NONE
imgs class1 2 MultipleHosts() NONE
imgs class2 2 MultipleHosts() NONE
imgs default 2 MultipleHosts() NONE
|
8.配置192.168.1.203的mogilefs。切记不要初始化数据库,配置应该与192.168.1.202一样
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
[root@node3 download]# mogadm --trackers= 192.168 . 1.203 : 7001 host add 192.168 . 1.203 --ip= 192.168 . 1.203 --status=alive
[root@node3 download]# mogadm --trackers= 192.168 . 1.203 : 7001 host list
192.168 . 1.202 [ 1 ]: alive
IP: 192.168 . 1.202 : 7500
192.168 . 1.203 [ 2 ]: alive
IP: 192.168 . 1.203 : 7500
添加存储节点 [root@node3 download]# mkdir /mgdata/dev2 [root@node3 download]# chown mogilefs.mogilefs -R /mgdata/dev2/ [root@node3 download]# mogadm --trackers= 192.168 . 1.203 : 7001 device add 192.168 . 1.203 2
[root@node3 download]# mogadm --trackers= 192.168 . 1.203 : 7001 domain list
domain class mindevcount replpolicy hashtype
-------------------- -------------------- ------------- ------------ ------- files class1 2 MultipleHosts() NONE
files class2 2 MultipleHosts() NONE
files default 2 MultipleHosts() NONE
imgs class1 2 MultipleHosts() NONE
imgs class2 2 MultipleHosts() NONE
imgs default 2 MultipleHosts() NONE
只需要添加主机就可以看到在其他主机上配置的内容 |
9.尝试上传数据,获取数据,客户端读取数据
上传数据,在任何一个节点上传都可以
1
|
[root@node3 download]# mogupload --trackers= 192.168 . 1.203 : 7001 --domain=imgs --key= '2.jpg' --file= '/root/1.jpg'
|
获取数据
1
2
3
4
5
6
7
8
9
10
|
[root@node3 download]# mogfileinfo --trackers= 192.168 . 1.203 : 7001 --domain=imgs --key= '2.jpg'
- file: 2 .jpg
class : default
devcount: 2
domain: imgs
fid: 4
key: 2 .jpg
length: 49809
- http: //192.168.1.203:7500/dev2/0/000/000/0000000004.fid
- http: //192.168.1.202:7500/dev1/0/000/000/0000000004.fid
|
客户端查看数据
我们可以通过任何一个节点查看到数据
三、与nginx结合
要想nginx能够实现对后端trucker的反向代理,必须结合第三方模块来实现
1.编译安装nginx
1
2
3
4
5
6
|
[root@node1 ~]# tar xf nginx- 1.6 . 0 .tar.gz
[root@node1 ~]# tar xf nginx_mogilefs_module- 1.0 . 4 .tar.gz
[root@node1 ~]# useradd -r nginx [root@node1 ~]# cd nginx- 1.6 . 0
[root@node1 nginx- 1.6 . 0 ]# ./configure --prefix=/usr/local/nginx --sbin-path=/usr/local/nginx/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 --add-module=../nginx_mogilefs_module- 1.0 . 4
[root@node1 nginx- 1.6 . 0 ]# make && make install
|
2.准备启动脚本
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
|
#!/bin/bash #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/local/nginx/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 |
3.nginx与mofilefs互联
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
location ~* /images/ { mogilefs_tracker 192.168 . 1.202 : 7001 ;
mogilefs_domain imgs;
mogilefs_pass {
proxy_pass $mogilefs_path;
proxy_hide_header Content-Type;
proxy_buffering off;
}
}
location ~* /file { mogilefs_tracker 192.168 . 1.202 : 7001 ;
mogilefs_domain files;
mogilefs_pass {
proxy_pass $mogilefs_path;
proxy_hide_header Content-Type;
proxy_buffering off;
}
} |
查看效果
5.配置后端truckers的集群
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
upstream mgfs { server 192.168 . 1.202 : 7001 ;
server 192.168 . 1.203 : 7001 ;
}
server{ location ~* /images/ {
mogilefs_tracker mgfs;
mogilefs_domain imgs;
mogilefs_pass {
proxy_pass $mogilefs_path;
proxy_hide_header Content-Type;
proxy_buffering off;
}
}
location ~* /file {
mogilefs_tracker mgfs;
mogilefs_domain files;
mogilefs_pass {
proxy_pass $mogilefs_path;
proxy_hide_header Content-Type;
proxy_buffering off;
}
}
} |
查看效果
大功告成了,后续思路,前段的nginx和数据库都存在单点故障,可以实现高可用集群
本文转自wangfeng7399 51CTO博客,原文链接:http://blog.51cto.com/wangfeng7399/1409582,如需转载请自行联系原作者