加载中...

实现linux多台服务器间目录文件同步

由于平台要上负载均衡,后面有4个emc节点,每次更新系统都比较麻烦,所以这里记录一下收集到的一个看着靠谱的同步方案

出处:Linux中文件实时同步 - 刘新元 - 博客园

注意:看着靠谱,暂时没有实验过,等实验后也许会更新本文。

目录

1. Rsync基本介绍

Rsync是一个文件同步工具,在同步的时候,只同步发生变化的文件或者是目录(每次发生变化的数据对整个同步目录数据来说是很小的,rsync在遍历查找文件时,速度很快)

2. rsync的两种工作模式

rsync有两种工作模式,客户端和服务器端,即rsync的客户端和服务器端是同一个程序,名字都叫rsync,你用它启动了服务作为守护进程,他就是服务器端,你没启动服务,而是直接调用它的命令,那么他就是客户端。

3. rsync的同步方案

假设有A、B两台服务器,我们要把A的文件同步到B,由于rsync的工作模式分为客户端从服务器端下载文件(pull操作),或者客户端把文件推送到服务器端(push操作),所以我们要讨论一个问题,A、B谁做客户端,谁做服务器端?

3.1 方案一

假设A做服务器端,B做客户端,那么B要从A中同步文件,就要启动定时任务,每隔一段时间执行一次同步命令,该命令会把A中的变化数据同步过来(实际上是做rsync客户端做pull操作)。

3.2 方案二

假设A做客户端,B做服务器端,A定时运行同步命令,把变化文件推送到B(rsync客户端做push操作)

这两个方案感觉都可以,那到底哪个好呢?

假设我们还有C、D两台服务器也要从A同步文件,也就是B、C和D都从A同步文件,假设用方案一,那么B、C和D都要设置一个定时任务,定时从A中拉取文件进行同步,但这有一个问题,无法实时同步,因为B、C和D都不知道A什么时候更新了文件,只能定时去同步。

如果使用方案二,则B、C和D都是rsync的服务器端(都要启动一个rsync守护进程),而客户端只有一个,就是A。假如我们在A中添加定时任务,定时执行同步命令,把A中的文件推送到B、C和D,那感觉和方案一没什么区别,也是无法实时同步文件。

但是,在方案二中,我们可以利用serync来检测哪些文件更新了,然后用serync调用rsync同步命令,把更新变化的文件推送到B、C、D服务器。

4. 环境信息

使用方案二 push操作
192.168.28.100 客户端
192.168.29.101 服务端

4.1 配置服务端

192.168.29.101

4.1.1 安装rsync和修改配置文件

  1. [root@node2 ~]# yum -y install rsync
  2. [root@node2 ~]# cat /etc/rsyncd.conf
  3. #指定运行的用户名或ID号(rsync客户端推送过来的文件所有者会被创建为uid指定的所有者)
  4. uid = root
  5. #指定运行的组名或组ID号(rsync客户端推送过来的文件所属组会被创建为gid指定的所属组)
  6. gid = root
  7. #切换目录
  8. use chroot = no
  9. #最大连接数
  10. max connections = 10
  11. #pid文件路径
  12. pid file = /var/run/rsyncd.pid
  13. #锁文件路径
  14. lock file = /var/run/rsyncd.lock
  15. #日志文件路径(可通过log format参数设置日志格式)
  16. log file = /var/run/rsyncd.log
  17. #传输日志
  18. transfer logging = yes
  19. #超时时间
  20. timeout = 900
  21. #忽略无法读取的文件
  22. ignore nonreadable = yes
  23. #忽略部分io错误
  24. ignore errors
  25. #是否只读(false就接受上传,即puhs,否则只接受下载,即pull)
  26. read only = false
  27. #下载(pull)操作时,如果没写下载哪个模块,则会列出模块
  28. list = false
  29. #允许的客户端ip或ip段(24也可写成255.255.255.0,这是网段,或子网掩码)
  30. #host allow = 10.37.129.5/24
  31. host allow = *
  32. #除了允许的ip或ip段外禁止其他ip或ip段
  33. #host deny = 0.0.0.0/32 #也可以直接写*
  34. #认证用户(客户端执行同步操作时,需要用user@ip来指定用户名,就跟ssh登录一个道理,这里写users是因为可配置多个用户,用逗号隔开即可)
  35. auth users = xiebruce
  36. #认证密码文件(后面会创建该文件,其实内容就是“用户名:密码”,一行一个用户)
  37. secrets file = /etc/rsyncd.secrets
  38. #如果用-az指定了打包压缩同步的文件,则指定这些后缀可以不压缩这些文件。
  39. # dont compress = *.gz *.tgz *.zip *.z *.Z *.rpm *.deb *.bz2
  40. ############# 自定义的传输模块2 ##################
  41. [ftpdata]
  42. #同步路径
  43. path = /data
  44. #注释
  45. comment = website
  46. #不接受的目录(该目录位于path指定的目录下)
  47. exclude = cache

可以用man查看相应的配置

  • 个别参数的详解

    use chroot = no
    如果为yes, rsync会首先进行chroot设置,将根映射在path参数路径下,对客户端而言,系统的根就是path参数指定的路径。但这样做需要root权限,并且在同步符号连接资料时只会同步名称,不会同步内容,所以我们一般设置为no。

4.2 在客户端服务器创建登录服务端的密码文件

sudo echo "123456" > /etc/rsyncd.password

4..3 在服务器端创建用户密码对

  1. sudo echo "xiebruce:123456" > /etc/rsyncd.secrets

注意:服务器端的用户密码文件是“用户名:密码”,而客户端只需要密码

4.4 修改客户端和服务端的密码文件权限

  1. 服务端
  2. sudo chmod 600 /etc/rsyncd.secrets
  3. sudo chown root:root /etc/rsyncd.secrets
  1. 客户端
  2. sudo chmod 600 /etc/rsyncd.password
  3. sudo chown root:root /etc/rsyncd.password

注意:一定要服务端和客户端都要设置

4.5 启动服务进行在客户端推数据进行测试

  1. systemctl start rsyncd
  2. systemctl enable rsyncd
 rsync -avz --partial  /data xiebruce@192.168.29.101::/data/ --password-file=/etc/rsyncd.password

5. 在客户端安装和配置sersync

5.1 配置文件如下

  1. [root@node1 sersync]# cat confxml.xml
  2. <?xml version="1.0" encoding="ISO-8859-1"?>
  3. <head version="2.5">
  4. <!-- hostip与port是针对插件的保留字段,对于同步功能没有任何作用,保留默认即可。 -->
  5. <host hostip="localhost" port="8008"></host>
  6. <!-- 是否开启debug模式 -->
  7. <debug start="false"/>
  8. <!-- 如果是xfs文件系统,则需要设置为true才能同步,rehat/REEL/CentOS/Fedora新版本默认都是xfs文件系统,可使用df -Th命令查看 -->
  9. <fileSystem xfs="true"/>
  10. <!-- 过滤器,设置为true则会对里面的exclude对应的正则匹配到的文件进行过滤,即不同步 -->
  11. <filter start="true">
  12. <!-- <exclude expression="(.*)\.svn"></exclude> -->
  13. <!-- <exclude expression="(.*)\.gz"></exclude> -->
  14. <!-- <exclude expression="^info/*"></exclude> -->
  15. <!-- <exclude expression="^static/*"></exclude> -->
  16. <exclude expression="^cache/*"></exclude>
  17. </filter>
  18. <!-- inotify是linux的内核功能,这里用于设置创建/删除/修改/移动文件时,是否视为文件改变(进而进行同步) -->
  19. <inotify>
  20. <!-- 删除一个文件是否视为文件改变(很明显我们要设置为true) -->
  21. <delete start="false"/>
  22. <!-- 创建一个文件夹是否视为文件改变(很明显我们要设置为true) -->
  23. <createFolder start="true"/>
  24. <!-- 创建一个文件是否触发文件改变事件(这里要设置false,因为创建一个文件除了有createFile事件还会有closeWrite事件,我们只要把closeWrite事件设置为true即可监控到创建 一个文件) -->
  25. <createFile start="false"/>
  26. <!-- 创建文件或修改文件后再关闭会触发该事件,比如vim打开一个文件,修改后用(:wq)保存,则会触发该事件,当然创建新文件一样会触发 -->
  27. <closeWrite start="true"/>
  28. <!-- 从别的地方移到被监控目录是否视为文件改变,毫无疑问要设置为true -->
  29. <moveFrom start="true"/>
  30. <!-- 被监控目录中的某个文件被移动到其他地方算不算文件改变?毫无疑问要设置为true -->
  31. <moveTo start="true"/>
  32. <!-- 文件属性改变了,是否视为文件改变?这个我们可以认为文件没有改,所以设置false -->
  33. <attrib start="false"/>
  34. <!-- 文件内容被修改了是否视为文件改变?感觉文件改变肯定要设置为true,但其实不用,因为这个改变有可能是vim(:w)保存,还没有关闭文件,所以保存的时候没必要同步,而关闭 的时候会触发closeWrite,所以修改的文件也是通过closeWrite来同步的 -->
  35. <modify start="false"/>
  36. </inotify>
  37. <!-- servsync的模块 -->
  38. <sersync>
  39. <!-- 指定要监控(即同步)的本地目录 -->
  40. <localpath watch="/data">
  41. <!-- ip指定同步到远程的哪个服务器,name填写远程服务器中rsync配置文件中的自定义模块名称(即中括号括起来的那个名称) -->
  42. <remote ip="192.168.29.101" name="ftpdata"/>
  43. <!-- 如果你要同步到多台服务器,继续填写即可,每个服务器一个remote标签 -->
  44. <!--<remote ip="192.168.8.40" name="tongbu"/>-->
  45. </localpath>
  46. <!-- rsync模块配置 -->
  47. <rsync>
  48. <!-- 公共参数,即我们手动执行rsync的时候要带的选项就填在这里,servsync会自动组装 -->
  49. <commonParams params="-azP"/>
  50. <!-- 密码文件及指定用户名(用户名就是rsync服务器端配置文件中的"auth user =" 指定的用户名) -->
  51. <auth start="true" users="xiebruce" passwordfile="/etc/rsyncd.password"/>
  52. <!-- 如果你rsync服务器不是默认端口873,那么就要在这里指定具体的端口,当然是默认的你也可以指定一下 -->
  53. <userDefinedPort start="false" port="873"/>
  54. <!-- rsync超时时间 -->
  55. <timeout start="false" time="100"/><!-- timeout=100 -->
  56. <!-- 是否使用ssh方式传输 -->
  57. <ssh start="false"/>
  58. </rsync>
  59. <!-- 对于失败的传输,会进行重新传送,再次失败就会写入rsync_fail_log,然后每隔一段时间(timeToExecute进行设置,单位sec)执行该脚本再次重新传送,然后清空该脚本。可以 通过path来设置日志路径。 -->
  60. <failLog path="/tmp/rsync_fail_log.sh" timeToExecute="60"/><!--default every 60mins execute once-->
  61. <!-- 定期整体同步功能,schedule表示crontab执行间隔,单位是min -->
  62. <crontab start="false" schedule="600"><!--600mins-->
  63. <!-- 同步过滤器,要开启请把start设置为true,用于 整体同步时,排除一些文件或目录,比如缓存目录可以不需要同步 -->
  64. <crontabfilter start="false">
  65. <exclude expression="*.php"></exclude>
  66. <exclude expression="info/*"></exclude>
  67. </crontabfilter>
  68. </crontab>
  69. <!-- 同步完成后,执行一个插件,name表示执行哪些插件,而这个插件必须在后边用plugin标签定义 -->
  70. <plugin start="false" name="command"/>
  71. </sersync>
  72. <!-- 定义一个command插件(command插件类型的一种,另外的类型有socket,refreshCDN,http(目前由于兼容性问题,http插件暂时不能用)) -->
  73. <plugin name="command">
  74. <!-- command插件其实就是“.sh”结尾的shell脚本文件,prefix和subffix用于拼成一条执行shell命令的命令 -->
  75. <param prefix="/bin/sh" suffix="" ignoreError="true"/> <!--prefix /data/wwwroot/mmm.sh suffix-->
  76. <!-- 该脚本做操作时要过滤的文件正则 -->
  77. <filter start="false">
  78. <include expression="(.*)\.php"/>
  79. <include expression="(.*)\.sh"/>
  80. </filter>
  81. </plugin>
  82. <!-- 定义一个socket插件,注意插件定义了但没有调用的话,是不会被执行的 -->
  83. <plugin name="socket">
  84. <localpath watch="/data">
  85. <deshost ip="192.168.138.20" port="8009"/>
  86. </localpath>
  87. </plugin>
  88. <!-- 定义一个refreshCDN插件,主要用于同步数据到cdn -->
  89. <plugin name="refreshCDN">
  90. <localpath watch="/data0/htdocs/cms.xoyo.com/site/">
  91. <cdninfo domainname="ccms.chinacache.com" port="80" username="xxxx" passwd="xxxx"/>
  92. <sendurl base="http://pic.xoyo.com/cms"/>
  93. <regexurl regex="false" match="cms.xoyo.com/site([/a-zA-Z0-9]*).xoyo.com/images"/>
  94. </localpath>
  95. </plugin>
  96. </head>

