一、分布式文件系統
分布式文件系統(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算法;
什么是兩段式提交:
通過使用某種協議進行通信來完成分布式事務,被稱為兩段式提交。從名字上看,您可能已經知道有兩個階段:
第一個階段,即預提交:
事務協調器給每個事務管理器發送准備操作的信號。
事務管理器將操作(通常是數據更新)步驟(或細節)寫入事務日志。如果失敗,事務管理器使用這些步驟重復操作。
事務管理器本地創建事務並通知資源管理器對資源(例如,數據庫或消息服務器)執行操作。
資源管理器執行操作並向事務管理器報告成功(准備提交信號)或失敗(准備回滾)。
資源管理器等待事務管理器進一步的指令。
事務管理器向事務協調器報告成功或失敗。
第二階段,即提交階段:在第二階段中,第一階段的結果將傳送給所有事務管理器。
如果任何事務管理器報告失敗,所有的事務參與者都必須回滾。
事務協調器讓所有事務管理器提交(或回滾)。
所有事務管理器將提交或回滾信息傳遞給其資源管理器。
資源管理器將成功或失敗提示返回給事務管理器。
事務管理器向事務協調器報告成功或失敗。
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上復制過來就可以了;
[root@node2 ~]# 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@node2 ~]# 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 [root@node2 ~]# mkdir -pv /dfs/mogdata/dev2 # 創建修改的docroot目錄 [root@node1 ~]# chown -R mogilefs.mogilefs /var/run/mogilefsd/ [root@node2 ~]# chown -R mogilefs.mogilefs /dfs/mogdata/dev2 # 修改屬主屬組
第二步:安裝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]#
然后在頁面上測試訪問剛才上傳的文件以及圖片:
總結:
最后還可以測試一下把一個節點掉了,試着訪問一下看另外正常工作的節點可不可以正常提供服務,這里還可以添加很多功能的,后續還會更新相關的基礎網站服務器架構搭建的文章,在此,如果發現在什么不妥或做得不到的還望大家多提點建議。