天天看點

CentOS 6.5 分布式檔案系統之MogileFS工作原理及實作過程

   MogileFS是一套高效的檔案自動備份元件,由Six Apart開發,廣泛應用在包括LiveJournal等web2.0站點上。

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算法;

什麼是兩段式送出: 

   通過使用某種協定進行通信來完成分布式事務,被稱為兩段式送出。從名字上看,您可能已經知道有兩個階段:

第一個階段,即預送出:

   事務協調器給每個事務管理器發送準備操作的信号。

   事務管理器将操作(通常是資料更新)步驟(或細節)寫入事務日志。如果失敗,事務管理器使用這些步驟重複操作。

   事務管理器本地建立事務并通知資料總管對資源(例如,資料庫或消息伺服器)執行操作。

   資料總管執行操作并向事務管理器報告成功(準備送出信号)或失敗(準備復原)。

   資料總管等待事務管理器進一步的指令。

   事務管理器向事務協調器報告成功或失敗。

第二階段,即送出階段:在第二階段中,第一階段的結果将傳送給所有事務管理器。

   如果任何事務管理器報告失敗,所有的事務參與者都必須復原。

   事務協調器讓所有事務管理器送出(或復原)。

   所有事務管理器将送出或復原資訊傳遞給其資料總管。

   資料總管将成功或失敗提示傳回給事務管理器。

<a href="http://s3.51cto.com/wyfs02/M01/26/E9/wKioL1Nt9w3z0lehAAE87dhGcdg736.jpg" target="_blank">   </a>

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分布式檔案系統的結構,這裡限于機器的原因,一些服務都整合在一起;

<a href="http://s3.51cto.com/wyfs02/M01/26/E9/wKioL1Nt-S7D9i2EAAK4TxGeCvM319.jpg" target="_blank">   </a>

   第一步:安裝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 [email protected]:/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@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 \

&gt;   --prefix=/usr \

&gt;   --sbin-path=/usr/sbin/nginx \

&gt;   --conf-path=/etc/nginx/nginx.conf \

&gt;   --error-log-path=/var/log/nginx/error.log \

&gt;   --http-log-path=/var/log/nginx/access.log \

&gt;   --pid-path=/var/run/nginx/nginx.pid  \

&gt;   --lock-path=/var/lock/nginx.lock \

&gt;   --user=nginx \

&gt;   --group=nginx \

&gt;   --with-http_ssl_module \

&gt;   --with-http_flv_module \

&gt;   --with-http_stub_status_module \

&gt;   --with-http_gzip_static_module \

&gt;   --http-client-body-temp-path=/var/tmp/nginx/client/ \

&gt;   --http-proxy-temp-path=/var/tmp/nginx/proxy/ \

&gt;   --http-fastcgi-temp-path=/var/tmp/nginx/fcgi/ \

&gt;   --http-uwsgi-temp-path=/var/tmp/nginx/uwsgi \

&gt;   --http-scgi-temp-path=/var/tmp/nginx/scgi \

&gt;   --with-pcre \

&gt;   --with-debug \

&gt;   --add-module=/root/nginx-mogilefs-module-master  # 這裡要指定編譯的子產品

[root@node0 nginx-1.4.2]# make &amp;&amp; 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" ] &amp;&amp; exit 0

nginx="/usr/sbin/nginx"

prog=$(basename $nginx)

NGINX_CONF_FILE="/etc/nginx/nginx.conf"

[ -f /etc/sysconfig/nginx ] &amp;&amp; . /etc/sysconfig/nginx

lockfile=/var/lock/subsys/nginx

make_dirs() {

  # make required directories

  user=`nginx -V 2&gt;&amp;1 | grep "configure arguments:" | sed 's/[^*]*--user=\([^ ]*\).*/\1/g' -`

  options=`$nginx -V 2&gt;&amp;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 &amp;&amp; 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 ] &amp;&amp; touch $lockfile

   return $retval

stop() {

   echo -n $"Stopping $prog: "

   killproc $prog -QUIT

   [ $retval -eq 0 ] &amp;&amp; rm -f $lockfile

restart() {

   configtest || return $?

   stop

   sleep 1

   start

reload() {

   echo -n $"Reloading $prog: "

   killproc $nginx -HUP

   RETVAL=$?

force_reload() {

   restart

configtest() {

 $nginx -t -c $NGINX_CONF_FILE

rh_status() {

   status $prog

rh_status_q() {

   rh_status &gt;/dev/null 2&gt;&amp;1

case "$1" in

   start)

       rh_status_q &amp;&amp; exit 0

       $1

       ;;

   stop)

       rh_status_q || exit 0

   restart|configtest)

   reload)

       rh_status_q || exit 7

   force-reload)

       force_reload

   status)

       rh_status

   condrestart|try-restart)

           ;;

   *)

       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的頁面:

<a href="http://s3.51cto.com/wyfs02/M01/26/EA/wKioL1NuIazhwS4pAAGtygDeERc606.jpg" target="_blank"></a>

第三步:連接配接上資料庫,給兩個使用者授權:

[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)]&gt; USE mysql;

Database changed

MariaDB [mysql]&gt; GRANT ALL ON *.* TO 'root'@'172.16.%.%' IDENTIFIED BY 'linux';

Query OK, 0 rows affected (0.20 sec)

MariaDB [mysql]&gt; GRANT ALL ON mogdb.* TO 'moguser'@'172.16.%.%' IDENTIFIED BY 'linux';

Query OK, 0 rows affected (0.00 sec)

MariaDB [mysql]&gt; FLUSH PRIVILEGES;

Query OK, 0 rows affected (0.21 sec)

MariaDB [mysql]&gt; 

第四步:再到兩個節點上,在其中一個上設定即可:

[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]&gt; USE mogdb;

MariaDB [mogdb]&gt; 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

                   used(G)    free(G)   total(G)  weight(%)

  dev1:   alive      2.799     15.887     18.686        100

  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

images               class0                    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

   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_domain files;

           mogilefs_pass $1 {

# 修改好配置檔案後儲存退出重新開機服務

[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  ]

[root@node0 nginx]#

<a href="http://s3.51cto.com/wyfs02/M02/26/EC/wKiom1Nu0kvhUoX7AAGNlzYhykE426.jpg" target="_blank"></a>

然後在頁面上測試通路剛才上傳的檔案以及圖檔:

<a href="http://s3.51cto.com/wyfs02/M00/26/EC/wKiom1Nu0lvgon8wAAF6poR9ojk207.jpg" target="_blank"></a>

<a href="http://s3.51cto.com/wyfs02/M02/26/EC/wKioL1Nu0jzDsnfqAADtA16tlWI571.jpg" target="_blank"></a>

總結:

   最後還可以測試一下把一個節點掉了,試着通路一下看另外正常工作的節點可不可以正常提供服務,這裡還可以添加很多功能的,後續還會更新相關的基礎網站伺服器架構搭建的文章,在此,如果發現在什麼不妥或做得不到的還望大家多提點建議。

<a href="http://down.51cto.com/data/2364413" target="_blank">附件:http://down.51cto.com/data/2364413</a>

本文轉自 wei0164 51CTO部落格,原文連結:http://blog.51cto.com/tanxw/1409362,如需轉載請自行聯系原作者