5.2 客户端启动

sersync2 -o /usr/local/sersync/confxml.xml -d

现在,你可以测试一下在100服务器的同步目录上添加文件,修改文件内容,看101服务器是否会修改.

解释一下这个参数配置

前面配置文件里的注释也说了,由于各种原因(如网络很差或延迟非常大)可能会有传输失败的情况,那为什么记录传输失败的文件不叫.log,而叫.sh呢?
下图就是我传输失败后自动成的/tmp/rsync_fail_log.sh文件的内容:

6. rsync+Lsyncd 实时同步配置

6.1 介绍

Lsyncd是一个辅助文件同步工具。它通过监听系统的文件变化事件,调用rsync进行同步。注意“辅助”二字,辅助的意思是:同步文件本身并不是由lsyncd来实现,它只负责监测哪些文件改变了,进而调用rsync来完成同步,真正同步文件的是rsync,如果你不知道什么是rsync,请查看使用sersync +rsync进行实时文件同步中的rsync部分。

6.2 Lsyncd的三种同步模式

  • default.rsync
  • default.rsyncssh
  • default.direct

为了方便,我们直接把它们称为rsync、rsyncssh、direct

6.2.1 rsync同步模式

  • rsync无法知道“什么时候同步”,因为rsync只有执行同步命令的时候,才会去扫描文件判断哪些文件被修改了,只能建立一个定时任务,每隔一定的时间(比如5分钟,10分钟等等)去执行一次同步,这样虽然能同步,但却“不实时”。
  • lsyncd就可以监听文件的修改,换句话说,某个文件修改了,lsyncd会得到通知(原理是使用linux系统的inotify/fsevents功能),得到通知之后,再去调用rsync把修改的文件进行同步(即组装一句rsync同步语句并执行),达到“实时同步”的效果。
  • lsyncd调用rsync同步命令的时候,会用rsync的--include-from=FILE之类的选项来指定要同步哪些文件,这样可以达到“减少rsync扫描文件带来的延时和性能损耗”。
  • 为什么这么说呢?因为如果让rsync自己去查询哪些文件改变了,需要消耗较多的时间和服务器资源,试想一下,在100万个文件中,有一个文件添加了一个英文的句号.,如果没有lsyncd告诉rsync改变的是这个文件,那rsync就要去扫描100万个文件来找出这个仅仅多了一个.的文件,虽然rsync的查找效率很高,但这个查找是非常没有必要的,这就是为什么lsyncd能“减少rsync扫描文件带来的延时和性能损耗”。

