共计 22460 个字符,预计需要花费 57 分钟才能阅读完成。
一、分布式文件系统
分布式文件系统(Distributed File System)是指文件系统管理的物理存储资源不一定直接连接在本地节点上,而是通过计算机网络与节点相连,也就是集群文件系统,可以支持大数量的节点以及 PB 级的数量存储。
相对地,在一个分享的磁盘文件系统中,所有节点对数据存储区块都有相同的访问权,在这样的系统中,访问权限就必须由客户端程序来控制。
分布式文件系统可能包含的功能有:透通的数据复制与容错。也就是说,即使系统中有一小部份的节点脱机,整体来说系统仍然可以持续运作而不会有数据损失
-
分布式文件系统类别
名称 |
特性 |
MogileFS | 适用于处理海量小文件 |
Ceph | 是一个 Linux PB 级别的分布式文件系统 |
MooseFS | 通用简便,适用于研发能力不强的公司 |
Taobao Filesystem | 适用于处理海量小文件 |
ClusterFS | 适用于处理单个大文件 |
Google Filesystem | GFS+MapReduce 擅长处理单个大文件 |
Hadoop Distributed Filesystem | GFS 的山寨版 +MapReduce,擅长处理单个大文件 |
MogileFS 是一个开源的分布式文件系统,用于组建分布式文件集群,由 LiveJournal 旗下 Danga Interactive 公司开发,Danga 团队开发了包括 Memcached、MogileFS、Perlbal 等不错的开源项目:(注:Perlbal 是一个强大的 Perl 写的反向代理服务器)。目前国内使用 MogileFS 的有图片托管网站 yupoo 等
MogileFS 由 3 个部分组成:
第 1 个部分:是 server 端,包括 mogilefsd 和 mogstored 两个程序。前者即是 mogilefsd 的 tracker,它将一些全局信息保存在数据库 里,例如站点 domain,class,host 等。后者即是存储节点(store node),它其实是个 HTTP Daemon,默认侦听在 7500 端口,接受客户端的文件备份请求。在安装完后,要运行 mogadm 工具将所有的 store node 注册到 mogilefsd 的数据库里,mogilefsd 会对这些节点进行管理和监控。
第 2 个部分:是 utils(工具集),主要是 MogileFS 的一些管理工具,例如 mogadm 等。
第 3 个部分:是客户端 API,目前只有 Perl API(MogileFS.pm)、PHP,用这个模块可以编写客户端程序,实现文件的备份管理功能, 提供 MogileFS.pm。
当下互联网飞速发展,海量并发所产生的数据量以几何方式增长,随着信息链接方式日益多样化,数据存储的结构也发生了变化,在这样的压力下我们不得不重新审视大量数据的存储所带来了巨大的挑战:
1、数据采集:对于社交网站一般都是由用户上传的;
2、数据存储:现在是数据量大爆炸时代,每天都会产生大量的数据,所以数据存储就成了一个大问题;
3、数据搜索:如果说存储是考验数据的存储能力的话,那搜索就是考量计算机能力了,从大量的数据中搜索出来;
4、数据共享:数据存储下来之后还要进行数据的共享问题,大量的数据该怎么共享这些数据呢;
5、数据传输:而海量数据存储下来之后数据怎么用户与用户之间进行安全的传输;
6、数据分析:数据的分析是了解我们过去的一些行为规范;
7、数据可视化:而海量数据存储下来之后怎么样可以直观的展示在人们面前呢;
分布式文件系统的几个难点:
1、缺乏全局时钟、不过同步本身就存在时间差,很难做到步调一致,
2、面对故障的独立性,分布式是由多个节点组成的,而每个节点都是独立工作的,一个节占故障度不会影响其它节点正常工作,
3、如何去处理单点故障,一是:做冗余,对单点做备份;二是:降低单点故障的影响范围
4、事务类的挑战,在分布环境中怎么处理事务呢;ACID 或 2PI(两段式提交)、最终一致、BASE 法则、CAP 理论、Paxos 算法;
MogileFS 设置 Memcached http://www.linuxidc.com/Linux/2012-03/56905.htm
在 MogileFS 中使用 Nginx http://www.linuxidc.com/Linux/2012-03/56904.htm
在开源分布式文件系统 MogileFS 中使用 Nginx http://www.linuxidc.com/Linux/2012-03/56573.htm
自定义 Nagios 监控 MogileFS 存储节点脚本 http://www.linuxidc.com/Linux/2011-12/49394.htm
什么是两段式提交 :
通过使用某种协议进行通信来完成分布式事务,被称为两段式提交。从名字上看,您可能已经知道有两个阶段:
第一个阶段 ,即预提交:
事务协调器给每个事务管理器发送准备操作的信号。
事务管理器将操作(通常是数据更新)步骤(或细节)写入事务日志。如果失败,事务管理器使用这些步骤重复操作。
事务管理器本地创建事务并通知资源管理器对资源(例如,数据库或消息服务器)执行操作。
资源管理器执行操作并向事务管理器报告成功(准备提交信号)或失败(准备回滚)。
资源管理器等待事务管理器进一步的指令。
事务管理器向事务协调器报告成功或失败。
第二阶段,即提交阶段:在第二阶段中,第一阶段的结果将传送给所有事务管理器。
如果任何事务管理器报告失败,所有的事务参与者都必须回滚。
事务协调器让所有事务管理器提交(或回滚)。
所有事务管理器将提交或回滚信息传递给其资源管理器。
资源管理器将成功或失败提示返回给事务管理器。
事务管理器向事务协调器报告成功或失败。
CAP 理论:一致性,可用性,分区容错性;指一个分布式系统不可以满足一致性,可用性和分区容错性这三个需求,最多只能同时满足其中的两个;
C(Consistency):一致性,任何一个读操作总是能够读取之前完成的写操作;就是一个数据写入一立马被读到;
A(Availability):可用性,每一次操作总是能够 在确定的时间返回;无论成功或失败都能收到一个返回值的;
P(Tolerance of network Partition):分区容错性,在出现网络分区的情况下,仍然能够满足一致性和可用性;
BASE 法则 模型反 ACID 模型,完全不同 ACID 模型,牺牲高一致性,获得可用性或可靠性:
BA:Basically Available,基本可以用,支持分区失败(sharding 碎片划分数据库);
S:Soft state,软状态,接受一段时间内的状态不同步,异步;
E:Eventually consistent:最终一致性,弱一致性的表现;
BASE 思想主要强调基本的可用性,如果你需要 High 可用性,也就是纯粹的高性能,那么就要以一致性或容错性为牺牲,BASE 思想的方案在性能上还是有潜力可挖的。
Paxos 算法:比 2PC 提交更轻量级的分布式事务的协调方式;大概是指不出现故拜占庭将军的前提下,要取得数据的一致性,在通信信道不安全的时候,我们数据传输可能会被人劫持,这样就不能保证数据的可信了,所以必须保证通信信道安全下 Paxos 算法才可行;
实现 MogileFS 的分布式过程,按照下图构建 MogileFS 分布式文件系统的结构,这里限于机器的原因,一些服务都整合在一起;
第一步:安装 MogileFS 软件,我们前面提到,它是由三部分组成,所以三个组件都得安装上,并且每个节点都做 MogileFS 和 Mogstored;
在这里先说一个笔者的基本布局,node0(172.16.27.88)上安装 nginx 和 MariaDB,node1(172.16.27.1)和 node2(172.16.27.2)上分别安装了 MogileFS 和 Mogstored,node1 和 node2 都共同使用 node0 上的 MariaDB 数据库,nginx 做为前端接收用户请求并负载均衡到后端两个节点上;
在 node1 上的安装和配置过程,修改好配置文件之后复制一份相同的配置文件到 node2 节点上,因为它们的配置参数都是一样的:
[root@node1 ~]# rpm -ivh 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@node1 ~]# yum -y install MogileFS-Server-mogstored-2.46-2.el6.noarch.rpm MogileFS-Utils-2.19-1.el6.noarch.rpm MogileFS-Server-2.46-2.el6.noarch.rpm MogileFS-Server-mogilefsd-2.46-2.el6.noarch.rpm perl-IO-AIO | |
# 安装好之后修改配置文件,只需要修改以下几项就可以了 | |
# mysql 指使用的数据库是什么,MariaDB 也是写 mysql;mogdb 指数据库名;host=172.16.27.88 指定安装数据的地址 | |
[root@node1 ~]# vim /etc/mogilefs/mogilefsd.conf | |
db_dsn = DBI:mysql:mogdb:host=172.16.27.1 | |
db_user = moguser # 指登录 mogdb 数据所使用的用户名 | |
db_pass = linux # 登录 mogdb 数据所使用密码 | |
listen = 0.0.0.0:7001 # 0.0.0.0 表示监听所有地址 | |
# 再编辑 mogstored.conf 这个配置文件 | |
maxconns = 10000 | |
httplisten = 0.0.0.0:7500 | |
mgmtlisten = 0.0.0.0:7501 | |
docroot = /dfs/mogdata # 把这项改一个特定的目录,以便存储数据,最好是一个独立分区 | |
[root@node1 ~]# mkdir -pv /dfs/mogdata/dev1 # 创建修改的 docroot 目录 | |
[root@node1 ~]# chown -R mogilefs.mogilefs /dfs/mogdata/dev1 # 修改属主属组 | |
[root@node1 ~]# chown -R mogilefs.mogilefs /var/run/mogilefsd/ | |
[root@node1 ~]# cd /etc/mogilefs | |
[root@node1 ~]# scp mogilefsd.conf mogstored.conf root@172.16.27.2:/etc/mogilefs/ # 复制修改好的配置文件到 node2 的 mogilefs 目录下,覆盖即可,两个节点都安装配置好之后先不要启动服务,数据库还没有安装 |
在 node2 上的安装和配置,这里的配置文件由 node1 上复制过来就可以了;
[ | ]|
[ | ]|
[ | ]|
[ | ]|
[ | ]
第二步:安装 nginx 和 MariaDB,这里安装 Nginx 需要编译安装,因为他需要装载第三方模块才可以使用 mogilefs,MariaDB 安装这里就不再说明了;
在 node0 节点上的安装步骤:
# 解决依赖关系 | |
[root@node0 ~]# yum -y groupinstall "Development Tools" "Server Platform Development" | |
[root@node0 ~]# yum -y install openssl-devel pcre-devel | |
[root@node0 ~]# groupadd -r nginx | |
[root@node0 ~]# useradd -r -g nginx nginx | |
[root@node0 ~]# tar xf nginx-1.4.2.tar.gz | |
[root@node0 ~]# unzip nginx-mogilefs-module-master.zip | |
[root@node0 ~]# cd nginx-1.4.2 | |
[root@node0 nginx-1.4.2]# ls | |
auto CHANGES CHANGES.ru conf configure contrib html LICENSE man README src | |
[root@node0 nginx-1.4.2]# ./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 # 这里要指定编译的模块 | |
[root@node0 nginx-1.4.2]# make && make install | |
# 这里 MariaDB 安装过程不再说明了,可以参数前面的博文,编译安装好之后就可以可以启动 MariaDB 和去配置 Nginx 的相关配置了,还要给 nginx 提供一个服务脚本;[root@node0 support-files]# service mysqld start | |
Starting MySQL... [OK] | |
[root@node0 nginx-1.4.2]# 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 | |
[root@node0 nginx-1.4.2]# chmod +x /etc/init.d/nginx | |
[root@node0 nginx-1.4.2]# vim /etc/profile.d/nginx.sh | |
export PATH=/usr/sbin/nginx:$PATH | |
[root@node0 nginx-1.4.2]# . /etc/profile.d/nginx.sh | |
[root@node0 nginx-1.4.2]# service nginx start | |
Starting nginx: [OK] | |
[root@node0 nginx-1.4.2]# ss -tnl | |
State Recv-Q Send-Q Local Address:Port Peer Address:Port | |
LISTEN 0 128 :::111 :::* | |
LISTEN 0 128 *:111 *:* | |
LISTEN 0 128 *:80 *:* |
测试访问一下 nginx 的页面:
第三步:连接上数据库,给两个用户授权:
[root@node0 ~]# mysql -uroot -p | |
Enter password: | |
Welcome to the MariaDB monitor. Commands end with ; or \g. | |
Your MariaDB connection id is 46 | |
Server version: 10.0.10-MariaDB-log MariaDB Server | |
Copyright (c) 2000, 2014, Oracle, SkySQL Ab and others. | |
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. | |
MariaDB [(none)]> USE mysql; | |
Database changed | |
MariaDB [mysql]> GRANT ALL ON *.* TO 'root'@'172.16.%.%' IDENTIFIED BY 'linux'; | |
Query OK, 0 rows affected (0.20 sec) | |
MariaDB [mysql]> GRANT ALL ON mogdb.* TO 'moguser'@'172.16.%.%' IDENTIFIED BY 'linux'; | |
Query OK, 0 rows affected (0.00 sec) | |
MariaDB [mysql]> FLUSH PRIVILEGES; | |
Query OK, 0 rows affected (0.21 sec) | |
MariaDB [mysql]> |
第四步:再到两个节点上,在其中一个上设置即可:
[root@node1 mogilefs]# mogdbsetup --dbhost=172.16.27.88 --dbport=3306 --dbname=mogdb --dbrootuser=root --dbrootpass=linux --dbuser=moguser --dbpass=linux --yes | |
# 可以再回到 node0 上查看一下生成的数据库 | |
MariaDB [mysql]> USE mogdb; | |
Database changed | |
MariaDB [mogdb]> SHOW TABLES; | |
+----------------------+ | |
| Tables_in_mogdb | | |
+----------------------+ | |
| 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.03 sec) |
第五步:在两个节点的其中一个上添加主机:
[root@node1 ~]# mogadm --trackers=172.16.27.1:7001 host add 172.16.27.1 --ip=172.16.27.1 --status=alive | |
[root@node1 ~]# mogadm --trackers=172.16.27.1:7001 host add 172.16.27.2 --ip=172.16.27.2 --status=alive | |
[root@node1 mogilefs]# mogadm --trackers=172.16.27.1:7001 host list | |
172.16.27.1 [1]: alive | |
IP: 172.16.27.1:7500 | |
172.16.27.2 [2]: alive | |
IP: 172.16.27.2:7500 | |
# 再添加设备 | |
[root@node1 mogilefsd]# mogadm --trackers=172.16.27.1:7001 device add 172.16.27.1 1 | |
[root@node1 mogilefsd]# mogadm --trackers=172.16.27.1:7001 device add 172.16.27.2 2 | |
[root@node1 mogilefsd]# mogadm --trackers=172.16.27.1:7001 device list | |
172.16.27.1 [1]: alive | |
used(G) free(G) total(G) weight(%) | |
dev1: alive 2.799 15.887 18.686 100 | |
172.16.27.2 [2]: alive | |
used(G) free(G) total(G) weight(%) | |
dev2: alive 1.476 17.210 18.686 100 | |
# | |
[root@node1 ~]# mogadm --trackers=172.16.27.1:7001 domain add images # 添加域 | |
[root@node1 ~]# mogadm --trackers=172.16.27.1:7001 domain add files | |
[root@node1 ~]# mogadm --trackers=172.16.27.1:7001 domain add html | |
[root@node1 ~]# mogadm --trackers=172.16.27.1:7001 domain list # 查看域 | |
domain class mindevcount replpolicy hashtype | |
-------------------- -------------------- ------------- ------------ ------- | |
files default 2 MultipleHosts() NONE | |
html default 2 MultipleHosts() NONE | |
images default 2 MultipleHosts() NONE | |
[root@node1 ~]# mogadm --trackers=172.16.27.1:7001 class add images class0 --mindevcount=2 | |
[root@node1 ~]# mogadm --trackers=172.16.27.1:7001 class list | |
domain class mindevcount replpolicy hashtype | |
-------------------- -------------------- ------------- ------------ ------- | |
files default 2 MultipleHosts() NONE | |
html default 2 MultipleHosts() NONE | |
images class0 2 MultipleHosts() NONE #添加类 | |
images default 2 MultipleHosts() NONE | |
# 上传几张图片和测试的页面上去 | |
[root@node1 ~]# mogupload --trackers=172.16.27.1:7001 --domain=images --key='1.png' --file='/usr/share/backgrounds/default_1920x1200.png' | |
[root@node1 ~]# mogupload --trackers=172.16.27.1:7001 --domain=images --key='2.png' --file='/usr/share/backgrounds/wallpaper-six-2560x1240.png' | |
[root@node1 ~]# mogupload --trackers=172.16.27.1:7001 --domain=images --key='/images/3.png' --file='/usr/share/backgrounds/CentOS_wallpaper_01_1920x1200.png' | |
[root@node1 ~]# mogupload --trackers=172.16.27.1:7001 --domain=html --key='/files/index.html' --file='/var/www/html/index.html' | |
[root@node1 ~]# mogupload --trackers=172.16.27.1:7001 --domain=files --key='/files/index.html' --file='/var/www/html/index.html' | |
[root@node1 ~]# moglistkeys --trackers=172.16.27.1:7001 --domain=images | |
/images/3.png | |
1.png | |
2.png | |
[root@node1 ~]# mogfileinfo --trackers=172.16.27.1:7001 --domain=images --key='/images/3.png' | |
- file: /images/3.png | |
class: default | |
devcount: 2 | |
domain: images | |
fid: 5 | |
key: /images/3.png | |
length: 202652 | |
- http://172.16.27.2:7500/dev2/0/000/000/0000000005.fid | |
- http://172.16.27.1:7500/dev1/0/000/000/0000000005.fid | |
[root@node1 ~]# mogfileinfo --trackers=172.16.27.1:7001 --domain=files --key='/files/index.html' | |
- file: /files/index.html | |
class: default | |
devcount: 2 | |
domain: files | |
fid: 9 | |
key: /files/index.html | |
length: 53 | |
- http://172.16.27.2:7500/dev2/0/000/000/0000000009.fid | |
- http://172.16.27.1:7500/dev1/0/000/000/0000000009.fid | |
[root@node1 ~]# |
可以复制这个地址在页面上测试一下,这里是每上传一个文件就都会在两个节点是都存一份,如果节点多的话它会根据定义的 devcount 自己选择节点存储几份,这样在一个节点掉了也可以在别的节点在有相同的资源可用;
第六步:以上的都配置好了就可以在前端的 Nginx 上配置访问控制了,修改配置文件:
[root@node0 nginx]# vim nginx.conf | |
upstream mogcluster { # 定义多个上游服务器 | |
server 172.16.27.1:7001; | |
server 172.16.27.2:7001; | |
} | |
server { # 定义一个虚拟主机 | |
listen 80; | |
server_name www.tanxw.com; | |
location /images/ { | |
mogilefs_tracker mogcluster; | |
mogilefs_domain images; | |
mogilefs_pass { | |
proxy_pass $mogilefs_path; | |
proxy_hide_header Content-Type; | |
proxy_buffering off; | |
} | |
} | |
location ~* ^(/files/.*)$ { | |
mogilefs_tracker mogcluster; | |
mogilefs_domain files; | |
mogilefs_pass $1 { | |
proxy_pass $mogilefs_path; | |
proxy_hide_header Content-Type; | |
proxy_buffering off; | |
} | |
} | |
} | |
# 修改好配置文件后保存退出重启服务 | |
[root@node0 nginx]# service nginx restart | |
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok | |
nginx: configuration file /etc/nginx/nginx.conf test is successful | |
Stopping nginx: [OK] | |
Starting nginx: [OK] | |
[root@node0 nginx]# |
:
然后在页面上测试访问刚才上传的文件以及图片:
总结:
最后还可以测试一下把一个节点掉了,试着访问一下看另外正常工作的节点可不可以正常提供服务,这里还可以添加很多功能的,后续还会更新相关的基础网站服务器架构搭建的文章,在此,如果发现在什么不妥或做得不到的还望大家多提点建议。
一、分布式文件系统
分布式文件系统(Distributed File System)是指文件系统管理的物理存储资源不一定直接连接在本地节点上,而是通过计算机网络与节点相连,也就是集群文件系统,可以支持大数量的节点以及 PB 级的数量存储。
相对地,在一个分享的磁盘文件系统中,所有节点对数据存储区块都有相同的访问权,在这样的系统中,访问权限就必须由客户端程序来控制。
分布式文件系统可能包含的功能有:透通的数据复制与容错。也就是说,即使系统中有一小部份的节点脱机,整体来说系统仍然可以持续运作而不会有数据损失
-
分布式文件系统类别
名称 |
特性 |
MogileFS | 适用于处理海量小文件 |
Ceph | 是一个 Linux PB 级别的分布式文件系统 |
MooseFS | 通用简便,适用于研发能力不强的公司 |
Taobao Filesystem | 适用于处理海量小文件 |
ClusterFS | 适用于处理单个大文件 |
Google Filesystem | GFS+MapReduce 擅长处理单个大文件 |
Hadoop Distributed Filesystem | GFS 的山寨版 +MapReduce,擅长处理单个大文件 |
MogileFS 是一个开源的分布式文件系统,用于组建分布式文件集群,由 LiveJournal 旗下 Danga Interactive 公司开发,Danga 团队开发了包括 Memcached、MogileFS、Perlbal 等不错的开源项目:(注:Perlbal 是一个强大的 Perl 写的反向代理服务器)。目前国内使用 MogileFS 的有图片托管网站 yupoo 等
MogileFS 由 3 个部分组成:
第 1 个部分:是 server 端,包括 mogilefsd 和 mogstored 两个程序。前者即是 mogilefsd 的 tracker,它将一些全局信息保存在数据库 里,例如站点 domain,class,host 等。后者即是存储节点(store node),它其实是个 HTTP Daemon,默认侦听在 7500 端口,接受客户端的文件备份请求。在安装完后,要运行 mogadm 工具将所有的 store node 注册到 mogilefsd 的数据库里,mogilefsd 会对这些节点进行管理和监控。
第 2 个部分:是 utils(工具集),主要是 MogileFS 的一些管理工具,例如 mogadm 等。
第 3 个部分:是客户端 API,目前只有 Perl API(MogileFS.pm)、PHP,用这个模块可以编写客户端程序,实现文件的备份管理功能, 提供 MogileFS.pm。
当下互联网飞速发展,海量并发所产生的数据量以几何方式增长,随着信息链接方式日益多样化,数据存储的结构也发生了变化,在这样的压力下我们不得不重新审视大量数据的存储所带来了巨大的挑战:
1、数据采集:对于社交网站一般都是由用户上传的;
2、数据存储:现在是数据量大爆炸时代,每天都会产生大量的数据,所以数据存储就成了一个大问题;
3、数据搜索:如果说存储是考验数据的存储能力的话,那搜索就是考量计算机能力了,从大量的数据中搜索出来;
4、数据共享:数据存储下来之后还要进行数据的共享问题,大量的数据该怎么共享这些数据呢;
5、数据传输:而海量数据存储下来之后数据怎么用户与用户之间进行安全的传输;
6、数据分析:数据的分析是了解我们过去的一些行为规范;
7、数据可视化:而海量数据存储下来之后怎么样可以直观的展示在人们面前呢;
分布式文件系统的几个难点:
1、缺乏全局时钟、不过同步本身就存在时间差,很难做到步调一致,
2、面对故障的独立性,分布式是由多个节点组成的,而每个节点都是独立工作的,一个节占故障度不会影响其它节点正常工作,
3、如何去处理单点故障,一是:做冗余,对单点做备份;二是:降低单点故障的影响范围
4、事务类的挑战,在分布环境中怎么处理事务呢;ACID 或 2PI(两段式提交)、最终一致、BASE 法则、CAP 理论、Paxos 算法;
MogileFS 设置 Memcached http://www.linuxidc.com/Linux/2012-03/56905.htm
在 MogileFS 中使用 Nginx http://www.linuxidc.com/Linux/2012-03/56904.htm
在开源分布式文件系统 MogileFS 中使用 Nginx http://www.linuxidc.com/Linux/2012-03/56573.htm
自定义 Nagios 监控 MogileFS 存储节点脚本 http://www.linuxidc.com/Linux/2011-12/49394.htm
什么是两段式提交 :
通过使用某种协议进行通信来完成分布式事务,被称为两段式提交。从名字上看,您可能已经知道有两个阶段:
第一个阶段 ,即预提交:
事务协调器给每个事务管理器发送准备操作的信号。
事务管理器将操作(通常是数据更新)步骤(或细节)写入事务日志。如果失败,事务管理器使用这些步骤重复操作。
事务管理器本地创建事务并通知资源管理器对资源(例如,数据库或消息服务器)执行操作。
资源管理器执行操作并向事务管理器报告成功(准备提交信号)或失败(准备回滚)。
资源管理器等待事务管理器进一步的指令。
事务管理器向事务协调器报告成功或失败。
第二阶段,即提交阶段:在第二阶段中,第一阶段的结果将传送给所有事务管理器。
如果任何事务管理器报告失败,所有的事务参与者都必须回滚。
事务协调器让所有事务管理器提交(或回滚)。
所有事务管理器将提交或回滚信息传递给其资源管理器。
资源管理器将成功或失败提示返回给事务管理器。
事务管理器向事务协调器报告成功或失败。
CAP 理论:一致性,可用性,分区容错性;指一个分布式系统不可以满足一致性,可用性和分区容错性这三个需求,最多只能同时满足其中的两个;
C(Consistency):一致性,任何一个读操作总是能够读取之前完成的写操作;就是一个数据写入一立马被读到;
A(Availability):可用性,每一次操作总是能够 在确定的时间返回;无论成功或失败都能收到一个返回值的;
P(Tolerance of network Partition):分区容错性,在出现网络分区的情况下,仍然能够满足一致性和可用性;
BASE 法则 模型反 ACID 模型,完全不同 ACID 模型,牺牲高一致性,获得可用性或可靠性:
BA:Basically Available,基本可以用,支持分区失败(sharding 碎片划分数据库);
S:Soft state,软状态,接受一段时间内的状态不同步,异步;
E:Eventually consistent:最终一致性,弱一致性的表现;
BASE 思想主要强调基本的可用性,如果你需要 High 可用性,也就是纯粹的高性能,那么就要以一致性或容错性为牺牲,BASE 思想的方案在性能上还是有潜力可挖的。
Paxos 算法:比 2PC 提交更轻量级的分布式事务的协调方式;大概是指不出现故拜占庭将军的前提下,要取得数据的一致性,在通信信道不安全的时候,我们数据传输可能会被人劫持,这样就不能保证数据的可信了,所以必须保证通信信道安全下 Paxos 算法才可行;
实现 MogileFS 的分布式过程,按照下图构建 MogileFS 分布式文件系统的结构,这里限于机器的原因,一些服务都整合在一起;
第一步:安装 MogileFS 软件,我们前面提到,它是由三部分组成,所以三个组件都得安装上,并且每个节点都做 MogileFS 和 Mogstored;
在这里先说一个笔者的基本布局,node0(172.16.27.88)上安装 nginx 和 MariaDB,node1(172.16.27.1)和 node2(172.16.27.2)上分别安装了 MogileFS 和 Mogstored,node1 和 node2 都共同使用 node0 上的 MariaDB 数据库,nginx 做为前端接收用户请求并负载均衡到后端两个节点上;
在 node1 上的安装和配置过程,修改好配置文件之后复制一份相同的配置文件到 node2 节点上,因为它们的配置参数都是一样的:
[root@node1 ~]# rpm -ivh 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@node1 ~]# yum -y install MogileFS-Server-mogstored-2.46-2.el6.noarch.rpm MogileFS-Utils-2.19-1.el6.noarch.rpm MogileFS-Server-2.46-2.el6.noarch.rpm MogileFS-Server-mogilefsd-2.46-2.el6.noarch.rpm perl-IO-AIO | |
# 安装好之后修改配置文件,只需要修改以下几项就可以了 | |
# mysql 指使用的数据库是什么,MariaDB 也是写 mysql;mogdb 指数据库名;host=172.16.27.88 指定安装数据的地址 | |
[root@node1 ~]# vim /etc/mogilefs/mogilefsd.conf | |
db_dsn = DBI:mysql:mogdb:host=172.16.27.1 | |
db_user = moguser # 指登录 mogdb 数据所使用的用户名 | |
db_pass = linux # 登录 mogdb 数据所使用密码 | |
listen = 0.0.0.0:7001 # 0.0.0.0 表示监听所有地址 | |
# 再编辑 mogstored.conf 这个配置文件 | |
maxconns = 10000 | |
httplisten = 0.0.0.0:7500 | |
mgmtlisten = 0.0.0.0:7501 | |
docroot = /dfs/mogdata # 把这项改一个特定的目录,以便存储数据,最好是一个独立分区 | |
[root@node1 ~]# mkdir -pv /dfs/mogdata/dev1 # 创建修改的 docroot 目录 | |
[root@node1 ~]# chown -R mogilefs.mogilefs /dfs/mogdata/dev1 # 修改属主属组 | |
[root@node1 ~]# chown -R mogilefs.mogilefs /var/run/mogilefsd/ | |
[root@node1 ~]# cd /etc/mogilefs | |
[root@node1 ~]# scp mogilefsd.conf mogstored.conf root@172.16.27.2:/etc/mogilefs/ # 复制修改好的配置文件到 node2 的 mogilefs 目录下,覆盖即可,两个节点都安装配置好之后先不要启动服务,数据库还没有安装 |
在 node2 上的安装和配置,这里的配置文件由 node1 上复制过来就可以了;
[ | ]|
[ | ]|
[ | ]|
[ | ]|
[ | ]
第二步:安装 nginx 和 MariaDB,这里安装 Nginx 需要编译安装,因为他需要装载第三方模块才可以使用 mogilefs,MariaDB 安装这里就不再说明了;
在 node0 节点上的安装步骤:
# 解决依赖关系 | |
[root@node0 ~]# yum -y groupinstall "Development Tools" "Server Platform Development" | |
[root@node0 ~]# yum -y install openssl-devel pcre-devel | |
[root@node0 ~]# groupadd -r nginx | |
[root@node0 ~]# useradd -r -g nginx nginx | |
[root@node0 ~]# tar xf nginx-1.4.2.tar.gz | |
[root@node0 ~]# unzip nginx-mogilefs-module-master.zip | |
[root@node0 ~]# cd nginx-1.4.2 | |
[root@node0 nginx-1.4.2]# ls | |
auto CHANGES CHANGES.ru conf configure contrib html LICENSE man README src | |
[root@node0 nginx-1.4.2]# ./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 # 这里要指定编译的模块 | |
[root@node0 nginx-1.4.2]# make && make install | |
# 这里 MariaDB 安装过程不再说明了,可以参数前面的博文,编译安装好之后就可以可以启动 MariaDB 和去配置 Nginx 的相关配置了,还要给 nginx 提供一个服务脚本;[root@node0 support-files]# service mysqld start | |
Starting MySQL... [OK] | |
[root@node0 nginx-1.4.2]# 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 | |
[root@node0 nginx-1.4.2]# chmod +x /etc/init.d/nginx | |
[root@node0 nginx-1.4.2]# vim /etc/profile.d/nginx.sh | |
export PATH=/usr/sbin/nginx:$PATH | |
[root@node0 nginx-1.4.2]# . /etc/profile.d/nginx.sh | |
[root@node0 nginx-1.4.2]# service nginx start | |
Starting nginx: [OK] | |
[root@node0 nginx-1.4.2]# ss -tnl | |
State Recv-Q Send-Q Local Address:Port Peer Address:Port | |
LISTEN 0 128 :::111 :::* | |
LISTEN 0 128 *:111 *:* | |
LISTEN 0 128 *:80 *:* |
测试访问一下 nginx 的页面:
