【keepalived + rsync +inotify 】實現(xiàn)真正的高效數(shù)據(jù)實時同步

實驗背景

A文件服務(wù)器的/opt/dataA 和 B文件服務(wù)器的/opt/dataB目錄實時同步

A正常時,A為主,B為備,B去實時同步A

A掛了時,B為主,待A起來后,A為備,去實時同步B,并且能補(bǔ)上掛掉期間B增加的數(shù)據(jù),反之亦然

keepalived + rsync +inotify 實現(xiàn)真正的高效數(shù)據(jù)實時同步

https://fandenggui.com/post/keepalived-rsync-inotify.html

真正的inotify+rsync實時同步 徹底告別同步慢

http://www.ttlsa.com/web/let-infotify-rsync-fast

一、實驗環(huán)境

操作系統(tǒng):CentOS7.2

serverA: 192.168.1.102

serverB: 192.168.1.103

vip: ? ? ? ? ?192.168.1.120

二、軟件安裝

在 serverA和serverB上

# yum ?-y install ?epel-release

# yum ?-y install ?keepalived ?inotity-tools? rsync ?httpd

# systemctl enable ? httpd ?keepalived

rsync-inotify.service?會由后面的Keepalived程序根據(jù)主備角色變化情況,自動的運(yùn)行和關(guān)閉

設(shè)置selinux為寬松模式

# setenforce 0

# sed -i 's/^SELINUX=.*/SELINUX=permissive/g' ? /etc/selinux/config

關(guān)閉防火墻

# systemctl stop ? ? firewalld

# systemctl disable firewalld

主機(jī)互信

我們同步采用rsync的ssh模式,需要讓serverA和?serverB 相互互信

三、主機(jī)配置

serverA?

# vim ?/opt/data_realtime_rsync.sh

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

#!/bin/bash

# File name:data_realtime_sync.sh

# File path: /opt/data_realtime_sync.sh

src_dir="/opt/dataA"

dest_dir="/opt/dataB"

src_ip="192.168.1.102"

dest_ip="192.168.1.103"

. /etc/init.d/functions

cd ${src_dir}

inotifywait -mrq -e modify,attrib,close_write,move,create,delete --format '%e %w%f' ./ |

while read file;do

? ? INO_EVENT=$(echo $file | awk '{print $1}') ? ? ?

? ? INO_FILE=$(echo $file ?| awk '{print $2}') ? ? ?

? ? if [[ $INO_EVENT =~ 'CREATE' ]] || [[ $INO_EVENT =~ 'MODIFY' ]] || [[ $INO_EVENT =~ 'CLOSE_WRITE' ]] || [[ $INO_EVENT =~ 'MOVED_TO' ]];then

? ? ? ? for ip in ${dest_ip};do

? ? ? ? ? ? rsync -avzcR -e ssh ?$(dirname ${INO_FILE}) root@${dest_ip}:${dest_dir}

? ? ? ? done

? ? fi

? ? if [[ $INO_EVENT =~ 'ATTRIB' ]];then

? ? ? ? if [ ! -d "$INO_FILE" ];then

? ? ? ? ? ? for ip in ${dest_ip};do

? ? ? ? ? ? ? ? rsync -avzcR ?-e ssh ?$(dirname ${INO_FILE}) root@${dest_ip}:${dest_dir}

? ? ? ? ? ? done

? ? ? ? fi

? ? fi

? ? if [[ $INO_EVENT =~ 'DELETE' ]] || [[ $INO_EVENT =~ 'MOVED_FROM' ]];then

? ? ? ? for ip in ${dest_ip};do

? ? ? ? ? ? rsync -avzcR --delete ?-e ssh ?$(dirname ${INO_FILE}) root@${dest_ip}:${dest_dir}

? ? ? ? done

? ? fi

done

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

# vim ?/etc/keepalived/keepalived.conf

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

! Configuration File for keepalived

global_defs {

? ?router_id LVS_DEVEL

}

vrrp_script check_httpd {?

? ? script "/etc/keepalived/check_httpd.sh"?

? ? interval 5 ? ??

} ??

vrrp_instance VI_1 {

? ? state BACKUP

? ? interface eno16777736

? ? virtual_router_id 100

? ? priority 100

? ? advert_int 1

? ? nopreempt

? ? authentication {

? ? ? ? auth_type PASS

? ? ? ? auth_pass 1111

? ? }

? ? track_script { ??

? ? ? check_httpd

? ? } ??

? ? virtual_ipaddress {

? ? ? ? 192.168.1.120

? ? }

notify_master "/etc/keepalived/rsync-inotify.sh start"

notify_backup "/etc/keepalived/rsync-inotify.sh stop"

notify_stop ? "/etc/keepalived/rsync-inotify.sh send"

}

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

# vim ?/etc/keepalived/check_httpd.sh

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

#!/bin/sh

#

httpd_status1=$(ps -C httpd --no-heading|wc -l)

if [ "${httpd_status1}" = "0" ]; then

? systemctl start httpd.service

? sleep 5

? httpd_status2=$(ps -C httpd --no-heading|wc -l)

? if [ "${httpd_status2}" = "0" ]; then

? ? systemctl stop keepalived.service

? fi

fi

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

# vim ?/etc/keepalived/rsync-inotify.sh

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

#!/bin/bash

case "$1" in

? start )

? ? systemctl start rsync-inotity.service

? ;;

? stop )

? ? systemctl stop rsync-inotity.service

? ;;

? restart )

? ? systemctl restart rsync-inotity.service

? ;;

? send )

? ? echo "Keepalived stoppd in 192.168.1.102" | mail -s "Alarm Mail" ?example@qq.com

? ;;

? * )

? ? echo "Usage:$0 start|stop|restart|send"

? ;;

esac

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

# vim ?/etc/systemd/system/rsync-inotity.service

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

[Unit]

Description=File instant rsync script

[Service]

ExecStart=/usr/bin/nohup /opt/data_realtime_rsync.sh ?&

[Install]

WantedBy=multi-user.target

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

# vim ?/etc/full-rsync.conf

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

src_dir="/opt/dataA"

dest_dir="/opt/dataB"

src_ip="192.168.1.102"

dest_ip="192.168.1.103"

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

# vim /etc/systemd/system/full-rsync.service

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

[Unit]

Description=Full rsync script

After=network.target sshd.service

Wants=sshd.service

[Service]

EnvironmentFile=/etc/full-rsync.conf

ExecStart=/usr/bin/rsync -avz --delete ?-e ssh ?root@${dest_ip}:${dest_dir}/ ?${src_dir}

Type=oneshot

[Install]

WantedBy=multi-user.target

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

serverB

# vim ?/opt/data_realtime_rsync.sh

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

#!/bin/bash

# File name:data_realtime_sync.sh

# File path: /opt/data_realtime_sync.sh

src_dir="/opt/dataB"

dest_dir="/opt/dataA"

src_ip="192.168.1.103"

dest_ip="192.168.1.102"

. /etc/init.d/functions

cd ${src_dir}

inotifywait -mrq -e modify,attrib,close_write,move,create,delete --format '%e %w%f' ./ |

while read file;do

? ? INO_EVENT=$(echo $file | awk '{print $1}') ? ? ?

? ? INO_FILE=$(echo $file ?| awk '{print $2}') ? ? ?

? ? if [[ $INO_EVENT =~ 'CREATE' ]] || [[ $INO_EVENT =~ 'MODIFY' ]] || [[ $INO_EVENT =~ 'CLOSE_WRITE' ]] || [[ $INO_EVENT =~ 'MOVED_TO' ]];then

? ? ? ? for ip in ${dest_ip};do

? ? ? ? ? ? rsync -avzcR ?-e ?ssh ?$(dirname ${INO_FILE}) root@${dest_ip}:${dest_dir}

? ? ? ? done

? ? fi

? ? if [[ $INO_EVENT =~ 'ATTRIB' ]];then

? ? ? ? if [ ! -d "$INO_FILE" ];then

? ? ? ? ? ? for ip in ${dest_ip};do

? ? ? ? ? ? ? ? rsync -avzcR -e ?ssh ?$(dirname ${INO_FILE}) root@${dest_ip}:${dest_dir}

? ? ? ? ? ? done

? ? ? ? fi

? ? fi

? ? if [[ $INO_EVENT =~ 'DELETE' ]] || [[ $INO_EVENT =~ 'MOVED_FROM' ]];then

? ? ? ? for ip in ${dest_ip};do

? ? ? ? ? ? rsync -avzcR --delete ?-e ssh ?$(dirname ${INO_FILE}) root@${dest_ip}:${dest_dir}

? ? ? ? done

? ? fi

done

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

# vim ?/etc/keepalived/keepalived.conf

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

! Configuration File for keepalived

global_defs {

? ?router_id LVS_DEVEL

}

vrrp_script check_httpd {?

? ? script "/etc/keepalived/check_httpd.sh"?

? ? interval 5 ? ??

} ??