rsync配置如上
环境如上

6.1 安装Lsyncd

  1. rpm -ivh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm # 安装 epel 源
  2. yum -y install lsyncd rsync # 安装
  3. vim /etc/lsyncd.conf # 配置

6.2 配置文件

  1. -- 由于该配置文件实际上是lua语言的语法,所以写注释要用--,--是lua语言的注释符号
  2. -- Lsyncd本身的配置
  3. settings {
  4. -- 指定日志文件位置
  5. logfile = "/var/log/lsyncd/lsyncd.log",
  6. -- 指定状态文件位置
  7. statusFile = "/var/log/lsyncd/lsyncd.status",
  8. -- inotify事件模式,什么事件才同步,CloseWrite表示文件关闭的时候同步(创建文件,修改文件后保存都会触发CloseWrite事件)
  9. inotifyMode = "CloseWrite",
  10. -- 最大同步进程数(default.rsyncssh模式,则必须设置为1,这就是rsyncssh模式的缺点了,如果是default.rsync模式则可以设置大于1,这样会有多个同步进程,速度更快)
  11. maxProcesses = 8,
  12. -- maxProcesses = 1,
  13. -- 配合下面的delay选项使用,delay单位是秒,当delay时间到了,不管maxDelays设置多少,都会同步,同样,当maxDelays达到了设定值,不管是否到delay时间,都会同步,即两个选项有一个满足即会触发同步,为了实时同>步,我们一般设置为1,表示即使只有一个文件改变也同步
  14. maxDelays = 1,
  15. -- 是否以后台的方式运行,注意它是nodaemon,所以是双重否定,如果填false,意思就是“不要不后台运行”(即后台运行),非后台运行一般用于调试,把rsync的verbose也设置为true,这样会把同步的细节输出到控制台,方便调试
  16. nodaemon = false,
  17. }
  18. ---- 同步配置default.rsync模式(比如配置从哪同步到哪,要忽略哪些文件,多久同步一次等),可以有多个sync模块,每个模块用于设置一台目标机器
  19. sync {
  20. -- 有default.rsync/default.direct/default.rsyncssh三种模式,我们默认都用default.rsync即可。
  21. default.rsync,
  22. -- 同步源目录(本机某个目录)
  23. source = "/data/",
  24. -- 同步目标地址,不同同步模式有不同写法,由于绝大多数情况都采用rsync同步,所以这里写的是rsync的同步地址
  25. target = "xiebruce@10.1.1.135::ftpdata",
  26. -- 默认true,允许删除目录服务器中的某些文件(即删除“那些在源服务器中不存在的文件”),可选值有: true/false/startup/running,startup就是只在启动lsyncd服务的时候判断目标服务器中有哪些文件在源服务器中没有,然后把这些文件删除,但启动之后如果目标服务器又新增了文件,这些文件即使在源服务器不存在,也不会被删除;而running与startup正好相反,是在启动的时候不会删除,启动之后会删除,true=running+startup,false相当于running和startup都不做。
  27. delete = false,
  28. -- 哪些文件不同步(可用正则))
  29. -- exclude = {
  30. -- ''.**'',
  31. -- ''.git/**'',
  32. -- ''*.bak'',
  33. -- ''*.tmp'',
  34. -- ''runtime/**'',
  35. -- ''cache/**''
  36. -- },
  37. -- 与上边的maxDelays配合,maxDelays是累计事件数(单位:个),delay是时间(单位:秒),这两个只要有一个符合条件就会同步一次,但为了确保实时同步,maxDelays我们一般设置为1,也就是只要有一个文件变化事件,就会同步一次,而delay是比较大的,默认是15。当然,假如我们把maxDelays设置为100,那可能15秒到了也没有达到100个文件变化,但由于到达时间了,它也会同步。
  38. delay = 15,
  39. -- 当init = false时只同步进程启动以后发生改动事件的文件,原有的目录即使有差异也不会同步,如果为true,则启动后如果源目录与目标目录的文件有差异,就会同步,我们当然要设置为true,默认为true,所以这个设置可以不写,写在这里是为了解释它。
  40. -- init = false,
  41. -- rsync的配置(这是default.rsync模式,如果是default.rsyncssh模式,该模块的配置会有所不同)
  42. rsync = {
  43. -- rsync可执行文件的绝对路径
  44. binary = "/usr/bin/rsync",
  45. -- 密码文件路径(default.rsyncssh模式不需要该项)
  46. password_file = "/etc/rsyncd.password",
  47. -- 打包后再同步(注意,打包不等于压缩,打包即可以压缩也可以不压缩)
  48. archive = true,
  49. -- 压缩后再同步
  50. compress = false,
  51. -- 输出同步信息(由于是后台执行,所以没必要输出,如果非后台执行可以设置为true,非后台执行主要用于调试)
  52. verbose = false,
  53. -- 由于rsync有非常多的选项(请自己rsync --help查看),部分非主要选项可以用_extra的方式指定,双引号引住,逗号分隔(bwlimit中的bw是bandwith,即带宽,整个意思是带宽限制,omit-link-times忽略符号链接的修改时间)
  54. _extra = {"--bwlimit=200", "--omit-link-times"}
  55. }
  56. }

7. 同时同步到多台机

格式如下,每台目标服务器一个sync模块即可,每个sync模块都像上边说的那样写就行,其实就只是ip不同,其他都一样:

  1. settings {
  2. logfile = "/var/log/lsyncd/lsyncd.log",
  3. inotifyMode = "CloseWrite or Modify",
  4. -- statusFile = "/var/log/lsyncd/lsyncd.status",
  5. }
  6. -- B服务器配置
  7. sync {
  8. default.rsync,
  9. source = "/etc/nginx/",
  10. target = "rsync://rsync@192.168.1.6:1873/nginx/",
  11. exclude = { ".*", "*.tmp", "*.swp", "*.bak", "*.log", "*.swx", "*~", "sets/config.json", "listen_local_*" },
  12. delay = 2,
  13. init = false,
  14. rsync = {
  15. password_file = "/etc/rsyncd.passwd",
  16. archive = true,
  17. compress = true,
  18. verbose = true,
  19. checksum = true,
  20. ignore_times = true
  21. }
  22. }
  23. -- C服务器配置
  24. sync {
  25. default.rsync,
  26. source = "/data/web/",
  27. target = "rsync://rsync@192.168.1.11:1873/web/",
  28. exclude = { ".*", "*.tmp", "*.swp", "*.bak", "*.log", "*.out", "*/logs/*", "*.swx", "*~" },
  29. delay = 120,
  30. init = false,
  31. rsync = {
  32. password_file = "/etc/rsyncd.passwd",
  33. archive = true,
  34. compress = true,
  35. verbose = true,
  36. checksum = true,
  37. ignore_times = true
  38. }
  39. }
  40. -- D服务器配置
  41. sync {
  42. default.rsync,
  43. source = "/data/script/",
  44. target = "rsync://rsync@192.168.1.100:1873/script/",
  45. exclude = { ".*", "*.tmp", "*.swp", "*.bak", "*.log", "*.out", "*/logs/*", "*.swx", "*~" },
  46. delay = 2,
  47. init = false,
  48. rsync = {
  49. password_file = "/etc/rsyncd.passwd",
  50. archive = true,
  51. compress = true,
  52. verbose = true,
  53. checksum = true,
  54. ignore_times = true
  55. }
  56. }

详情介绍请见如下连接

CentOS7部署lsyncd+rsync实现服务器文件实时同步 - 系统运维 - 亿速云