大杂烩

实现MooseFS的高可用

#################################################################

  • 开篇引题

  • Distributed Replicated Block Device

  • 部署MFS

  • 部署Corosync+Pacemaker

  • 故障模拟测试

  • 补充和总结

#################################################################

 

开篇引题

 

   直接上图,有图有真相啊!此图是MFS网络组成和运行原理,先不说图中每种角色的作用(下文会有详细说明),直观信息告诉我们客户端无论是读写请求都需要与MasterServer通信,而图中MasterServer角色只有一个,因此单点故障的因素就显而易见了。解决MFS的单点故障正是本文的初衷,接下来就介绍如何利用多种技术解决MFS的单点故障,实现MasterServer的高可用。

 

Distributed Replicated Block Device

   分布式复制块设备是Linux内核的存储层中的一个分布式存储系统,可利用DRBD在两台Linux服务器之间共享块设备、文件系统和数据,类似于一个网络RAID1的功能,内核中的DRBD模块监听特定套接字上,复制系统调用产生的写数据为副本并通过TCP协议发送至DRBD从节点,因为节点间磁盘设备每一个数据位都是相同的,所以DRBD可以实现廉价块级别的数据共享。

   DRBD工作模型

       主从模型(primary/secondary),同一时刻只能有一个节点提供服务(否则会产生脑裂),从节点无法使用磁盘分区(挂载也不可以)。

       主主模型(primary/primary),需要借助于集群文件系统并启用分布式文件锁功能,而且写性能不会有提升.

   DRBD管理

       内核模块:drbd用户空间

       管理工具:drbdadm,drbdsetup,drbdmeta

   工作流程(默认模型是Sync)

       Async:副本交于本地TCP/IP协议栈就返回(性能最高)

       SemiSync:副本交对方TCP/IP协议栈就返回(折中方案)

       Sync:副本被secondary存储到磁盘中就返回(性能差)

   安装配置DRBD(drbd内核模块必须和内核版本完全匹配)

rpm -ivh drbd-8.4.3-33.el6.x86_64.rpm drbd-kmdl-2.6.32-358.el6-8.4.3-33.el6.x86_64.rpm 

   主配置文件

[root@one packages]# cat /etc/drbd.conf 
# You can find an example in  /usr/share/doc/drbd.../drbd.conf.example 
include "drbd.d/global_common.conf"; 
include "drbd.d/*.res"; 

    全局配置文件