vrrp_instance VI_1 {

? ? state BACKUP

? ? interface eno16777736

? ? virtual_router_id 90

? ? priority 100

? ? advert_int 1

? ? nopreempt

? ? authentication {

? ? ? ? auth_type PASS

? ? ? ? auth_pass 1111

? ? }

? ? track_script { ??

? ? ? check_httpd

? ? } ??

? ? virtual_ipaddress {

? ? ? ? 192.168.1.120

? ? }

notify_master "/etc/keepalived/rsync-inotify.sh start"

notify_backup "/etc/keepalived/rsync-inotify.sh stop"

notify_stop ? "/etc/keepalived/rsync-inotify.sh send"

}

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

# vim ?/etc/keepalived/check_httpd.sh

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

#!/bin/sh

#

httpd_status1=$(ps -C httpd --no-heading|wc -l)

if [ "${httpd_status1}" = "0" ]; then

? systemctl start httpd.service

? sleep 5

? httpd_status2=$(ps -C httpd --no-heading|wc -l)

? if [ "${httpd_status2}" = "0" ]; then

? ? systemctl stop keepalived.service

? fi

fi

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

# vim ?/etc/keepalived/rsync-inotify.sh


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

#!/bin/bash

case "$1" in

? start )

? ? systemctl start rsync-inotity.service

? ;;

? stop )

? ? systemctl stop rsync-inotity.service

? ;;

? restart )

? ? systemctl restart rsync-inotity.service

? ;;

? send )

? ? echo "Keepalived stoppd in 192.168.1.102" | mail -s "Alarm Mail" ??example@qq.com

? ;;

? * )

? ? echo "Usage:$0 start|stop|restart|send"

? ;;

esac

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

# vim ?/etc/systemd/system/rsync-inotity.service

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

[Unit]

Description=File instant rsync script

[Service]

ExecStart=/usr/bin/nohup /opt/data_realtime_rsync.sh ?&

[Install]

WantedBy=multi-user.target

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

# vim ?/etc/full-rsync.conf

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

src_dir="/opt/dataB"

dest_dir="/opt/dataA"

src_ip="192.168.1.103"

dest_ip="192.168.1.102"

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

# vim /etc/systemd/system/full-rsync.service

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

[Unit]

Description=Full rsync script

After=network.target sshd.service

Wants=sshd.service

[Service]

EnvironmentFile=/etc/full-rsync.conf

ExecStart=/usr/bin/rsync -avz --delete ?-e ssh ?root@${dest_ip}:${dest_dir}/ ?${src_dir}

Type=oneshot

[Install]

WantedBy=multi-user.target

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

四、測試

# systemctl ?status httpd

# systemctl ?status keepalived

# systemctl ?status ?rsync-inotity

五、全量同步

手動方式

A 全量同步B

# ?vim ?full_rsync_from_B_to_A.sh

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

#!/bin/bash

src_dir="/opt/dataA"

dest_dir="/opt/dataB"

src_ip="192.168.1.102"

dest_ip="192.168.1.103"

rsync -avz?--delete ?-e ssh ?root@${dest_ip}:${dest_dir}/ ?${src_dir}/

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

B 全量同步A

# vim full_rsync_from_A_to_B.sh

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

#!/bin/bash

src_dir="/opt/dataB"

dest_dir="/opt/dataA"

src_ip="192.168.1.103"

dest_ip="192.168.1.102"

rsync -avz?--delete ?-e ssh ?root@${dest_ip}:${dest_dir}/ ?${src_dir}/

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

系統(tǒng)服務(wù)

#?systemctl ?daemon-reload

# systemctl ?start? full-rsync

# ?systemctl ?status ?full-rsync

通過/etc/rc.d/rc.local 開機(jī)執(zhí)行

# vim?/etc/rc.d/rc.local

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

# Full rsync?

src_dir="/xxx"

dest_dir="/xxx"

src_ip="xx.xx.xx.xx"

dest_ip="xx.xx.xx.xx"

rsync -avz --delete ?-e ssh ?root@${dest_ip}:${dest_dir}/ ?${src_dir}

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

# chmod +x ?/etc/rc.d/rc.local

六、優(yōu)化inotity

如果不進(jìn)行優(yōu)化,遇到瓶頸會有如下錯誤提示:

Failed to watch /your/path; upper limit on inotify watches reached!

