项目有个新的需求,在多台APP服务器随机上传图片/资源文件,其中一台APP需要读取上传的图片,这样之前做的rsync+inotify的设置就无法应对了。


    所以研究了下多向触发式实时同步机制,大家可以实验一下,如果有不妥的地方,请联系我修正,多谢了。

    

以下开始正题


一、     简介

Unison是Windows、Linux以及其他Unix平台下都可以使用的文件同步工具,它能使两个文件夹(本地或网络上的)保持内容的一致。Unison拥有与其它一些同步工具或文件系统的相同的特性,但也有自身的特点:

1.跨平台使用;

2.对内核和用户权限没有特别要求;

3.Unison是双向的,它能自动处理两分拷贝中更新没有冲突的部分,有冲突的部分将会显示出来让用户选择更新策略;

4.只要是能连通的两台主机,就可以运行unison,可以直接使用socket连接或安全的ssh连接方式,对带宽的要求不高,使用类似rsync的压缩传输协议

5.Unison双向同步基本原理是:假如有A B两个文件夹,A文件夹把自己的改动同步到B,B文件夹也把自己的改动同步到A,最后A B两文件夹的内容相同,是AB文件夹的合集。

6.Unison双向同步不适用于对在两个同步文件夹中同一个文件,在同一时刻被修改时,unison是不会去同步的,因为unison无法判断以那个为准。Unison将创建文件锁,并由用户来手动解锁。


二、     测试环境

A机 ubuntu 12.04           10.8.12.35      ssh:22

B机 RHEL6.2                    10.8.12.201     ssh:22


三、     部署结果

实现A,B机的 /home/test/reward/目录双向同步。


四、     测试结果

a)     A,B机对应的目录实现了双向同步,基于文件级别,有验证措施,有日志,如果传输失败,会再次传输。