cat /etc/drbd.d/global_common.conf 
global { 
    usage-count yes; 
    # minor-count dialog-refresh disable-ip-verification 

common { 
    handlers { 
        pri-on-incon-degr "/usr/lib/drbd/notify-pri-on-incon-degr.sh; /usr/lib/drbd/notify-emergency-reboot.sh; echo b > /proc/sysrq-trigger ; reboot -f"; 
        pri-lost-after-sb "/usr/lib/drbd/notify-pri-lost-after-sb.sh; /usr/lib/drbd/notify-emergency-reboot.sh; echo b > /proc/sysrq-trigger ; reboot -f"; 
        local-io-error "/usr/lib/drbd/notify-io-error.sh; /usr/lib/drbd/notify-emergency-shutdown.sh; echo o > /proc/sysrq-trigger ; halt -f"; 
        # fence-peer "/usr/lib/drbd/crm-fence-peer.sh"; 
        # split-brain "/usr/lib/drbd/notify-split-brain.sh root"; 
        # out-of-sync "/usr/lib/drbd/notify-out-of-sync.sh root"; 
        # before-resync-target "/usr/lib/drbd/snapshot-resync-target-lvm.sh -p 15 -- -c 16k"; 
        # after-resync-target /usr/lib/drbd/unsnapshot-resync-target-lvm.sh; 
    } 
    startup { 
        # wfc-timeout degr-wfc-timeout outdated-wfc-timeout wait-after-sb 
    } 
    options { 
        # cpu-mask on-no-data-accessible 
    } 
    disk { 
        on-io-error detach; 
        # size max-bio-bvecs on-io-error fencing disk-barrier disk-flushes 
        # disk-drain md-flushes resync-rate resync-after al-extents 
                # c-plan-ahead c-delay-target c-fill-target c-max-rate 
                # c-min-rate disk-timeout 
    } 
    net { 
        cram-hmac-alg "sha1"; 
        shared-secret "soulboy"; 
        # protocol timeout max-epoch-size max-buffers unplug-watermark 
        # connect-int ping-int sndbuf-size rcvbuf-size ko-count 
        # allow-two-primaries cram-hmac-alg shared-secret after-sb-0pri 
        # after-sb-1pri after-sb-2pri always-asbp rr-conflict 
        # ping-timeout data-integrity-alg tcp-cork on-congestion 
        # congestion-fill congestion-extents csums-alg verify-alg 
        # use-rle 
    } 
    syncer { 
        rate 1000M; 
    } 

   定义资源mfs

[root@one packages]# cat /etc/drbd.d/mydata.res 
resource mydata { 
    on one.soulboy.com { 
        device  /dev/drbd0; 
        disk    /dev/sdb2;     #大小要一致 
        address 192.168.1.61:7789; 
        meta-disk internal; 
    } 
    on two.soulboy.com { 
        device  /dev/drbd0; 
        disk    /dev/sdb1;     #大小要一致 
        address 192.168.1.62:7789; 
        meta-disk internal; 
    } 

resource mfs { 
    on one.soulboy.com { 
        device  /dev/drbd1; 
        disk    /dev/sdb3; 
        address 192.168.1.61:7788; 
        meta-disk internal; 
    } 
    on two.soulboy.com { 
        device  /dev/drbd1; 
        disk    /dev/sdb2; 
        address 192.168.1.62:7788; 
        meta-disk internal; 
    } 

   同步配置文件到从节点

scp /etc/drbd.d/* two.soulboy.com:/etc/drbd.d/ 

   初始化资源(分别在两个节点上执行)

drbdadm create-md mfs 

   启动资源(分别在两个节点上执行)

service drbd start 

   将某节点变为主节点(192.168.1.61为主节点)

drbdadm primary --force mydata 

   查看状态确定同步完毕

[root@one packages]# service drbd status 
1:mfs     Connected  Primary/Secondary  UpToDate/UpToDate  C  /mfs     ext4 

   格式化文件系统(在主节点)

mke2fs -t ext4 /dev/drbd1 

   允许对方抢占(分别在两节点上执行)

drbdadm primary mfs 

   开机不要自动启动

chkconfig drbd off 

部署MFS

   MFS工作原理

       MFS文件系统能够实现RAID功能,节约成本,不逊色于专业的存储系统,可以实现在线扩容。

   MFS的四种角色

       MasterServer(元数据服务器):负责管理各个ChunkServer及调度文件读写,回收文件空间及恢复多节点拷贝。

       Metalogger(元数据日志服务器):负责备份管理服务器的变化日志文件。

       ChunkServer(数据存储服务器):真正存储用户数据的服务器,将文件切块相互同步,听从MasterServer的调度为Client提供数据传输,Chunk节点数量越多,可靠性和MFS可用的磁盘空间就会越大。

       Client(客户端):客户端通过fuse内核接口远程管理服务器上所管理的数据存储服务器,和使用本地文件系统一样。

   安装配置元数据服务

mount /dev/drbd1 /mfs               #挂载drbd设备 
groupadd -g 1000 mfs                #两边节点的uid要统一 
useradd -u 1000 -g mfs -s /sbin/nologin mfs  #两边节点都需要创建 
mkdir -pv /mfs                      #主节点创建数据目录即可 
chown -R mfs.mfs /mfs               #两个节点修改目录属主和属组为mfs 
tar xf mfs-1.6.26.tar.gz 
cd mfs-1.6.26 
./configure --prefix=/mfs --with-default-user=mfs --with-default-group=mfs 
make && make install 
cp /mfs/etc/mfsmaster.cfg.dist  /mfs/etc/mfsmaster.cfg 
cp /mfs/etc/mfsexports.cfg.dist  /mfs/etc/mfsexports.cfg 
cp /mfs/var/mfs/metadata.mfs.empty  /mfs/var/mfs/metadata.mfs 

   主配置文件

vim /mfs/etc/mfsmaster.cfg 
    # WORKING_USER = mfs            #运行用户 
    # WORKING_GROUP = mfs           #运行组 
    # SYSLOG_IDENT = mfsmaster      #在syslog中标识自己 
    # LOCK_MEMORY = 0               #是否执行mlockall()以避免mfsmaster进程溢出(默认为0) 
    # NICE_LEVEL = -19              #运行的优先级 
    # EXPORTS_FILENAME = /usr/local/mfs/etc/mfsexports.cfg   #目录控制文件路径 
    # TOPOLOGY_FILENAME = /usr/local/mfs/etc/mfstopology.cfg #拓扑类型文件路径 
    # DATA_PATH = /usr/local/mfs/var/mfs    #数据存放路径(changelog,sessions,stats) 
    # BACK_LOGS = 50                        #元数据的改变日志文件数量 
    # BACK_META_KEEP_PREVIOUS = 1           # 
    # REPLICATIONS_DELAY_INIT = 300         #延迟复制时间(300秒) 
    # REPLICATIONS_DELAY_DISCONNECT = 3600  #ChunkServer断开复制的延迟 
    # MATOML_LISTEN_HOST = *                #元数据日志服务器监听的IP地址(*代表任何IP) 
    # MATOML_LISTEN_PORT = 9419             #元数据日志服务器监听的端口地址(9419) 
    # MATOCS_LISTEN_HOST = *                #用于ChunkServer连接的IP地址(*代表任何IP) 
    # MATOCS_LISTEN_PORT = 9420             #用于ChunkServer连接的端口(9420) 
    # MATOCL_LISTEN_HOST = *                #用于客户端连接的地址 
    # MATOCL_LISTEN_PORT = 9421             #用于客户端连接的端口 
    # CHUNKS_LOOP_CPS = 100000        
    # CHUNKS_LOOP_TIME = 300                #Chunks回环频率 
    # CHUNKS_SOFT_DEL_LIMIT = 10      
    # CHUNKS_HARD_DEL_LIMIT = 25 
    # CHUNKS_WRITE_REP_LIMIT = 2            #在一个循环里复制到一个ChunkServer的最大Chunks数目 
    # CHUNKS_READ_REP_LIMIT = 10 
    # REJECT_OLD_CLIENTS = 0                #弹出低于1.6.0客户端的连接 

   目录挂载控制文件

vim /mfs/etc/mfsexports.cfg #分为三个部分,无需修改 
*                       .           rw 
*                       /           rw,alldirs,maproot=0 
客户端IP         被挂载目录       客户端拥有的权限 

   为MasterServer提供lsb格式启动脚本

cat /etc/init.d/mfsmaster 
# chkconfig: 345 91 10 
# description: mfs start. 
. /etc/rc.d/init.d/functions 
. /etc/sysconfig/network 
path="/mfs/sbin" 
[ "${NETWORKING}" = "no" ] && exit 0 
start() { 
$path/mfsmaster start 
$path/mfscgiserv start 

stop() { 
$path/mfsmaster stop 
$path/mfscgiserv start 

restart() { 
$path/mfsmaster restart 
$path/mfscgiserv restart 

status() { 
$path/mfsmaster test 
$path/mfscgiserv test 

case "$1" in 
start) 
     start 
     ;; 
stop) 
     stop 
     ;; 
restart) 
     restart 
     ;; 
status) 
     status 
     ;; 
 *) 
     echo $"Usage: $0 start|stop|restart|status" 
     exit 1 
     esac 
     exit 0 

   修改权限

chmod 755 /etc/init.d/mfsmaster 

   导出命令

echo 'export PATH=$PATH:/mfs/sbin' > /etc/profile.d/mfs.sh 
. /etc/profile.d/mfs.sh 

   同步启动脚本至从节点

scp -p /etc/init.d/mfsmaster two:/etc/init.d/ 

   关闭服务卸载drbd设备

service mfsmaster stop 
umount /dev/drbd1 

 

部署Corosync+Pacemaker

   Corosync是集群管理套件的一部分,它在传递信息的时候可以通过一个简单的配置文件来定义信息传递的方式和协议等,RHCS集群套件就是基于corosync实现。但corosync只提供了message layer的能力。集群的资源管理则需要Pacemaker,其管理接口有两个分别是crmsh和pcs。

   环境准备

       service NetworkManager stop

       时间同

       主机名称解析的结果等于uname -n

   安装(pacemaker作为corosync的插件运行)

yum install -y corosync pacemaker 

    资源管理器配置接口基于crmsh

yum install -y crmsh-1.2.6-4.el6.x86_64.rpm pssh-2.3.1-2.el6.x86_64.rpm 

   生成密钥

corosync-keygen 
cp /etc/corosync/corosync.conf.example /etc/corosync/corosync.conf 

   配置文件

vim /etc/corosync/corosync.conf #添加pacemaker插件 
            compatibility: whitetank    #是否兼容0.8版本的corosync 
            totem {                     #用来定义集群节点心跳信息传递 
                version: 2              #版本号 
                secauth: on             #启用安全认证机制 
                threads: 0              #启用多少线程完成心跳信息传递 
                interface {                   #定义心跳信息传递的接口 
                    ringnumber: 0             #避免循环转发心跳信息 
                    bindnetaddr: 192.168.2.0  #指定网卡的网络地址 
                    mcastaddr: 226.194.61.21   #心跳信息使用的组播地址 
                    mcastport: 5405            #组播监听端口 
                    ttl: 1 
                } 
            } 
            logging {               #心跳信息层日志 
                fileline: off       # 
                to_stderr: no       #是否把错误信息发往屏幕 
                to_logfile: yes     #使用自定义日志文件logfile 
                to_syslog: no       #是否记录到系统日志 
                logfile: /var/log/cluster/corosync.log 
                debug: off          #调试功能 
                timestamp: on       #每次记录心跳信息是否记录时间戳 
                logger_subsys { 
                    subsys: AMF 
                    debug: off 
                } 
            } 
            amf { 
                mode: disabled 
            } 
            service {       #添加pacemaker插件 
                ver: 0 
                name: pacemaker 
            } 
            aisexec {       #可省略 
                user: root 
                group: root 
            } 

   复制配置文件到其他节点

scp -p /etc/corosync/corosync.conf /etc/corosync/authkey two.soulboy.com:/etc/corosync/ 

  分别在两节点启动corosync服务

service corosync start 

   使用crmsh接口定义drbd资源(忽略法定票数、禁用stonith设备)

crm(live)configure# property no-quorum-policy=ignore 
crm(live)configure# property stonith-enabled=false 

   定义原始资源

crm(live)configure# primitive mfs_drbd ocf:linbit:drbd params drbd_resource=mfs op monitor role=Master interval=10 timeout=20 op monitor role=Slave interval=20 timeout=20 op start timeout=240 op stop timeout=100   #定义drbd资源 
crm(live)configure# ms ms_mfs_drbd mfs_drbd meta master-max="1" master-node-max="1" clone-max="2" clone-node-max="1" notify="true"   #定义drbd的克隆资源、克隆属性 
crm(live)configure# primitive mfsstore ocf:heartbeat:Filesystem params device="/dev/drbd1" directory="/mfs" fstype="ext4" op monitor interval=40 timeout=40 op start timeout=60 op stop timeout=60   #定义本地挂载资源 
crm(live)configure# primitive mfsip ocf:heartbeat:IPaddr params ip="192.168.1.40" op monitor interval=20 timeout=20 on-fail=restart   #定义vip 
crm(live)configure# primitive mfsserver lsb:mfsmaster   #定义mfs服务 

   定义colocation约束(资源运行在同一个节点上的偏好)

crm(live)configure# colocation mfsstore_with_ms_mfs_drbd_master inf: mfsstore ms_mfs_drbd:Master   #挂载资源追随drbd主资源在一起 
crm(live)configure# colocation mfsserver_with_mfsstore inf: mfsserver mfsstore   #mfs服务追随挂载资源 
crm(live)configure# colocation mfsip_with_mfsserver inf: mfsip mfsserver   #vip追随mfs服务 

 定义资源组(如果定义了资源组就没有必要定义colocation约束了)

crm(live)configure# group ha_mfsservice mfsstore mfsserver mfsip   #本文没有这样做,但特此说明这样做也是可以的 

   定义order约束(资源启动和关闭的次序)  

crm(live)configure# order ms_mfs_drbd_before_mfsstore mandatory: ms_mfs_drbd:promote mfsstore:start   #节点上存在drbdMaster才能启动mystore服务 
crm(live)configure# order mfsstore_before_mfsserver mandatory: mfsstore:start mfsserver:start   #mystore服务启动才能启动mfs服务 
crm(live)configure# order mfsip_before_mfsserver mandatory: mfsip mfsserver   #vip启动才能启动mfs服务    

 定义location约束(资源对节点的倾向性)

location mfsservice_prefer_one ha_mfsservice 500: one.soulboy.com   #主节点从故障中回复是否可以将资源抢夺回来,本文没有这样做,特此说明这样做是可以完成资源抢占的。 

   检查语法并保存

crm(live)configure# verify 
crm(live)configure# commit 

   查看集群状态(发现资源都运行在主节点上)

[root@one packages]# crm 
crm(live)# status 
Online: [ one.soulboy.com two.soulboy.com ] 
Master/Slave Set: ms_mfs_drbd [mfs_drbd] 
     Masters: [ one.soulboy.com ] 
     Slaves:  [ two.soulboy.com ] 
mfsstore   (ocf::heartbeat:Filesystem):    Started one.soulboy.com 
mfsserver  (lsb:mfsmaster):                Started one.soulboy.com 
mfsip      (ocf::heartbeat:IPaddr):        Started one.soulboy.com 

  查看验证

[root@one ~]# drbd-overview               #drbd资源正常 
  1:mfs/0     Connected Primary/Secondary UpToDate/UpToDate C r----- /mfs    ext4 5.0G 142M 4.6G 3% 
[root@one ~]# service mfsmaster status       #mfs资源正常 
mfsmaster pid: 13966 
mfscgiserv pid:14158 
[root@one ~]# ip addr show  | grep 192.168.1.40  #vip资源正常 
    inet 192.168.1.40/24 brd 192.168.1.255 scope global secondary eth0 
[root@one ~]# ls /mfs               #挂载资源正常 
etc  lost+found  sbin  share  var 

故障模拟测试

   安装ChunkServer

useradd mfs -s /sbin/nologin 
tar xf mfs-1.6.26.tar.gz 
cd mfs-1.6.26 
./configure --prefix=/usr/local/mfs --with-default-user=mfs --with-default-group=mfs 
make && make install 
cp /usr/local/mfs/etc/mfschunkserver.cfg.dist /usr/local/mfs/etc/mfschunkserver.cfg 
cp /usr/local/mfs/etc/mfshdd.cfg.dist /usr/local/mfs/etc/mfshdd.cfg 

   主配置文件

vim /usr/local/mfs/etc/mfschunkserver.cfg 
# WORKING_USER = mfs 
# WORKING_GROUP = mfs 
# SYSLOG_IDENT = mfschunkserver 
# LOCK_MEMORY = 0 
# NICE_LEVEL = -19 
# DATA_PATH = /usr/local/mfs/var/mfs 
# MASTER_RECONNECTION_DELAY = 5 
# BIND_HOST = * 
MASTER_HOST = 192.168.1.40         #元数据服务器的地址 
MASTER_PORT = 9420                 #元数据服务器监听端口 
# MASTER_TIMEOUT = 60 
# CSSERV_LISTEN_HOST = * 
# CSSERV_LISTEN_PORT = 9422       #此端口用户和其他ChunkServer间复制数据 
# HDD_CONF_FILENAME = /usr/local/mfs/etc/mfshdd.cfg   #分配给MFS磁盘使用空间配置文件路径 
# HDD_TEST_FREQ = 10 
# LOCK_FILE = /var/run/mfs/mfschunkserver.lock 
# BACK_LOGS = 50 
# CSSERV_TIMEOUT = 5 

   磁盘空间配置文件

vim /usr/local/mfs/etc/mfshdd.cfg 
/data      #/data是一个MFS的分区,实例化为本机一个独立的磁盘挂载分区。 

   修改权限并启动服务

chown -R mfs:mfs /data 
mfschunkserver start 

   Client编译安装

   MFS客户端依赖于fuse

tar xf fuse-2.9.2.tar.gz 
cd fuse-2.9.2 
./configure 
make && make install 
vim /etc/profile     #在最后添加 
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH 
source /etc/profile   #即时生效 
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH 

   安装MFS客户端

useradd mfs -s /sbin/nologin 
tar xf mfs-1.6.26.tar.gz 
cd mfs-1.6.26 
./configure --prefix=/usr/local/mfs --with-default-user=mfs --with-default-group=mfs --enable-mfsmount 
make && make install 
modprobe fuse    #加载fuse到内核 

   挂载MFS文件系统

mkdir /webdata       #创建本地目录作为挂载点 
/usr/local/mfs/bin/mfsmount /webdata -H 192.168.1.40   #挂载MFS到本地/webdata目录 

   挂载MFSMeta文件系统

mkdir /webdatameta   #创建本地MFSMeta目录 
/usr/local/mfs/bin/mfsmount -m /webdatameta -H 192.168.1.40   #挂载MFSMeta文件系统 

   client创建文件并查看信息(正常)

[root@five /]# echo "123" > /webdata/one   #创建文件 
[root@five /]# mfsfileinfo  /webdata/one  #查看副本和存储节点 
/webdata/one: 
    chunk 0: 0000000000000006_00000001 / (id:6 ver:1) 
        copy 1: 192.168.1.50:9422 
        copy 2: 192.168.1.64:9422 

   登录web管理控制台(正常)

   模拟主节点故障

crm(live)node# standby    #离线,等待几秒钟 
crm(live)node# online     #上线 
crm(live)node# cd         #回退 
crm(live)# status         #查看集群资源状态 
Online: [ one.soulboy.com two.soulboy.com ] 
Master/Slave Set: ms_mfs_drbd [mfs_drbd] 
     Masters: [ two.soulboy.com ] 
     Slaves: [ one.soulboy.com ] 
mfsstore   (ocf::heartbeat:Filesystem):    Started two.soulboy.com 
mfsserver  (lsb:mfsmaster):                Started two.soulboy.com 
mfsip      (ocf::heartbeat:IPaddr):        Started two.soulboy.com 

   client再次创建文件并查看副本数(正常)

[root@five /]# echo "123" > /webdata/two 
[root@five /]# mfsfileinfo  /webdata/two 
/webdata/two: 
    chunk 0: 0000000000000007_00000001 / (id:7 ver:1) 
        copy 1: 192.168.1.50:9422 
        copy 2: 192.168.1.64:9422 

   再次登录web管理控制台(正常)

 

补充和总结

   解决MFS单点故障的主要思路是将MasterServer安装在drbd设备目录中,通过corosync+pacemaker将drbd、vip、mount、mfsmaster资源粘合在一起,并通过colocation和order的约束保证了资源间依赖关系和启动次序,此外mfsmaster的启动在pacemaker中定义为lsb风格RA,也就是形如/etc/init.d/目录下的sysv风格的脚本。值得一提的是pacemaker的管理接口,本文中使用的是crmsh,而pcs接口有着比crmsh更强大的功能,可以实现管理集群整个生命周期,支持节点的添加、移除、启动、关闭等操作。

   实现mysql的高可用也可以通过本文这种思路实现,具体步骤可参考本文,这里补充下pcs接口的用法,方便读者做对比。

pcs resource create myvip ocf:heartbeat:IPaddr params ip=192.168.1.70 op monitor interval=20 timeout=20 on-fail=restart   #定义vip 
pcs resource create mystore ocf:heartbeat:Filesystem params device="192.168.1.50:/mysqldata" directory="/mydata" fstype="nfs" op monitor interval=40 timeout=40 on-fail=restart op start timeout=60 op stop timeout=60   #定义nfs 
pcs resource create mysqlserver lsb:mysqld op monitor interval=20 timeout=20 on-fail=restart   #定义httpd 
pcs resource group add mysqlservice myvip mystore mysqlserver   #定义webservice资源组 
pcs constraint location mysqlservice prefers two.soulboy.com=500   #定义资源倾向性,资源组webservice对节点二的倾向性为500 
pcs constraint order start myvip then start mystore   #定义资源的order执行次序,这个貌似不能一下子定义三个资源月约束 
pcs constraint order start mystore then start mysqlserver   #定义资源的order执行次序 
pcs constraint colocation add myvip mystore   #定义colocation,如果有资源组可以省略。这个貌似不能一次定义三个资源月约束 
pcs constraint colocation add mystore mysqlserver   #定义colocation 

   实现mfs的高可用也可以通过heartbeat+drbd来实现,思路和本文类似,已经大牛撰写,文章内容优质,请参考:  qzhijun的BLOG

 

海量小文件存储利器Mogilefs

#######################################################################

  • 数据存储的趋势和大数据带来的挑战

  • 分布式存储与CAP定理

  • 分布式存储文件系统

  • Mogilefs基本原理

  • Mogilefs实现

  • Nginx反向代理Tracker节点

#######################################################################

 

数据存储的趋势和大数据带来的挑战

       当下我们处在一个互联网飞速发展的信息社会,在海量并发连接的驱动下每天所产生的数据量必然以几何方式增长,随着信息连接方式日益多样化,数据存储的结构也随着发生了变化。在这样的压力下使得人们不得不重新审视大量数据的存储所带来的挑战,例如:数据采集、数据存储、数据搜索、数据共享、数据传输、数据分析、数据可视化等一系列问题。

传统存储在面对海量数据存储表现出的力不从心已经是不争的事实,例如:纵向扩展受阵列空间限制、横向扩展受交换设备限制、节点受文件系统限制。

       然而分布式存储的出现在一定程度上有效的缓解了这一问题,之所以称之为缓解是因为分布式存储在面对海量数据存储时也并非十全十美毫无压力,依然存在的难点与挑战例如:节点间通信、数据存储、数据空间平衡、容错、文件系统支持等一系列问题仍处在不断摸索和完善中。

 

分布式存储与CAP定理

       首先要说明的是一个完美分布式系统有三个最重要的元素,他们分别是:

       一致性(Consistency):任何一个读操作总是能读取之前完成的写操作。

       可用性(Availability):每次操作总是能够在预定时间返回。

       分区容错性(Partition Tolerance):在出现网络分区(分布式)的情况下,仍然能够满足一致性和可用性。

       2007年,正当所有科学家都在致力于CAP三元素并存的时候,Eric.Brewer教授站了出来并指出CAP永远无法兼顾,只能根据具体应用来权衡和取舍,并且至多两个元素可以共存,后来由两位麻省理工学院的科学家证明此观点是具有前瞻性的,由此形成Brewer的CAP定理。

       正所谓鱼和熊掌不可兼得,关注一致性就需要处理因系统不可用而带来写操作失败的情况,反之关注可用性就无法保证每次都能读取到最新的写入操作。传统关系型数据库侧重于CA,而非关系型键值数据库则侧重于AP

       对于大型站点,可用性(Availability)分区容错性(Partition Tolerance)的优先级会高于一致性(Consistency),这里并不是指完全舍弃一致性,而是通过其他手段实现数据的弱一致性,例如:用户微博的浏览数和评论可以容忍相对长时间的不一致,几乎不会影响用户体验,而股票价格的数据则异常敏感,即便是10秒钟的数据不一致也无法容忍,为了能更形象的了解所谓“各种一致性”需要进行一下内容的回顾。

       强一致性(ACID)在单机环境中,强一致性可以由数据库的事务来保证;在分布式环境中,强一致性很难做到,即便是做到也会因为分布式事物所带来的性能低下,不适合在互联网的环境中应用。

       弱一致性(包括最终一致性)系统不能保证后续访问返回最新的值,在访问到最新值之前这段时间称之为不一致窗口

       最终一致性:是弱一致性的一种特例,存储系统保证如果对象有多次更新,在渡过不一致窗口之后必将放回最后更新的值。

       服务器的一致性N代表节点的个数;W代表更新的时候需要确认已经被更新的节点个数;R代表读取数据需要的节点数量。

               W + R > N  ---->  强一致性(通常N=3,W=R=2)

               W=N,R=1   ---->  最佳读

               W=1,R=N   ---->  最佳写

               W + R <= N ---->  弱一致性

 

分布式存储文件系统



Mogilefs基本原理

       MogileFS是一个开源的分布式文件系统,用于组建分布式文件集群,由LiveJournal旗下DangaInteractive公司开发,Danga团队开发了包括 Memcached、MogileFS、Perlbal等不错的开源项目:(注:Perlbal是一个强大的Perl写的反向代理服务器)。MogileFS是一个开源的分布式文件系统。主要特性包括:应用层的组件、无单点故障、自动文件复制、具有比RAID更好的可靠性、无需RAID支持等……核心角色如下:

       tracker节点:借助数据库保存各节点文件的元数据信息保存每个域中所有键的存储位置分布,方便检索定位数据位置的同时监控各节点,告诉客户端存储区位置并指挥storage节点复制数据副本,进程名为mogilefsd(7001)。

       database节点为tracker节点提供数据存取服务。

       storage节点:将指定域中的键转换为其特有的文件名存储在指定的设备文件中,转换后的文件名为值,storage节点自动维护键值的对应关系,storage节点由于使用http进行数据传输,因此依赖于perlbal,storage节点前端可以使用nginx进行反向代理,但需要安装nginx-mogilefs-module-master模块进行名称转换,进程名mogstored(7501),perbal(7500)。

       Domain一个域中的键值是惟一的,一个MogileFS可以有多个域,域可以用来存储不同应用类型的数据的容器。

       Host每一个存储节点称为一个主机,一个主机上可以有多个存储设备(单独的硬盘),每个设备都有ID号,Domain+Fid用来定位文件。

       Class:复制最小单位,文件属性管理,定义文件存储在不同设备上份数。

       流程图如下:

       1、应用层发起GET请求到Nginx。

       2、Nginx根据负载均衡机制随机代理到后台Node one。

       3、Node one向从服务器发起查询请求。

       4、从服务器返回查询结果。

       5、Node one将查询结果返回给Nginx。

       6、Nginx将查询结果根据模块转换为合理的url方位Node three。

       7、Node Three将文件内容通过http协议返回给Nginx。

       8、Nginx将结果返回给应用层的请求。

 

Mogilefs实现

      由于各角色和服务之间都是基于套接字通信,就服务本身来说没有耦合性,所以可以使用少量机器运行多种服务角色,功能图如下:

       1、通过Nginx+Keepalived实现高可用的负载均衡,通过upstream模块可以有选择性的转发应用层的请求至后端tracker节点。

       2、DRBD+Corosync+Pacemaker的机制保证了Mysql的高可用,详细配置请参阅博文:DAS之mysql高可用解决方案

       3、为了进一步提升Mysql的性能引入从节点为其分摊读操作,从节点的数据可以根据具体业务规模来设定,如果使用数据库代理进行读写分离,代理会成为单点故障,则需要为代理做高可用,另外Tracker节点支持手动为其指定从节点,因此可以根据自己的喜好,Mysql代理和复制相关实现请参阅博文:Mysql复制及代理

##### Database节点 
安装mariadb 
授权 
GRANT ALL ON *.* TO 'root'@'%' IDENTIFIED BY 'mypass'; 
CREATE DATABASE mogilefs; 
GRANT ALL ON mogilefs.* TO 'moguser'@'%' IDENTIFIED BY 'mogpass'; 
FLUSH PRIVILEGES; 
##### Tracker节点(可以是所有节点) 
安装 mogilefs 
修改配置文件如下 
vim /etc/mogilefs/mogilefsd.conf         
daemonize = 1 
pidfile = /var/run/mogilefsd/mogilefsd.pid 
db_dsn = DBI:mysql:mogilefs:host=192.168.1.241 
db_user = moguser 
db_pass = mogpass 
listen = 0.0.0.0:7001 
conf_port = 7001 
query_jobs = 100 
delete_jobs = 1 
replicate_jobs = 5 
reaper_jobs = 1 
service mogilefsd start     #启动服务 
ss -tanlp (LISTEN      0      128       192.168.1.241:7001  ) 
##### storage节点(可以是所有节点) 
安装 mogilefs 
mkdir /mogdata/dev1 -pv     #创建设备目录 
chown -R mogilefs.mogilefs /mogdata/dev2/   #权限 
vim /etc/mogilefs/mogstored.conf 
maxconns = 10000 
httplisten = 0.0.0.0:7500 
mgmtlisten = 0.0.0.0:7501 
docroot = /mogdata          #目录级别 
service mogstored start 
ss -tanlp (*:7500) 
##### tracker节点添加storage节点和常用命令 
mogadm check        #检测节点 
mogadm host list    #每个存储节点称为一个host 
mogadm host add 192.168.1.213 --ip=192.168.1.213 --ip=192.168.1.213 --status=alive      #添加第一个存储节点 
mogadm host add 192.168.1.242 --ip=192.168.1.242 --ip=192.168.1.242 --status=alive       #添加第一个存储节点 
mogadm host add 192.168.1.241 --ip=192.168.1.241 --ip=192.168.1.241 --status=alive      #添加第一个存储节点 
mogadm device add 192.168.1.213 1    #添加第一个设备,设备号唯一不能重名 
mogadm device add 192.168.1.242 2   #添加第二个设备 
mogadm device add 192.168.1.241 3   #添加第三个设备 
mogadm check    #可以查看状态 
mogadm domain add files     #创建文件存储域 
mogadm domain add images    #创建图片存储域 
mogadm domain list  #查看所有域 
mogupload --trackers=192.168.1.241 --domain=files --key='/fstab' --file='/etc/fstab'     #上传fstab文件,key为'/fstab' 
mogfileinfo --trackers=192.168.1.241 --domain=files --key='/fstab'    #根据key查看文件存放信息 

注释:mogupload工具是为了测试,实际环境中上传是由程序员在代码中使用mogilefs的API进行交互。

 

Nginx反向代理Tracker节点

##### 配置Nginx 
安装tng 
yum install pcre-devel -y 
yum groupinstall "Development Tools" "Server Platform Development" 
yum install libxslt-devel gd-devel lua-devel geoip-devel 
tengine-1.5.1.tar.gz 
nginx-mogilefs-module-master.zip    #mogilefs模块需要打补丁 
mkdir -pv /var/tmp/nginx/client     #模块需要 
unzip nginx-mogilefs-module-master.zip 
useradd -r nginx 
./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 \ 
  --enable-mods-shared=all \ 
  --add-module=/nginx-mogilefs-module-master 
make && make install 
vim /etc/profile.d/nginx.sh 
export PATH=/usr/local/nginx/sbin:$PATH 
. !$ 
提供脚本..... 
配置nginx 
vim /etc/nginx/nginx.cfg 
upstream trackers { 
        server 192.168.1.242:7001 weight=1; 
        server 192.168.1.213:7001 weight=1; 
        server 192.168.1.241:7001 backup; 
        check interval=3000 rise=2 fall=5 timeout=1000; 
        check_http_send "GET / HTTP/1.0\r\n\r\n"; 
        check_http_expect_alive http_2xx http_3xx; 
   } 
location /jpg/ { 
        mogilefs_tracker trackers; 
        mogilefs_domain images; 
        mogilefs_methods GET; 
        mogilefs_pass { 
            proxy_pass $mogilefs_path; 
            proxy_hide_header Content-Type; 
            proxy_buffering off; 
                } 
       } 
##### 配置keepalived 
安装keepalived 
vim /etc/keepalived/keepalived.conf  # backup  priority 99 
global_defs { 
   notification_email { 
     root@localhost 
   } 
   notification_email_from admin@localhost 
   smtp_server 127.0.0.1 
   smtp_connect_timeout 30 
   router_id LTT 

vrrp_script chk_nginx { 
   script "killall -0 nginx" 
   interval 1 
   weight -2 
   fall 2 
   rise 1 

vrrp_instance IN_1 { 
    state MASTER 
    interface eth0 
    virtual_router_id 22 
    priority 100 
    advert_int 1 
    authentication { 
        auth_type PASS 
        auth_pass aaaa 
    } 
    virtual_ipaddress { 
        192.168.1.222 
    } 
   track_script { 
    chk_nginx 


 

查看负载节点:

 

模拟GET方法测试Nginx_mogilefs模块:

 

SAN之可扩展的集群共享存储

###############################

SCSI

SAN

ISCSI

SAN和NAS的对比

ISCSI+gfs2+cLVM的实现

###############################

 

SCSI

计算机体系结构

  • CPU:核心组件,负责从memory中读取数据并进行处理。

  • Memory:核心组件,通过北桥与外围存储设备进行交换,作为易失性存储有极高的存储效率,但断电后数据会丢失。

  • IDE:有限的接口上,能够连接的设备有限,IDE的控制器在数据传输过程中的协议封装能力很差,整个传输过程需要大量CPU时钟周期的参与,这就意味着CPU要花费大量的时候完成数据的读入和写出,在业务处理比较繁忙和CPU资源极尤为重要的场合下是无法忍受的。

  • SCSI:是一种I/O技术,SCSI规范了一种并行的I/O总线和相关的协议,除了硬盘转速上的提升外,总线的适配器HBA(HostBusAdapter)卡中内置了控制芯片,此控制芯片可以完成协议的封装,可以大量降低CPU的参与,此外由于SCSI的数据传输是以块的方式进行的,因此它具有以下特点设备无关性、多设备并行、高带宽、低系统开销

SCSI使用体系结构

  • 窄SCSI总线:最多允许8个SCSI设备和它进行连接。

  • 宽SCSI总线:最多允许16个不同的SCSI设备和它进行连接

  • SCSI ID:一个独立的SCSI总线按照规格不同可以支持8或16个SCSI设备,设备的编号需要通过SCSI ID(Target)来进行控制,系统中每个SCSI设备都必须有自己唯一的SCSI ID,SCSI ID实际上就是这些设备的地址。

SCSI的局限性

  • 传输距离:由于SCSI线缆的长度有限,限制了SCSI的延展性。

  • 服务主机:Target数量限制了可服务的主机数。

 

 

SAN

  • 能够通过非SCSI线缆传输SCSI协议报文,并且能将其路由至目标存储设备的网络成为Storage Area Network(区域存储网络)。

 

SCSI协议报文

  • Physical Interconnects and Transport Protocols:定义物理传输介质和传输报文格式,通过光信道传输就成为FCSAN,通过IP网络传输就成为IPSAN

  • Shared Command Set:SCSI共享(公共)命令集,定义存储或读取等相关命令。

  • SCSI Device-Type Specific Command Sets:不同SCSI设备类型特有的命令。

  • Common Access Method:公共访问方法。

 

ISCSI

IPSAN和FCSAN的对比

  • FCSAN:需要FC的HBA,存储端互相也需要FC的交换机或者SCSI线缆,应用程序存储数据由Adapter Driver向存储网络发起请求并完成数据存取。

  • IPSAN:应用程序的请求先交由SCSI驱动封装(协议报文各种指令),再由ISCSI驱动封装(用于联系ISCSI服务器端),借助于TCP/IP网络发送至ISCSI服务器端。

IPSAN的传输过程

  • ISCSI服务端:通过安装一款成熟的存储管理软件ISCSI Target,也称为Target。

  • ISCSI客户端:可以是硬件,也可以是安装iscsi客户端软,称为Initiator。客户端的连接方式有以下三种:

  • 以太网卡+initiator软件:成本低,但需要占用客户端主机部分资源用于ISCSI和TCP/IP协议之间的解析, 适用于低I/O带宽的环境下。

  • 硬件TOE网卡+initiator:TOE(TCP Offload Engine)功能的智能以太网卡可以完成ISCSI的封装,但SCSI封装仍以软件方式运作,使得客户端主机可以从繁忙的协议中解脱出来,大幅度提高数据传输速率,降低了客户端主机资源消耗。但TOE功能的网卡,成本较高。

  • ISCSI HBA卡连接:不需要安装客户端软件,全部靠硬件,数据传输性能最好,但成本很高,客户端数量和性价比成反比。

 

SAN和NAS的对比

注释:由于SAN是在DAS的基础之上增加了延展性,因此下图以DAS作比较:

结论:从图中可以看出NAS的文件系统在服务器端,而SAN的文件系统在客户端,因为SAN的客户端可以实现对分区的创建格式化等操作,而NAS不可以。因此SAN经常配合集群文件系统(gfs2、ocfs)一起使用,为的就是避免多个Initiator对Target的同一资源在同一时刻进行征用带来的脑裂。

 

ISCSI+gfs2+cLVM的实现

架构图如下:

部署Target端

安装软件包

yum install scsi-target-utils 

查看当前磁盘状况(将/dev/sdb2发布出去3GB)

[root@localhost yum.repos.d]# fdisk -l 
Disk /dev/sdb: 21.4 GB, 21474836480 bytes 
255 heads, 63 sectors/track, 2610 cylinders 
Units = cylinders of 16065 * 512 = 8225280 bytes 
   Device Boot      Start         End      Blocks   Id  System 
/dev/sdb1               1        1217     9775521   83  Linux 
/dev/sdb2            1218        1583     2939895   83  Linux 

常用配置 

/etc/tgt/targets.conf   配置文件的方式来管理target 
/etc/sbin/tgt-admin     通过配置文件定义 
/usr/sbin/tgtadm        通过命令行的方式管来target 
service tgtd start      启动服务 

编辑配置文件vim /etc/tgt/targets.conf

<target iqn.2013-08.com.soulboy:sdb1> 
        backing-store /dev/sdb2 
        initator-address 192.168.1.0/24 
</target> 

启动服务

service tgtd start 

命令行方式配置

tgtadm --lld iscsi --mode logicalunit --op new --tid 2 --lun 1 --backing-store /dev/sdb2 
    tgtadm --lld iscsi --mode target --op bind --tid 2 --initiator-address 192.168.1.0/24 

部署各节点

安装软件包

yum install -y cman rgmanager gfs2-utils vm2-cluster 

确保个节点hosts文件和hostname为如下

[root@node3 ~]# cat /etc/hosts 
192.168.1.21    node1.soulboy.com node1 
192.168.1.22    node2.soulboy.com node2 
192.168.1.23    node3.soulboy.com node3 

各节点时间同步

ntpdate 192.168.1.101 

集群逻辑卷 cLVM共享存储做成LVM,借用HA的机制,让多个节点可以同时对一个卷发起管理操作。

vim /etc/lvm/lvm.conf 
locking_type = 3 

定义集群名称

ccs_tool create tcluster 

添加fence设备

ccs_tool addfence meatware fence_manual 

添加集群成员

ccs_tool addnode -v 1 -n 1 -f meatware node1.soulboy.com 
ccs_tool addnode -v 1 -n 2 -f meatware node2.soulboy.com 
ccs_tool addnode -v 1 -n 3 -f meatware node3.soulboy.com 

在各节点依次启动服务

service  cman  start                 
service  rgmanager start 

查看各节点信息

[root@node3 ~]#  ccs_tool lsnode 
Cluster name: tcluster, config_version: 7 
Nodename                        Votes Nodeid Fencetype 
node1.soulboy.com                  1    1 
node2.soulboy.com                  1    2 
node3.soulboy.com 

各节点安装initator配置并启动服务

yum --nogpgcheck localinstall iscsi-initiator-utils-6.2.0.872-16.el5.i386.rpm
service iscsi start 启动服务 

各节点客户端执行发现和登陆操作

[root@localhost mydata]#  iscsiadm -m discovery -t sendtargets -p 192.168.1.50 
192.168.1.50:3260,1 iqn.2013-08.com.soulboy:sdb1 
192.168.1.50:3260,1 iqn.2013-08.com.soulboy:sdb2 
[root@localhost mydata]#  iscsiadm -m node -T iqn.2013-08.com.soulboy:sdb2 -p 192.168.1.50 -l 

在任意initator上对共享设备创建分区(各节点在本地识别成sdc)

fdisk /dev/sdc 

在其他节点上执行

partprobe /dev/sdb 

在节点三创建物理卷

[root@node3 ~]# pvcreate /dev/sdc 

在节点二使用pvs命令查看

[root@node2 ~]# pvs 
PV         VG         Fmt  Attr PSize  PFree 
/dev/sda2  VolGroup00 lvm2 a--  19.88G    0 
/dev/sdc              lvm2 a--   2.80G 2.80G 

在节点三创建创建卷组

[root@node3 ~]# vgcreate clustervg /dev/sdc 

在节点二使用vgs命令查看

[root@node2]# vgs 
  VG         #PV #LV #SN Attr   VSize  VFree 
  VolGroup00   1   2   0 wz--n- 19.88G      0 
  clustervg    1   1   0 wz--nc  2.80G  2.80G 

在节点二创建逻辑卷

[root@node2]# lvcreate -L 1G -n clusterlv clustervg 

在节点三使用lvs命令查看

[root@node3 ~]# lvs 
LV        VG         Attr   LSize  Origin Snap%  Move Log Copy%  Convert 
LogVol00  VolGroup00 -wi-ao 17.88G                               
LogVol01  VolGroup00 -wi-ao  2.00G                               
clusterlv clustervg  -wi-a-  1.00G 

在集群逻辑上使用集群文件系统(暂时先创建2个日志区域,加入两个节点)

mkfs.gfs2 -j 2 -p lock_dlm -t tcluster:lktb1 /dev/clustervg/clusterlv 

各节点创建/mydata目录

mkdir /mydata 

各节点挂载逻辑卷clustervg至本地/mydata目录中

mount -t gfs2 /dev/clustervg/clusterlv /mydata 

查看信息

[root@node3 ~]# gfs2_tool df /mydata 
/mydata: 
  SB lock proto = "lock_dlm" 
  SB lock table = "tcluster:lktb1" 
  SB ondisk format = 1801 
  SB multihost format = 1900 
  Block size = 4096 
  Journals = 2 
  Resource Groups = 8 
  Mounted lock proto = "lock_dlm" 
  Mounted lock table = "tcluster:lktb1" 
  Mounted host data = "jid=1:id=196610:first=0" 
  Journal number = 1 
  Lock module flags = 0 
  Local flocks = FALSE 
  Local caching = FALSE 
  Type           Total Blocks   Used Blocks    Free Blocks    use%    
  ------------------------------------------------------------------------ 
  data           524196         66195          458001         13% 
  inodes         458018         17             458001         0% 

补充

#####立刻同步到磁盘 
gfs2_tool settune /mydata new_files_directio 1 
#####默认是60秒,日志刷新次数 
log_flush_secs = 60                    
#####扩展逻辑卷物理边界至2GB(可以指定选项,不指默认就是扩展全部) 
lvextend -L 2G /dev/clustervg/clusterlv 
mount -t gfs2 /dev/clustervg/clusterlv /mnt 
#####扩展逻辑卷逻辑编辑至2GB 
gfs2_grow /dev/clustervg/clusterlv 
#####磁盘检测命令 
fsck.gfs2 
#####冻结gfs文件系统(只能读,不能写) 
gfs2_tool freeze /mydata 
#####解冻,备份数据的时候可以用到。 
gfs2_tool unfreeze /mydata 
注释:扩展卷组需要iSCSI添加新的设备,和使用LVM一样创建PV,添加入卷组即可不在演示过程。 

测试

节点二

[root@node2 mydata]# pwd 
/mydata 
[root@node2 mydata]# ls 
[root@node2 mydata]# touch node2 
[root@node2 mydata]# ls 
node2 

节点三

[root@node3 mydata]# pwd 
/mydata 
[root@node3 mydata]# ls 
node2 
[root@node3 mydata]# rm -rf node2 

节点二

[root@node2 mydata]# pwd 
/mydata 
[root@node2 mydata]# ls

 

NAS之mysql高可用解决方案

###############################################

NAS

高可用集群

hearbeat v2、crm、NFS实现MySQL高可用集群

NFS作为共享存储所存在的问题

###############################################

 

NAS

  • (NetworkAttachedStorage):网络附属存储是一种将分布、独立的数据整合为大型、集中化管理的数据中心,以便于对不同主机和应用服务器进行访问的技术。它通过网络交换机连接存储系统和服务器,建立专门用于数据存储的私有网络,用户通过TCP/IP协议访问数据,采用业界标准的文件共享协议如:NFS、HTTP、CIFS来实现基于文件级的数据共享,NAS存储使文件共享访问变的快捷方便,并且易增加存储空间。但NAS本身也有一定的局限性,它会受到网络带宽和网络拥堵的影响,在一定程度上限制了NAS的网络传输能力。

  • NAS的优点:NAS具备文件操作和管理系统,kernel的存在有效解决多个进程在同一时间对同一资源征用带来的数据崩溃(脑裂split-brain);NAS是共享与独享兼顾的数据存储池并且简单灵活创建成本不高。

  • NAS的缺点:NAS本身将会受到网络带宽和网络拥堵的影响;文件级别的数据共享在一定程度上会影响效率。

 

高可用集群

  • 高可用集群,英文原文为High Availability Cluster,简称HA Cluster,简单的说,集群(cluster)就是一组计算机,它们作为一个整体向用户提供一组网络资源。这些单个的计算机系统 就是集群的节点(node)。只有两个节点的高可用集群又称为双机热备,即使用两台服务器互相备份。当一台服务器出现故障时,可由另一台服务器承担服务任务,从而在不需要人工干预的 情况下,自动保证系统能持续对外提供服务。双机热备只是高可用集群的一种,高可用集群系统更可以支持两个以上的节点,提供比双机热备更多、更高级的功能, 更能满足用户不断出现的需求变化,逻辑结构图如下:

  • ccm(Cluster Consensus Menbership Service):监听节点间心跳信息并计算整个集群的票数和收敛状态信息。

  • crmd(Cluster Resource Manager):集群资源管理器实现了资源的分配,资源分配的每个动作都要通过crm来实现,是核心组建,每个节点上的crm都维护一个cib用来定义资源特定的属性,哪些资源定义在同一个节点上。

  • cib(Cluster Infonation Base):集群信息基库是XML格式的配置文件,在内存中的一个XML格式的集群资源的配置文件。

  • lrmd(Local Resource Manager):本地资源管理器用来获取本地某个资源的状态,并且实现本地资源的管理。

  • pengine:PE、TE

  • PE(Policy Engine):策略引擎负责计算集群资源的粘性

  • TE(Transition Engine):事务引擎根据PE计算结果指挥节点进行资源转移

  • stonithd(Shoot The Other Node in the Head):切断故障节点电源。

Messagin Layer软件

  • heartbeat

  • corosync

  • cman

  • keepalived

  • ultramokey

Cluster Resource Manager Layer软件

  • crm

  • pacemaker

  • rgmanager

HA常用组合

  • heartbeat v2+crm

  • heartbeat v3+pacemaker

  • corosync+pacemaker

  • cman + rgmanager

  • keepalived+lvs

 

 

hearbeat v2、crm、NFS实现MySQL高可用集群

  • 网络结构图如下:

注释:节点1和节点2上运行着HA软件和mysql服务,数据目录在NFS服务器端/mydata目录下,通过HA软件的实时监控可以完成节点故障时资源的自动转移,对于客户端来说VIP表征着mysql服务,并持久可用。

必备条件

  • 节点名称必须跟uname -n命令的执行结果一致

  • 节点名称和IP对应关系保存在/etc/hosts文件,不依赖于DNS

  • 各节点ssh互信通信

  • 集群各节点时间需要同步

######修改各节点主机名 
hostname node1.soulboy.com 
vim /etc/sysconfig/network 
HOSTNAME=node1.soulboy.com 
######修改hosts文件 
vim /etc/hosts 
192.168.1.131   node1.soulboy.com       node1 
192.168.1.132   node2.soulboy.com       node2 
######各节点ssh互信,节点二不再演示 
ssh-keygen -t rsa -f ~/.ssh/id_rsa -P '' 
ssh-copy-id -i .ssh/id_rsa.pub root@192.168.1.132 
######各节点时间同步,需要时间服务器配合crontab 
* */5 * * *  ntpdate 192.168.1.100 

部署HA软件

######各节点安装软件包 
yum --nogpgcheck localinstall heartbeat-2.1.4-9.el5.i386.rpm heartbeat-gui-2.1.4-9.el5.i386.rpm heartbeat-pils-2.1.4-10.el5.i386.rpm heartbeat-stonith-2.1.4-10.el5.i386.rpm libnet-1.1.4-3.el5.i386.rpm perl-MailTools-1.77-1.el5.noarch.rpm 
######各节点提供配置文件 
cp /usr/share/doc/heartbeat-2.1.4/{authkeys,ha.cf,haresources} /etc/ha.d/ 
chmod 600 /etc/ha.d/authkeys 
######修改密钥文件authkeys 
dd if=/dev/random count=1 bs=512 | md5sum   生成随机数 
vim /etc/ha.d/authkeys 
auth 1 
1 md5 b20f227f85d8f51f76f9feec992061ed 
######各节点修改核心配置文件 
vim /etc/ha.d/ha.cf 
mcast eth0 225.0.100.20 694 1 0   组播 
node    node1.soulboy.com 
node    node2.soulboy.com 
crm     respawn                 crm从此代替haresources,并实现CRM功能 
######复制node1秘钥文件到node2 
scp /etc/ha.d/authkeys node2:/etc/ha.d/ -P  复制到node2 
######各节点启动服务 
service hearbeat start 

部署NFS服务器

partprobe /dev/sdb 
pvcreate /dev/sdb1 
vgcreate myvg /dev/sdb1 
lvcreate -L 6G -n mydata myvg 
mke2fs -j /dev/myvg/mydata 
groupadd -g 3306 mysql     添加mysql用户组 
useradd -u 3306 -g mysql -s /sbin/nologin -M mysql 
mkdir /mydata              创建共享目录 
vim /etc/fstab             开机自动挂载 
/dev/myvg/mydata    /mydata    ext3    defaults    0  0 
mount -a                   挂载 
mkdir /mydata/data         创建数据目录 
chown -R mysql.mysql /mydata/data/     修改目录为mysql用户 
vim /etc/exports 
/mydata         192.168.1.0/24(no_root_squash,rw)   修改共享权限 
exportfs -arv 

部署mysql服务

######各节点停止heartbeat服务 
service heartbeat stop 
######创建mysql用户和组 
groupadd -g 3306 mysql 
useradd -g 3306 -u 3306 -s /sbin/nologin -M mysql 
mkdir /mydata 
mount 192.168.1.230:/mydata /mydata    挂载目录 
usermod -s /bin/bash mysql             测试是否可写 
su - mysql 
touch /mydata/data/a 
rm /mydata/data/a 
logout 
usermod -s /sbin/nologin mysql 
umount /mydata                         测试正常 
#####在节点一上安装mysql 
tar xf mysql-5.5.28-linux2.6-i686.tar.gz -C /usr/local/ 
ln -sv /usr/local/mysql-5.5.28-linux2.6-i686 /usr/local/mysql 
chown -R root:mysql /usr/local/mysql/* 
mount 192.168.1.230:/mydata /mydata     挂载NFS共享目录到本地mydata目录 
#####初始化mysql 
/usr/local/mysql                        切换目录 
scripts/mysql_install_db --user=mysql --datadir=/mydata/data/  初始化 
#####修改相关配置文件 
cp /usr/local/mysql/support-files/my-large.cnf  /etc/my.cnf 
vim /etc/my.cnf 
datadir = /mydata/data 
innodb_file_per_table = 1               表空间独立 
cp /usr/local/mysql/support-files/mysql.server  /etc/init.d/mysqld 
chkconfig --add mysqld 
chkconfig mysqld off                    禁止开机自启动 
service mysqld start                    启动服务 
/usr/local/mysql/bin/mysql              客户端工具 
######为Mysql授权远程用户 
/usr/local/mysql/bin/mysql 
mysql> GRANT ALL ON *.* to 'root'@'%' IDENTIFIED BY 'redhat'; 
mysql> FLUSH PRIVILEGES; 
mysql> create database testdb; 
mysql> use testdb 
mysql> create table student (id int unsigned not null auto_increment primary key, name char(20)); 
######停止服务卸载目录 
service mysqld stop                     关闭mysql服务 
umount /mydata                          卸载mydata目录 
######同步配置文件和启动脚本到node2 
cp /etc/my.cnf  node2:/etc/   
scp /etc/init.d/mysqld  node2:/etc/init.d/ 
######为node2创建/mydata目录 
mkdir /mydata 

使用crm定义资源

######配置GUI登陆账户密码 
passwd hacluster 
######打开GUI登陆窗口(请确保连接DC) 
hb_gui & 

1、登陆crm

2、定义资源组

3、定义VIP

4、定义NFS存储

5、定义mysql服务

6、启动资源组

7、查看资源已运行在node2上

8、使用客户端登陆测试

模拟故障测试HA功能是否生效

1、资源组此时运行在node2节点,node1并无任何资源,此时让node2变为standy。

2、crm显示所有资源已成功转移至node1

3、切换至node1端验证真实性

4、mysql客户端第二次查询

crm的补充(关于资源约束)

 

location: 资源对节点的倾向程度,同一节点所有资源(进程)之和。

caloation:资源间互斥性,两个资源倾向于在一起还是分开。

order: 资源采取动作的次序。

 

NFS作为共享存储所存在的问题

  • 单点故障的问题显而易见

 

Network File System

#####################################

Local Procedure Call为开发带来的不便

Remote Procedure Call的引入

Network File System

NFS在LAMP架构下的应用

#####################################

Local Procedure Call为开发带来的不便

 本地两个进程或进程和内核之间调用函数完成某种功能的过程叫做本地过程调用。

Remote Procedure Call的引入

 远程过程调用,不同主机上的两个进程直接依赖于二进制协议通信,它是编程技术及协议,简化分布式应用程序的开发,它一种开发框架,在这种框架下,程序员开发程序无需再考虑网络报文的封装,有RPC底层机制负责完成,RPC本身只是一种协议,它的实现是Portmap。

Network File System

一、NFS简介

 和ext3、ext2等一样,也位于内核空间作为内核模块工作的,它基于RPC基础实现,不同主机上的两个进程直接依赖于二进制协议通信,它可以让远程文件系统挂载到本地一个目录。nfs-utils是NFS的安装包,包含了三个主进程:

nfsd   (文件传输主进程)      固定端口为TCP/UDP 2049端口

mountd  (接收客户端挂载请求)    动态向portmap注册端口

quotad  (磁盘配额进程)       动态向portmap注册端口

 /etc/exports  主配置文件

注意:由于nfs是基于RCP协议实现,所以请确保portmap服务开启

二、NFS工作机制

三、NFS使用方法

文件系统导出属性

ro                 只读 
rw                 读写 
sync               同步 
async              异步 
root_squach        将root用户映射为来宾账号 
no_root_squach     非常不安全,客户端管理员此时等于服务器端管理员权限。 
all_squash         把用户全部映射为来宾用户,最安全 
anonuid,anongid    指定映射的来宾账号UID和GID 

 简单的通过映射用户ID来标识文件属主和属组,客户端只要有用户ID号跟服务器端一样,就可以具有相应权限,相当不安全,因此通常可以把一个目录或文件锁定为一个服务器端能控制的用户,而所有用户的权限等于此用户的权限,例如:

NFS服务端 
useradd-u 510 nfstest 
touch/shared/nfstest 
chownnfstest.nfstest /shared/nfstest 
vim /etc/exports                          修改主配置文件 
/shared192.168.1.0/24(rw,all_squash,anonuid=510,anongid=510) 
exportfs -ra 

客户端重新挂载并看结果

showmount命令

mount-t nfs 192.168.1.30:/shared/tmp/nfs    挂载远程NFS共享目录至本地 
showmount -a 192.168.1.30    显示NFS服务器所有文件系统挂载情况 
showmount -e 192.168.1.30    显示NFS服务器已被挂在的文件系统和客户端列表 
showmount -d 192.168.1.30    显示NFS服务器已被挂在的文件系统列表 

exportfs命令(无需重启服务让配置文件生效)

-a 
-r    重新导出 
-u    取消导出 
-v    显示过程 
-arv  重新导出配置文件内容 
-auv  (取消所有导出文件系统) 

开机自动挂载

vim /etc/fstab 
192.168.1.30:/shared    /tmp/nfs    nfs    defaults,_rnetdev    0    0 

让mountd和quotad等进程监听在固定端口

vim   /etc/sysconfig/nfs 
MOUNTD_PORT=892 
RQUOTAD_PORT=875 
LOCKD_TCPPORT=32803 
LOCKD_UDPPORT=32769 

NFS在LAMP架构下的应用

一、NFS服务器端

部署LAMP平台

##########################安装LAMP########################## 
yum installhttpd httpd-develhttpd                安装httpd 
yum installmysql mysql-server mysql-devel mysql  安装mysql 
yum installphp53 php53-mbstring php53-mysqlphp   安装php 
##########################httpd############################# 
#AddDefaultCharset UTF-8                          修改字符集 
unzip Discuz_X2.5_SC_GBK.zip                      加压论坛 
mvupload/* /var/www/html/                        发布论坛 
service httpd start                               启动服务 
##########################mysql############################# 
mysqladmin -uroot -p password 'redhat'            为数据库添加密码 
grant all privileges on *.* to root@'%'identified by 'redhat'; 
                                                  远程授权root 
service mysqld start                               启动服务 
##########################修改权限安装论坛################## 
cd/var/www/html 
chmod777 config/ data/ data/cache/data/avatar/data/plugindata/data/download/data/addonmd5/data/template/data/threadcache/data/attachment/data/attachment/album/data/attachment/forum/data/attachment/group/data/log/uc_client/data/cache/uc_server/data/uc_server/data/cache/uc_server/data/avatar/uc_server/data/backup/uc_server/data/logs/uc_server/data/tmp/uc_server/data/view/ 

启动NFS服务

service portmap status                            检测portmap服务 
vim /etc/exports                                  修改主配置文件 
/var/www/html   192.168.1.240(rw,no_root_squash) 
exportfs –ra                                      重新导出目 
service nfs start                                 启动nfs服务 

二、NFS客户端

###########################安装LAP平台########################## 
yum install httpd httpd-devel                            安装httpd 
yum install php53 php53-mbstring php53-mysql             安装php 
service httpd start                                      启动服务 
##########################NFS客户端############################# 
mount -t nfs 192.168.1.230:/var/www/html /var/www/html   挂载目录 
#AddDefaultCharset UTF-8                                 修改字符集 
service httpd start                                      启动服务 

三、测试

客户端使用浏览器访问192.168.1.240(NFS客户端)

客户端使用浏览器访问192.168.1.230(NFS服务端)

 

File Transfer Protocol

#####################################

FTP简介

vsftpd基本使用

明文传输带来的安全隐患

安全通信方式

vsftpd + PAM + mysql实现虚拟用户

#####################################

FTP简介

   文件传输服务位于应用层,监听21/tcp端口,数据传输模式为自适应,没有交叉编码能力Mine,遵循原文件本身格式,基于TCP协议实现,它有两个连接,命令连接和数据连接,它的工作模式有两种,主动模式和被动模式。

主动模式

被动模式

 

vsftpd基本使用

特性

   文件服务权限等于文件系统权限和文件共享权限的交集

   支持虚拟用户

       家目录在/var/ftp目录下,/目录被锁定为其家目录

   支持匿名用户

   支持系统用户

       家目录目录在/home/username目录下,/目录没有锁定,可以切换 lcd

   支持基于PAM实现用户认证

安装

yum install vsftpd 
service vsftpd start 
chkconfig vsftpd on 
/etc/vsftpd                        配置文件 
/etc/init.d/vsftpd                 服务脚本 
/usr/sbin/vsftpd                   守护进程 
/etc/pam.d/*                       配置文件 
/lib/security                      认证模块 
/var/ftp                           文件目录,不允许除root用户之外的其他用户具有写权限 

常用选项

anonymous_enable=YES            启用匿名用户anonymous 
local_enable=YES                启用系统用户 
write_enable=YES                开启写入 
anon_upload_enable=YES          开启上传 
anon_mkdir_write_enable=YES     开启目录创建 
anon_other_write_enable=YES     开启其他写权限,例如delete等…… 
dirmessage_enable=YES           开启目录进入欢迎提示 
    vim /var/ftp/upload/.message      当用户切换到此目录时候会显示 
xferlog_enable=YES             开启传输日志 
xferlog_file=/var/log/vsftpd.log      定义传输日志存储位置和名称 
#chown_uploads=YES              是否开启修改用户上传之后修改用户属主 
#chown_username=whoever         修改为谁? 
#idle_session_timeout=600       命令连接超时时间 
#data_connection_timeout=120    数据连接超时时间 
#ascii_upload_enable=YES        文本模式上传 
#ascii_download_enable=YES      文本模式下载 
chroot_list_enable=YES          禁锢用户至自己家目录 
chroot_list_file=/etc/vsftpd/chroot_list通过用户列表禁锢那些用户 
#chroot_local_user=YES          禁锢所有用户至自己家目录,需要注释上面两项 
listen=YES                      vsftpd是否工作为一个独立守护进程类型; 
        独立守护进程适合于 (访问量大,在线时间长的服务) 
        瞬时守护进程 (访问量比较小,在线时间不长的服务) 
pam_service_name=vsftpd         基于pam的认证 
  /etc/vsftpd/ftpusers (文件中用户不能登录,清空/etc/vsftpd/user_list后才真正由此文件控制) 
userlist_enable=YES            文件的用户不允许登录(/etc/vsftpd/user_list) 
userlist_deny=NO               仅允许文件中的用户可以登录(/etc/vsftpd/user_list) 
tcp_wrappers=YES 
max_clients                    最多允许几个IP访问 
max_per_ip                     一个IP最多几个请求 

举例:让匿名用户可以上传文件

anon_upload_enable=YES    开启 
mkdir /var/ftp/upload 
setfacl -m u:ftp:rwx /var/ftp/upload/ 
getfacl /var/ftp/upload/ 

 

明文传输带来的安全隐患

使用客户端连接FTP服务器

在服务器端使用tcpdum命令抓包

tcpdump -i eth0 -nn -X -vv tcp port 21 and ip host 192.168.1.30

 

安全通信方式

ftps:ftp+ssl/tls

sftp:OpenSSH,SubSystem,sftp(SSH)

创建私有CA

cd /etc/pki/CA 
mkdir certs newcerts crl 
echo 01 > serial 
(umask 077;openssl genrsa -out private/cakey.pem 2048)创建私钥 
openssl req -new -x509 -key private/cakey.pem -out cacert.pem -days 3650生成自签证书 

生成证书颁发请求并签署

mkdir  /etc/vsftpd/ssl 
cd /etc/vsftpd/ssl 
(umask 077; openssl genrsa -out vsftpd.key 2048;)  生成私钥 
openssl req -new -key vsftpd.key -out vsftpd.csr   生成证书颁发请求 
openssl ca -in vsftpd.csr -out vsftpd.crt          签署证书 

修改配置文件etc/vsftpd/vsftpd.conf支持ssl、tsl功能

# ssl or tls 
ssl_enable=YES 
ssl_sslv3=YES 
ssl_tlsv1=YES 
allow_anon_ssl=NO 
force_local_data_ssl=YES 
force_local_logins_ssl=YES 
rsa_cert_file=/etc/vsftpd/ssl/vsftpd.crt 
rsa_private_key_file=/etc/vsftpd/ssl/vsftpd.key 

客户端软件登陆

本文中使用FlashFXP作为FTP客户端

点击连接

成功连接

在服务器端抓包发现是明文

tcpdump -i eth0 -nn -X -vv tcp port 21 and ip host 192.168.1.30

 

vsftpd + PAM + mysql实现虚拟用户

一、安装所需要程序

事先安装好开发环境和mysql数据库;

yum -y install mysql-server mysql-devel 
yum -y groupinstall "Development Tools" "Development Libraries" 

安装pam_mysql-0.7RC1

tar zxvf  pam_mysql-0.7RC1.tar.gz 
cd  pam_mysql-0.7RC1 
./configure --with-mysql=/usr --with-opensslrpm包的mysql 
make 
make install 

安装vsftpd

yum -y install vsftpd 

二、创建虚拟用户账号

准备数据库及相关表,首先请确保mysql服务已经正常启动。而后,按需要建立存储虚拟用户的数据库即可,这里将其创建为vsftpd数据库。

mysql> create database vsftpd; 
mysql> grant select on vsftpd.* to vsftpd@localhost identified by 'vsftpd'; 
mysql> grant select on vsftpd.* to vsftpd@127.0.0.1 identified by 'vsftpd'; 
mysql> flush privileges; 
mysql> use vsftpd; 
mysql> create table users ( 
    -> id int AUTO_INCREMENT NOT NULL, 
    -> name char(20) binary NOT NULL, 
    -> password char(48) binary NOT NULL, 
    -> primary key(id) 
    -> ); 

添加测试的虚拟,用户pam_mysql的password()函数与MySQL的password()函数可能会有所不同。

insert into users (name,password) value ('bob','123'),('tom','321'),('lucy','333'); 

三、配置vsftpd

建立pam认证所需文件vi /etc/pam.d/vsftpd.mysql

auth required /usr/lib/security/pam_mysql.so user=vsftpd passwd=vsftpd host=localhost db=vsftpd table=users usercolumn=name passwdcolumn=password crypt=0 
account required /usr/lib/security/pam_mysql.so user=vsftpd passwd=vsftpd host=localhost db=vsftpd table=users usercolumn=name passwdcolumn=password crypt=0 

修改vsftpd的配置文件,使其适应mysql认证,建立虚拟用户映射的系统用户及对应的目录

useradd -s /sbin/nologin -d /var/ftproot vuser 
chmod go+rx /var/ftproot 

请确保/etc/vsftpd.conf中已经启用了以下选项

anonymous_enable=YES 
local_enable=YES 
write_enable=YES 
anon_upload_enable=YES 
anon_mkdir_write_enable=NO 
chroot_local_user=YES 

修改为NO,验证不通过SSL

force_local_data_ssl=NO 
force_local_logins_ssl=NO 

而后添加以下选项

guest_enable=YES        启用来宾用户 
guest_username=vuser    来宾用户为 

并确保pam_service_name选项的值如下所示

pam_service_name=vsftpd.mysql 

四、启动vsftpd服务并测试

启动服务

service vsftpd start 
chkconfig vsftpd on            自动启动 

查看端口开启情况

netstat -tnlp |grep :21 

查看数据库

FTP客户端工具登录验证pam是否生效

五、配置虚拟用户具有不同的访问权限

为虚拟用户使用配置文件目录

vim /etc/vsftpd/vsftpd.conf 
user_config_dir=/etc/vsftpd/vusers_dir 

创建所需要目录,并为虚拟用户提供配置文件

mkdir /etc/vsftpd/vusers_dir/ 
touch /etc/vsftpd/vusers_dir/bob /etc/vsftpd/vusers_dir/tom 

配置虚拟用户的访问权限;所有虚拟用户的家目录为/var/ftproot;所有的虚拟用户映射到vuser中,而vuser属于匿名用户,因此虚拟用户的访问权限是通过匿名用户指令生效的。

bob可以上传、创建、删除

vim /etc/vsftpd/vusers_dir/bob 
anon_upload_enable=YES      (配置文件中已经开启,这里不写也可以) 
anon_mkdir_write_enable=YES 
anon_other_write_enable=YES 

tom不可以上传

vim /etc/vsftpd/vusers_dir/tom 
anon_upload_enable=NO 

lucy可以上传

主配置文件中匿名上传已启用anon_upload_enable=YES,所以不需要做任何修改 

bob测试

tom测试

lucy测试

 

rsync+inotify搭建实时同步系统

rsync简介

   rsync是Linux和UNIX系统下的文件同步和数据传输工具,它采用了“rsync”算法使一个客户机和远程文件服务器之间的文件同步,它不同于cp和wget命令完整复制的局限性,它支持增量备份,因此文件传输效率高,因而同步时间很短,具体特性如下:

   1、可以镜像保存整个目录树和文件系统

   2、可以增量同步数据。文件传输效率高。

   3、可以保持原有文件的权限、时间等属性。

   4、加密传输数据,保证数据的安全性。

   5、可以使用rcp、ssh等方式来传输文件。

 

搭建远程容灾备份系统

   Web服务器为了保证数据安全,每天凌晨2点将数据备份到远程容灾服务器上,由于数据量比较大,每年只能进行增量备份,仅备份当天新增数据,系统环境如下:

Web端配置

主配置文件/etc/rsyncd.conf

密码文件chmod 600 /etc/server.pass 

启动rsync守护进程

远程容灾端配置

密码文件chmod 600 /etc/server.pass

添加计划任务crontab -e

分析不足

此时一个远程容灾系统已经搭建完成,但这并非是一个完整意义上的容灾方案,由于rsync需要通过触发才能将服务器端数据同步,因此两次触发同步的时间间隔内,服务器和客户端的数据可能不一致,如果在这个时间间隔内,网站系统出现问题,数据必然丢失,Linux 2.6.13以后的内核提供了inotify文件系统监控机制,用过rsync与inotify的组合,完全可以实现rsync服务器端和客户端的实时数据同步。

 

rsync+inotify实现数据的实时备份

   inotify是一种强大的、细粒度的、异步的文件系统时间监控机制,Linux内核从2.6.13版本起,加入了对inotify的支持。通过inotify可以监控文件系统中添加、删除、修改、移动等各种细微事件,利用这个内核接口,第三方软件可以监控文件系统下文件的各种变化情况,inotify-tools软件正是基于这种需求实现的一个第三方软件。

   内容分发服务器实时同步数据对2个Web服务器上,inotify是用来监控文件系统变化的工具,因此必须安装在内容发布节点上,内容发布节点(Server)充当了rsync客户端的角色,2个Web节点充当了rsync服务器端的角色,整个数据同步过程就是一个从客户端向服务器端发送数据的过程,与前面案例中的逻辑结构刚好相反,系统环境如下:

Web1端配置

主配置文件/etc/rsyncd.conf

密码文件chmod 600 /etc/server.pass

启动rsync守护进程并添加开机自动启动

Web2端配置

主配置文件/etc/rsyncd.conf

密码文件chmod 600 /etc/server.pass

启动rsync守护进程并添加开机自动启动

Server端配置

安装inotify-tools

密码文件chmod 600 /etc/server.pass

监控目录变化并同步Web节点脚本

指定权限并放入后台运行

为此脚本添加开机自动启动

测试结果

Server端(rsync客户端)创建测试文件,如图:

Web1端查看,如图:

Web2端查看,如图:

 

HTML5本地存储之Database Storage篇

在上一篇《HTML5本地存储之Web Storage篇》中, 简单介绍了如何利用localStorage实现本地存储;实际上,除了sessionStorage和localStorage外,HTML5还支持通 过本地数据库进行本地数据存储,HTML5采用的是"SQLite"这种文件型数据库,该数据库多集中在嵌入式设备上,熟悉IOS/Android开发的 同学,应该对SQLite数据库比较熟悉。

HTML5中的数据库操作比较简单,主要有如下两个函数:

1、通过openDatabase方法创建一个访问数据库的对象

[javascript] view plaincopy

  1. var db = openDatabase(databasename,version,description,size)  
该方法有四个参数,作用分别为:
  • databasename:数据库名;
  • version:数据库版本号,可不填;
  • description:数据库描述;
  • size:给数据库分配的空间大小;

2、使用第一步创建的数据库访问对象(如db)执行transaction方法,用来执行事务处理;

[javascript] view plaincopy

  1. db.transaction(function(tx)){  
  2.     //执行访问数据库的语句  
  3. });  
transaction方法使用一个回调函数作为参数,在这个函数中,执行访问数据库的具体操作;

3、通过executeSql方法执行查询

[javascript] view plaincopy

  1. tx.executeSql(sqlQuery,[value1,value2..],dataHandler,errorHandler)  
executeSql方法有四个参数,作用分别如下:
  • sqlQuery:需要具体执行的sql语句,可以是create、select、update、delete;
  • [value1,value2..]:sql语句中所有使用到的参数的数组,在executeSql方法中,将sql语句中所要使用的参数先用“?”代替,然后依次将这些参数组成数组放在第二个参数中;
  • dataHandler:执行成功是调用的回调函数,通过该函数可以获得查询结果集;
  • errorHandler:执行失败时调用的回调函数;

本文通过HTML5的数据库支持,重新实现一遍上篇文章中的通讯录管理,待实现功能如下:

  • 可创建联系人并保存到数据库中,联系人字段包括:姓名、手机号码、公司、创建时间;
  • 列出当前已保存的所有联系人信息;
  • 可删除特定联系人信息;

同样,先准备一个HTML页面,如下:

[html] view plaincopy

  1. <!DOCTYPE HTML>  
  2. <html>  
  3. <head>  
  4.     <meta charset="utf-8"/>  
  5.     <title>HTML5本地存储之本地数据库篇</title>  
  6.     <style>  
  7.         .addDiv{  
  8.             border: 2px dashed #ccc;  
  9.             width:400px;  
  10.             text-align:center;  
  11.         }  
  12.     </style>  
  13. </head>  
  14. <body onload="loadAll()">  
  15.     <div class="addDiv">     
  16.         <label for="user_name">姓名:</label>  
  17.         <input type="text" id="user_name" name="user_name" class="text"/>  
  18.         <br/>  
  19.         <label for="mobilephone">手机:</label>  
  20.         <input type="text" id="mobilephone" name="mobilephone"/>  
  21.         <br/>  
  22.         <label for="mobilephone">公司:</label>  
  23.         <input type="text" id="company" name="company"/>  
  24.         <br/>  
  25.         <input type="button" onclick="save()" value="新增记录"/>  
  26.     </div>  
  27.     <br/>  
  28.     <div id="list">  
  29.     </div>  
  30. </body>  
  31. </html>  

界面展现如下:

 
要实现创建新联系人并存入数据库功能,需要如下简单的JS代码:

[javascript] view plaincopy

  1. //打开数据库  
  2. var db = openDatabase('contactdb','','local database demo',204800);  
  3.   
  4. //保存数据  
  5. function save(){  
  6.     var user_name = document.getElementById("user_name").value;  
  7.     var mobilephone = document.getElementById("mobilephone").value;  
  8.     var company = document.getElementById("company").value;  
  9.     //创建时间  
  10.     var time = new Date().getTime();  
  11.     db.transaction(function(tx){  
  12.         tx.executeSql('insert into contact values(?,?,?,?)',[user_name,mobilephone,company,time],onSuccess,onError);  
  13.     });  
  14. }  
  15.  //sql语句执行成功后执行的回调函数  
  16. function onSuccess(tx,rs){  
  17.     alert("操作成功");  
  18.     loadAll();  
  19. }  
  20. //sql语句执行失败后执行的回调函数  
  21. function onError(tx,error){  
  22.     alert("操作失败,失败信息:"+ error.message);  
  23. }  
要展现当前所有已保存的联系人列表,可通过如下JS代码实现:

[javascript] view plaincopy

  1. //将所有存储在sqlLite数据库中的联系人全部取出来  
  2. function loadAll(){  
  3.     var list = document.getElementById("list");  
  4.     db.transaction(function(tx){  
  5.         //如果数据表不存在,则创建数据表  
  6.         tx.executeSql('create table if not exists contact(name text,phone text,company text,createtime INTEGER)',[]);  
  7.         //查询所有联系人记录  
  8.         tx.executeSql('select * from contact',[],function(tx,rs){  
  9.            if(rs.rows.length>0){  
  10.                 var result = "<table>";  
  11.                 result += "<tr><th> 序号</th><th>姓名</th><th>手机</th><th>公 司</th><th>添加时间</th><th>操作</th></tr>";  
  12.                 for(var i=0;i<rs.rows.length;i++){  
  13.                     var row = rs.rows.item(i);  
  14.                     //转换时间,并格式化输出  
  15.                     var time = new Date();  
  16.                     time.setTime(row.createtime);  
  17.                     var timeStr = time.format("yyyy-MM-dd hh:mm:ss");  
  18.                     //拼装一个表格的行节点  
  19.                     result += "<tr><td>"+(i+1)+"</td><td>"+row.name+"</td><td>"+row.phone+"</td><td>"+row.company+"</td><td>"+timeStr+"</td><td><input type='button' value='删除' onclick='del("+row.phone+")'/></td></tr>";  
  20.                 }  
  21.                 list.innerHTML = result;  
  22.            }else{  
  23.                 list.innerHTML = "目前数据为空,赶紧开始加入联系人吧";  
  24.            }   
  25.         });  
  26.     });  
  27. }  
其中,涉及到格式化时间的format函数,可参考如下JS实现:

[javascript] view plaincopy

  1. Date.prototype.format = function(format)  
  2. {  
  3.     var o = {  
  4.     "M+" : this.getMonth()+1, //month  
  5.     "d+" : this.getDate(),    //day  
  6.     "h+" : this.getHours(),   //hour  
  7.     "m+" : this.getMinutes(), //minute  
  8.     "s+" : this.getSeconds(), //second  
  9.     "q+" : Math.floor((this.getMonth()+3)/3),  //quarter  
  10.     "S" : this.getMilliseconds() //millisecond  
  11.     }  
  12.     if(/(y+)/.test(format)) format=format.replace(RegExp.$1,  
  13.     (this.getFullYear()+"").substr(4 - RegExp.$1.length));  
  14.     for(var k in o)if(new RegExp("("+ k +")").test(format))  
  15.     format = format.replace(RegExp.$1,  
  16.     RegExp.$1.length==1 ? o[k] :  
  17.     ("00"+ o[k]).substr((""+ o[k]).length));  
  18.     return format;  
  19. }  
最后,界面实现效果如下:


要实现具体某个联系人,需执行如下JS代码:

[javascript] view plaincopy

  1. //删除联系人信息  
  2. function del(phone){  
  3.      db.transaction(function(tx){  
  4.         //注意这里需要显示的将传入的参数phone转变为字符串类型  
  5.         tx.executeSql('delete from contact where phone=?',[String(phone)],onSuccess,onError);  
  6.     });  
  7. }  

 

如上截图中的表格样式,可参考如下CSS代码:

[css] view plaincopy

  1. th {  
  2.     font: bold 11px "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif;  
  3.     color: #4f6b72;  
  4.     border-right: 1px solid #C1DAD7;  
  5.     border-bottom: 1px solid #C1DAD7;  
  6.     border-top: 1px solid #C1DAD7;  
  7.     letter-spacing: 2px;  
  8.     text-transform: uppercase;  
  9.     text-align: left;  
  10.     padding: 6px 6px 6px 12px;  
  11. }  
  12. td {  
  13.     border-right: 1px solid #C9DAD7;  
  14.     border-bottom: 1px solid #C9DAD7;  
  15.     background: #fff;  
  16.     padding: 6px 6px 6px 12px;  
  17.     color: #4f6b72;  
  18. }  
 
 
 
 
Anna

How to import merries diapers from Japan to China?

How to import merries diapers from Japan to China?

Seahog logistics firm can help you!

Chinese tax

Customs clearance

Customs declaration

Seahog Logistics is an international integrated logistics specialist business offering worldwide air freight and sea freight services to clients throughout the world. The company, which is located in Shanghai, was set-up in 1997 and has many years experience in the trade, with a global network of contacts and appointed agents.

 

Agent: Anna Leung   

Mobile: +86 15218771070

Tel: +86 769-89830090

Email: anna@seahog.cn 

anna0109@qq.com  

QQ:1975088296

Skype: AnnaLeung89

Company: Shanghai Seahog International Logistics Company

Address: Rm 404A, Building B, #1518 Minsheng Rd, Pudong New District,Shanghai City, China

Website: http://www.seahog-ay.com/  

 

 
 
 
 
磁选机安装

第八届中国西南国际煤矿及采矿技术装备展览会

第八届中国西南国际煤矿及采矿技术装备展览会_展会信息_财富云南_新浪七彩云南_新浪网 $(function () { $("#txtKeyword").focus(function () { if ($(this).val() == "输入你要搜索的关键字...") { $(this).val(""); } }); $("#txtKeyword").blur(function () { if ($(this).val() == "") { $(this).val("输入你要搜索的关键...
 
 
 
 
wyw5257

Set模型,集装箱改变世界

集装箱改变世界,集装箱改变了航运的经济规律.并因此改变了全球的贸易流。如果没有集装箱.就不会有全球化,集装箱成为经济全球化的幕后推手,主要有以下三个特性:

1、标准化,减少货物中转及理货时间,提高货物运输效率,降低运输成本,海上集装箱船装卸、中转。(货柜车\火车\轮船)
2、规模化,按集装箱规格来进行业务周转,规模化作业运转,降低运作成本,提高效率。( 30吨、20吨、10吨)
3、模块化,外形方正,尺寸标准化,堆放、装卸、运输方便,功能单一化,无需再包装,节约成本。

日常会有很多场景应用集装箱模式来解决很多问题,可以先看看我们常遇到的问题:

1、业务非常多,每个业务的服务器数量都很大,...

 
 
 
 
zjwsk

Hadoop分布式文件系统和OpenStack对象存储有何不同

引用:http://blog.csdn.net/starean/article/details/11158979

 

“HDFS (Hadoop分布式文件系统)和OpenStack对象存储(OpenStack Object Storage)似乎都有着相似的目的:实现冗余、快速、联网的存储。什么样的技术特性让这两种系统因而不一样?这两种存储系统最终趋于融合是否大有意义?”

问题提出之后,很快有OpenStack的开发者进行了回复。本文在此摘抄了前两名回复进行翻译,以供各位参考。


排名第一的答案来自RackSpace的OpenStack Swift开发者Chuck Their:

虽然HDFS与Openstack对象存储(Swift)之间有着一些相似之处,但是这两种系统的总体设计却大不一样。

1. HDFS使用了中央系统来维护文件元数据(Namenode,名称节点),而在Swift中,元数据呈分布式,跨集群复制。使用一种中央元数据系统对HDFS来说无异于单一故障点,因而扩展到规模非常大的环境显得更困难。
2. Swift在设计时考虑到了多租户架构,而HDFS没有多租户架构这个概念。
3. HDFS针对更庞大的文件作了优化(这是处理数据时通常会出现的情况),Swift被设计成了可以存储任何大小的文件。
4. 在HDFS中,文件写入一次,而且每次只能有一个文件写入;而在Swift中,文件可以写入多次;在并发操作环境下,以最近一次操作为准。
5. HDFS用Java来编写,而Swift用Python来编写。

 

另外,HDFS被设计成了可以存储数量中等的大文件,以支持数据处理,而Swift被设计成了一种比较通用的存储解决方案,能够可靠地存储数量非常多的大小不一的文件。

排名第二的答案来自Joshua McKenty,他是美国宇航局Nebula云计算项目的首席架构师,是OpenStack Nova软件的早期开发者之一,目前是OpenStack项目监管委员会的成员,还是Piston.cc这家基于OpenStack的公司的创始人。

Chuck刚才详细介绍了两者的技术差异,但是没有讨论两者可想而知的融合,OpenStack设计峰会上抛出了融合这个话题。简而言之,HDFS被设计 成可以使用Hadoop,跨存储环境里面的对象实现MapReduce处理。对于许多OpenStack公司(包括我自己的公司)来说,支持Swift里 面的处理是路线图上面的一个目标,不过不是每个人都认为MapReduce是解决之道。

我们已讨论过为HDFS编写包装器,这将支持OpenStack内部存储应用编程接口(API),并且让用户可以针对该数据来执行Hadoop查询。还有一个办法就是在Swift里面使用HDFS。但是这些方法似乎没有一个是理想的。

OpenStack社区方面也在开展研究开发方面的一些工作,认真研究其他替代性的MapReduce框架(Riak和CouchDB等)。

最后,现在有别的一些存储项目,目前“隶属于”OpenStack社区(SheepDog和HC2)。充分利用数据局部性,并且让对象存储变得“更智能”,这是预计会取得进步的一个领域。

 

posted on 2016-09-01 18:08  Poer李  阅读(636)  评论(0编辑  收藏  举报

导航