Please increase the amount of inotify watches allowed per user via `/proc/sys/fs/inotify/max_user_watches'.

主要優(yōu)化?max_user_watches?及?max_queued_events?

具體大小可以等于當(dāng)前數(shù)據(jù)盤的 inode最大值

這里以1T數(shù)據(jù)盤為例:

# echo "67108864" > /proc/sys/fs/inotify/max_user_watches

# echo "67108864" > /proc/sys/fs/inotify/max_queued_events

將下面參數(shù)寫入 /etc/sysctl.conf,永久生效

# vim ?

/etc/sysctl.conf

fs.inotify.max_user_watches = 67108864

fs.inotify.max_queued_events = 67108864

七、參考

keepalived + rsync +inotify 實現(xiàn)真正的高效數(shù)據(jù)實時同步

https://fandenggui.com/post/keepalived-rsync-inotify.html

真正的inotify+rsync實時同步 徹底告別同步慢

http://www.ttlsa.com/web/let-infotify-rsync-fast


【Keepalived 】keepalived check and notify scripts

大家知道keepalived會有四種狀態(tài)的變化,每種狀態(tài)變化時,都可以調(diào)用一個腳本

當(dāng)進(jìn)入Master狀態(tài)時會呼叫notify_master

當(dāng)進(jìn)入Backup狀態(tài)時會呼叫notify_backup

當(dāng)發(fā)現(xiàn)異常情況時進(jìn)入Fault狀態(tài)呼叫notify_fault

當(dāng)Keepalived程序終止時則呼叫notify_stop

進(jìn)入Master和Backup這兩種狀態(tài)很容易理解了,就是分別變?yōu)橹骱蛷?/p>

進(jìn)入Fault,簡單的說就是keepalived發(fā)現(xiàn)自己有問題了,不能能再去參與Master競選了,你得修好他才行。

進(jìn)入這種狀態(tài)一般是keepalived自身出問題了,或者keepalived檢測的網(wǎng)卡出問題不通了,再或者就是我們自己寫的檢測業(yè)務(wù)的腳本返回錯誤

進(jìn)入Stop 這個就容易理解了,執(zhí)行service keepalived stop 或者 systemctl stop keepalived ?就會進(jìn)入這個狀態(tài)。

設(shè)置selinux為寬松模式

# setenforce 0

# sed -i 's/^SELINUX=.*/SELINUX=permissive/g' ? /etc/selinux/config

CentOS防火墻默認(rèn)是不允許keepalived使用?vrrp的組播。

如果不開啟組播ip,keepalived雙機(jī)不能實現(xiàn)熱備的效果,只能實現(xiàn)負(fù)載的效果,即虛擬ip不能實現(xiàn)漂移?。

Check that the multicast IP and protocol for VRRP are allowed in the firewall on both servers.?

For firewalld:

添加規(guī)則

# firewall-cmd --direct --permanent--add-rule?ipv4 filterINPUT ? ??0 ??? --in-interface eth0? ?--destination?224.0.0.18?--protocol vrrp -j ACCEPT

# firewall-cmd --direct --permanent--add-ruleipv4 filterOUTPUT?0 ? ?--out-interface eth0? --destination?224.0.0.18?--protocol vrrp -j ACCEPT

# firewall-cmd --reload

刪除規(guī)則

# firewall-cmd --direct --permanent--remove-ruleipv4 filter INPUT ? ??0 ??? --in-interface eth0? ?--destination?224.0.0.18?--protocol vrrp -j ACCEPT

# firewall-cmd --direct --permanent--remove-rule?ipv4 filter ?OUTPUT?0 ? ?--out-interface eth0? --destination?224.0.0.18?--protocol vrrp -j ACCEPT

# firewall-cmd --reload

For iptables:

添加規(guī)則

# iptables?-A?INPUT?-p?vrrp?-j?ACCEPT

# iptables?-A?OUTPUT?-p?vrrp?-j?ACCEPT

# service iptables save

刪除規(guī)則

# iptables ?-D ?INPUT?-p?vrrp?-j?ACCEPT

# iptables ?-D?OUTPUT?-p?vrrp?-j?ACCEPT

# service iptables save

keepalived基本應(yīng)用解析

http://blog.51cto.com/pangge/1301878

keepalived官方文檔

http://www.keepalived.org/doc/introduction.html

使用keepalived實現(xiàn)redis的故障切換

http://peiqiang.net/2014/11/21/keepalived-and-redis.html

Kamailio High Availability Done Right with Keepalived

http://blog.unicsolution.com/2015/01/kamailio-high-availability-with.html

Keepalived Check and Notify Scripts

https://tobrunet.ch/keepalived-check-and-notify-scripts

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容