b)     有清空保护机制:如有出现 rm -rf ./* 操作会自动停止同步,并再日志中报错。但此时再有文件级别变化,执行 清空 的同步操作,然后同步有变化的文件

c)     日志文件/home/test/inotify_unison/unison.log不能删除,一旦删除,unison程序报错。

d)     注意对文件的操作是那台机器上进行的,日志就会打在那台机器上。



五、     配置步骤

    a)     安装软件

A机,ubuntu系统

test@test-01:~$ sudo apt-get install ocaml unison inotify-tools –y
test@test-01:~$ dpkg -l | grep ocaml
ii  ocaml                             3.12.1-2ubuntu2               ML language implementation with a class-based object system
ii  ocaml-base                        3.12.1-2ubuntu2               Runtime system for OCaml bytecode executables
ii  ocaml-base-nox                    3.12.1-2ubuntu2               Runtime system for OCaml bytecode executables (no X)
ii  ocaml-interp                      3.12.1-2ubuntu2               OCaml interactive interpreter and standard libraries
ii  ocaml-nox                         3.12.1-2ubuntu2               ML implementation with a class-based object system (no X)
test@test-01:~$ dpkg -l | grep unison
ii  unison                            2.40.65-1ubuntu1              file-synchronization tool for Unix and Windows
test@test-01:~$ dpkg -l | grep inotify-tools
ii  inotify-tools                     3.13-3                        command-line programs providing a simple interface to inotify



B机 RHEL系统,无需安装


b)     配置A,B机 SSH互信  账号为test


c)     检查A,B机器时间同步机制,确保AB机器时间一致。


d)     配置A机上unison服务


1)     执行unison命令生成配置文件

test@test-01:~$ unison abc



2)     创建日志文件夹(此步骤可以忽略,已添加到脚本中)

test@test-01:~$ mkdir /home/test/inotify_unison



3)     配置unison服务

test@test-01:~$ vim /home/test/.unison/default.prf

# Unison preferences file

#表示全自动模式,接受并执行默认动作。

batch = true

#表示保持同步的文件属组信息。

group = true

#表示保持同步的文件属主信息。

owner = true

#同步指定的子目录及文件,而非整个目录。可以写多个path。

#path = wwwbak

#指定同步忽略的子目录或者文件,支持正则。

#ignore = Name *.tmp

#表示保持同步的文件读写权限。

perms = -1

#安静模式

silent = true

#同步修改时间

times = true

#force参数表示会以本地所指定文件夹为标准,将该目录同步到远端。这里需要注意,如果指定了force参数,那么Unison就变成了单项同步了,也就是说会以force指定的文件夹为准进行同步,类似与rsync。

#force =

#true表示同步时通过文件的创建时间来比较两地文件;false表示同步时通过比较两地文件内容。

fastcheck = false

#links = true

#打开日志记录,指定日志路径。

log = true

logfile = /home/test/inotify_unison/unison.log

#间隔1秒后,开始新的一次同步检查

repeat = 1

#失败重试次数

retry = 10

#指定同步时最大线程数。

maxthreads = 300

#默认值是true,用于激活rsync传输模式,false将使用SSH传输

rsync = false

#使用ssh的压缩传输方式。

sshargs = -C

#stream = true

#优化传输参数,默认值为true。

xferbycopying = true


e)     配置A机上功能脚本

[test@localhost scripts]$ vim /home/test/scripts/inotify_unison.sh
#!/bin/bash
# inotify_unison tools
# create by wei.yang@baozun.cn
# 2014/11/29
UNISON="/usr/bin/unison"
LOCAL_DIR="/home/test/reward_to_sm/"
REMOTE_DIR="/home/test/reward_to_sm/"
REMOTE_USER="test"
ATTRIBUTES="modify,delete,create,attrib"
# mkdir unison log dir
LOGDIR="/home/test/inotify_unison"
# sync file to many servers  IP_LIST="10.8.12.201,10.8.9.9,10.8.12.20"
IP_LIST="10.8.12.201"
IP_LIST_FILE="/tmp/${USER}_inotify_unison_iplist"
echo $IP_LIST > $IP_LIST_FILE
sed -i 's/,/\n/g' $IP_LIST_FILE
[ -d /home/test/inotify_unison ] || mkdir -p /home/test/inotify_unison
# create /tmp/test_inotify_unison.bin
echo "#!/bin/bash
inotifywait  -mrq --timefmt '%d/%m/%y %H:%M' --format '%T %w%f' -e ${ATTRIBUTES} ${LOCAL_DIR} | while read files
do
        for IPADDR in \`sed '/^$/p' $IP_LIST_FILE\`
        do
                  $UNISON default "${LOCAL_DIR}" "ssh://${REMOTE_USER}@\$IPADDR/${REMOTE_DIR}"
        done
done
" > /tmp/${USER}_inotify_unison.bin
chmod +x /tmp/${USER}_inotify_unison.bin
start() {
     if [ -f /tmp/${USER}_inotify_unison_lock ]
     then
          echo -e " $USER inotify_unison had started !\n" &&  exit 1
     fi
     echo "$USER inotify_unison start ..."
     nohup /tmp/${USER}_inotify_unison.bin > /tmp/${USER}_inotify_unison_nohup.out 2>&1  &
     echo -e "${USER}\n${LOCAL_DIR}\n${REMOTE_DIR}\n${IP_LIST}" > /tmp/${USER}_inotify_unison_lock
}
stop() {
     echo "$USER inotify_unison stop  ... "
     rm -f /tmp/${USER}_inotify_unison_lock
     ps -ef | grep unison | grep -v grep | grep -v $$ | grep $USER | awk '{print $2}' | xargs kill -9
}
restart() {
  stop
  start
}
reload() {
  stop
  start
}
case "$1" in
    start)
        $1
        ;;
    stop)
        $1
        ;;
    restart)
        $1
        ;;
    reload)
        $1
        ;;
    status)
     if [ -f /tmp/${USER}_inotify_unison_lock ]
     then
          echo -e " $USER inotify_unison had started !\n"
          exit 0
     else
          echo -e " $USER inotify_unison not started !\n"
          exit 0
     fi
        ;;
    *)
        echo $"Usage: $0 {start|stop|status|restart|reload}"
        exit 2
esac
exit $?



PS:Windows下的unison配置文件默认位于C:\Documents and Settings\currentuser\.unison目录,默认的配置文件名是default.prf。


六、     启动与关闭inotify_unison服务

启动命令:

su - test
/home/test/scripts/inotify_unison.sh start
关闭命令:
su - test
/home/test/scripts/inotify_unison.sh stop