如何在Linux服务器中实现数据实时同步及备份

如何在Linux服务器中实现数据实时同步及备份,第1张

科技时代,任何行业都离不开数据的分析以及统筹,如果掌握了最关键的数据及技术,那成功就指日可待,所以数据对于一个企业来说,就是最无形的财富,而一个企业的数据基本都有服务器保存及管理着,如何保证数据安全,实现数据同步及备份?诚恺科技小编就同大家一起来看看在Linux服务器中利用rsync配合inotify实现数据实时同步及备份的方法。

rsync:可以镜像保存整个目录树和文件系统。可以很容易做到保持原来文件的权限、时间、软硬链接等等。第一次同步时 rsync 会复制全部内容,但在下一次只传输修改过的文件。

方案:起初用rsync进行数据备份是利用计划任务,定时执行一下命令实现rsync的同步,但最近开发这边修改比较频繁,看来需要实时同步备份来完善备份机制!所以需要利用inotify触发器来改善!达到一旦指定的位置有了新的变动就将其同步!

环境:

CentOS 6.4 64位

rsync-3.0.9

inotify-tools-3.14

说明:

10.10.1.6 (rsync+inotify)----------网站程序(/data0/htdocs/)

10.10.1.9 (rsync)------------------网站程序备份(/data0/htdocs/)

目的:

实现10.10.1.6的/data0/htdocs/目录下发生任何变动都将实时同步到10.10.1.9的/data0/htdocs/上(另,这两台都跑有keepalived+nginx,来实现出现故障自动切换的容灾,详细配置会在后面补上)

一、web服务器10.10.1.6 (rsync+inotify)

1、准备软件包

2、安装Rsync

1)、1234 tar-zxvf rsync-3.0.9.tar.gz

2)、cdrsync-3.0.9

3)、./configure--prefix=/usr/local/rsync

4)、makemakeinstall

建立密码认证文件

[root@ftp ~]# echo "111111">/etc/rsyncd/rsyncd.secrets建立密码认证文件

*其中111111可以自己设置密码,rsyncd.secrets名字也可以自己设置;

权限:要将/etc/rsyncd/rsyncd.secrets设置为root拥有, 且权限为600。

# chmod 600 /etc/rsyncd/rsyncd.secrets

3、安装inotify

1)、1234 tar-zxvf inotify-tools-3.14.tar.gz

2)、cdinotify-tools-3.14

3)、./configure--prefix=/usr/local/inotify

4)、makemakeinstall

4、创建rsync复制脚本

此项功能主要是将ftp端的目录/data0/htdocs/里的内容,如果修改了(无论是添加、修改、删除文件)能够通过inotify监控到,并通过rsync实时的同步给10.10.1.9的/data0/htdocs里,下面是通过shell脚本实现的。

[root@web ~]# vim /root/shell/rsync.sh

[root@web ~]# chmod u+x /root/shell/rsync.sh

[root@web ~]# setsid /root/shell/rsync.sh &

#后台运行脚本,关闭shell终端继续后台运行

rsync.sh脚本加入开机启动项

# echo "/root/shell/rsync.sh" >>/etc/rc.local

防火墙开启rsync端口:873

添加:

iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 873 -jACCEPT

重启:

# /etc/init.d/iptables restart

二、备份服务器10.10.1.9(rsync)

1、准备工作

创建备份目录:

# mkdir /data0/htdocs

2、安装rsync(备份主机只安装rsync)

1)、1234 tar-zxvf rsync-3.0.9.tar.gz

2)、cdrsync-3.0.9

3)、./configure--prefix=/usr/local/rsync

4)、makemakeinstall

3、建立用户与密码认证文件

[root@backup ~]# echo "root:111111" >/etc/ rsyncd/rsyncd.secrets

[root@backup ~]# less /etc/rsyncd/rsyncd.secrets

root:111111

注意:

请记住,在10.10.1.6端建立的密码文件,只有密码,没有用户名;而在10.10.1.9里建立的密码文件,用户名与密码都有。

权限:要将/etc/rsyncd/rsyncd.secrets设置为root拥有, 且权限为600。

#chmod 600 /etc/rsyncd/rsyncd.secrets

4、建立rsync配置文件

[root@backup ~]# vim /etc/rsyncd/rsyncd.conf

启动rsync服务

# /usr/local/rsync/bin/rsync --daemon --config=/etc/rsyncd.conf

# ps -ef |grep rsync

Rsync服务加入开机启动项

# echo "/usr/local/rsync/bin/rsync --daemon --config=/etc/rsyncd.conf" >>/etc/rc.local

防火墙开启rsync端口:873

添加:

iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 873 -jACCEPT

重启:

# /etc/init.d/iptables restart

完成,其实这个时候数据已经同步了!

测试一下:

由于/data0/htdocs/下涉及到一些公司信息,所以就以/data0/htdocs/tmp/为例

主机名可以区别是两台机器,里面的内容完全一直,连文件的属性都一样

再对里面修改一下试试,创建一个文件,然后删除user目录试试

这个我们期末考试考过。 inotify只能监控单层目录变化,不能监控子目录中的变化情况。 如果需要监控子目录,需要在调用inotify_add_watch(int fd, char *dir, int mask):int建立监控时,递归建立子目录的监控,伪代码如下 void addwatch(int fd,...

Linux内核: 接受输入设备的中断,并将原始事件的数据写入设备节点中设备接电,作为内核与 IMS 的桥梁,将原始事   件的数据暴露给用户空间,以便 IMS 可以从中读取事件;

InputManagerService: 一个 Android 系统服务,分为 Java 层和 Native 层两部分,Java 层负责与 WMS 通信,而 Native 层则是 InputReader 和 InputDispatcher 两个输入系统关键组件的运行容器;

EventHub: 直接访问所有的设备节点,通过一个名为 getEvents() 的函数将所有输入系统相关的待处理的底层事件返回给使用者,包括原始输入事件,设备节点的增删等;

InputReader: IMS 中的关键组件之一,它运行在一个独立的线程中,负责管理输入设备的列表和配置,以及进行输入事件的加工处理,它通过其线程循环不断地通过 getEvents() 函数从 EventHub 中将事件取出并进行处理,对于设备节点的增删事件,它会更新输入设备列表与配置;对于原始输入事件,InputReader对其进行翻译,组装,封装为包含更多信息,更多可读性的输入事件,然后交给InputDispatcher进行派发

InputReaderPolicy: 为 InputReader 的事件加工处理提供一些策略配置

InputDispatcher: 是 IMS 中的另一个关键组件,运行于一个独立的线程中,InputDispatcher 中保管来自 WMS 的所有窗口的信息,收到 InputReader 的输入事件后,会在其保管的窗口中寻找合适的窗口,并将事件派发给此窗口;

InputDispatcherPolicy: 为 InputDispatcher 的派发过程提供策略控制,例如 HOME 键被 InputDispatcherPolicy 截取到 PhoneWindowManager 中处理,并阻止窗口收到 HOME 键按下的事件;

WindowManagerService: 它并不是输入系统的一员,新建窗口时,WMS 为新窗口和 IMS 创建了事件传递所用的通道,会将窗口的可点击区域,焦点窗口等信息实时更新到 IMS 的 InputDispatcher 中,使得 InputDispatcher 可以正确将事件派发到指定窗口;

ViewRootImpl: 对某些窗口,如壁纸窗口,SurfaceView 的窗口来说,窗口就是输入事件派发的终点,而对其他的如Activity,对话框等使用了 Android 控件系统的窗口来说,输入事件的终点是控件;

1. 创建新的IMS对象

SystemServer->ServerThread.run()

—>com_android_server_input_InputManagerService.cpp —>nativeInit()

创建了 NativeInputManager 对象,该对象实现了 InputReaderPolicyInterface 与 InputDispatcherPolicyInterface 接口,创建 EventHub 和 InputManager,InputManager 创建了 InputReader 与 InputDispatcher 以及 InputReaderThread 与 InputDispatcherThread

2.调用IMS对象的start函数完成启动

InputReader.cpp —>InputReaderThread::threadLoop()

分三步:

1.首先从 EventHub 抽取未处理的时间列表,一类是从设备节点读取的原始输入事件,另一类则是输入设备可用性变化事件,简称设备事件;

2.processEventsLocked 对事件进行处理,对于设备事件,此函数对根据设备的可用性加载或移除设备对应的配置信息,对原始输入事件,则在进行转译,封装与加工后将结果暂存到 mQueuedListener;

3.所有事件处理完毕后,调用 mQueuedListener.flush 将所有暂存的输入事件一次性地交给InputDispatcher。

1.设备节点监听的建立

通过 INotify 与 Epoll 机制建立起对设备节点增删事件以及可读状态的监听

EventHub.cpp:EventHub

2.getEvents

使用 Epoll 的核心是 mPendingEventItems 数组,它是一个事件池,getEvents 包含了原始输入事件读取,输入设备加载/卸载等 *** 作。

3.输入设备管理

每个输入设备在 dev/input/ 下有一个设备节点,设备节点包含输入设备的所有信息,EventHub 负责在设备节点可用时加载并维护这些信息,并在设备节点被删除时将其移除,名为 Device 的私有结构体保存。

4.原始输入事件的监听与读取

当设备的原始输入事件到来之时,getevents 函数将会获得一个 Epoll 事件,然后根据 Epoll 事件读取文件描述符的原始输入事件,将其填充到 RawEvents 结构体并放入 buffer 中被调用者取走。

1.原始输入事件的加工

InputReader:processEventsLocked

—>inputReader:processEventsForDeviceLocked

—> InputReader:InputDevice::process

InputDevice 描述一个输入设备,是一个存储输入设备信息的类

InputMapper 是 InputReader 中实际进行原始输入事件加工的场所

2.InputDevice 与 InputMapper

inputDevice 创建 InputReader:addDeviceLocked

—> InputReader:createDeviceLocked

3.keyboard 类型事件的加工处理

(1)keyboardInputMapper 配置(屏幕旋转状态)

(2)键盘扫描码与虚拟键值

扫描码是硬件实现,虚拟键值是 *** 作系统实现

(3)扫描码到虚拟键值的映射

InputReader —>KeyboardInputMapper:process

(4)按键事件的加工处理

InputReader —>keyboardInputMapper:processKey

4.Touch类型事件的加工处理

(1)Touch 类型事件的信息与原始事件的组织方式

(2)TouchInputMapper 的体系

(3)MultiTouchInputMapper 的配置

MultiTouchInputMapper 的 configureRawPointerAxes 获取来自设备节点的各项触控信息,同时构建传感器的物理坐标系

TouchInputMapper 的 configureSurface 获取来自 DisplayViewPort 的屏幕方向以及屏幕坐标系的信息,并计算物理坐标系到屏幕坐标系的差异信息

(4)点击事件的信息收集

InputReader->MultiTouchInputMapper:process

->MultiTouchMotionAccumulator:process

(5)点击事件信息的整合,变换与高级事件的生成

1.将事件注入派发队列

InputDispatcher 实现了 InputListenerInterface,并在 InputReader 循环的最后,QueuedInputListener 调用此接口将InputReader 产生的事件以及 NotifyXXXArgs 结构体的形式提交给 InputDispatcher

—> InputDispatcher:notifyMotionLocked

—> InputDispatcher:enqueueInboundEventLocked

2.派发线程的线程循环

InputDispatcher:dispatchOnce

派发线程的一次循环包括以下三项:

进行一次事件派发,事件的派发工作仅当命令队列中没有命令时才会进行,派发工作会设置nextWakeupTime指明随后休眠时间长短

执行命令列表中的命令

陷入休眠状态

3.派发工作的整体流程

dispatchOnceInnerLocked函数体现派发过程

InputDispatcher:dispatchOnceInnerLocked

4.事件被丢弃的原因

.....

5.Motion事件目标窗口的确定

InputDispatcher:dispatchMotionLocked

三项工作:

对于被丢弃的事件,返回 true

为事件寻找合适的窗口,窗口分为普通窗口和监听窗口,普通通过按点和焦点查找,监听窗口则无条件监听所有输入事件

如果成功地找到可以接收事件的目标窗口,通过 dispatchEventLocked 完成实际的派发工作

6.向窗口发送事件

InputDispatcher:dispatchEventLocked

1.将事件注入派发队列

2.额外的派发策略查询

InputDispatcher:dispatchOnceInnerLocked

3.重复按键事件

InputDispatcher:dispatchOnceInnerLocked

—>InputDispatcher:dispatchKeyLocked 开启与关闭重复按键模拟

—> InputDispatcher:synthesizeKeyRepeatLocked 重复按键的生成

4.按键事件派发总结

按键事件通过 notifyKey 函数进入 InputDispatcher,在注入派发队列前,使用 DispatcherPolicy 的interceptKeyBeforeQueueing 函数询问后续的派发策略 policyFlag

按键事件在正式派发给窗口前,进行一次额外的派发策略查询,查询的结果保存在 keyEntry:interceptKeyResult,结果觉得事件是正常派发,稍后派发还是丢弃

当按键按下到按键抬起之间的时间里,dispatchOnceInnerLocked 和 dispatchKeyLocked 会协同工作完成对重复按键事件的模拟

按键事件的派发目标仅通过焦点方式进行查找

InputDispatcher 运行于 system_server 进程,窗口运行于其它的应用进程中

InputChannel 的本质是一对 SocketPair,SocketPair 用来实现在本机内进行进程间的通信

InputTransport —>InputChannel:openInputChannelPair

WinodwManagerService:addwindow

WMS 添加窗口时,会创建一对 InputChannel,其中一个保存在 WindowState 中,并注册给 IMS,它是服务端,另一个则通过传出参数 outInputChannel 交给调用者,是客户端

1.服务端连接的建立

addwindow 函数中,有以下三项工作:

通过 WindowState.setInputChannel 函数保存服务端的 InputChannel

通过 IMS.registerInputChannel 将 InputChannel 注册到 IMS

通过 InputMonitor.updateInputWindowsLw 将所有窗口的信息更新到 IMS

2.窗口端连接的建立

当窗口端通过 addwindow 函数获取 InputChannel,便会使用它创建一个 InputEventReceiver 对象,可以接收来自InputChannel 的输入事件,触发 onInputEvent 回调

InputEventRecevier 如何工作?将 InputChannel 的可读事件注册到 Looper,然后在事件到来时从 InputChannel 中读取 InputMessage,并翻译成 InputEvent,然后回调 InputEventReceiver 的 onInputEvent

3.InputDispatcher与窗口的连接

派发循环是指 InputDispatcher 不断地派发队列取出事件,寻找合适的窗口并进行发送的过程,是 InputDispatcher 线程的主要工作

事件发送循环是 InputDispatcher 通过 Connection 对象将事件发送给窗口,并接受其反馈的过程

InputDispatcher —>dispatchEventLocked:dispatchEventLocked 根据 InputTarget 中的 InputChannel 找到对应的Connection

—> InputDispatcher:prepareDispatcCycleLocked

—> InputDispatcher:enqueueDispatchEntriesLocked

—> InputDispatcher:startDispatchCycleLocked

输入事件被 InputPublisher 以 InputMessage 的形式写入 InputChannel,然后将事件转存到 waitQueue 中等待窗口的反馈

当 InputPublisher 将事件以 InputMessage 的形式写入 InputChannel 中,窗口端的 Looper 会因此而被唤醒,并执行NativeInputEventReceiver 的 handleEvent 调用 consumeEvent

—>android_view_InputEventReceiver —> NativeInputEventReceiver:consumeEvent 读取一个 InputEvent,生成 java 层的 InputEvent 对象,最后通过 JNI 回调

—>  InputEventReceier:dispatchInputEvent

—> inputEventReceiver:finishInputEvent

—> android_view_InputEventReceiver —>NativeInputEventReceiver:finishInputEvent 触发服务端 InputChannel 回调

—> InputDispatcher:handleReceiveCallback

—> InputDispatcher:doDispatchCycleFinishedLockedInterruptible

对于输入事件反馈的处理主要有两个方面

将事件从 Connection 的 waitQueue 队列中删除,这个删除动作标志着此事件的派发流程完成

最后调用 startDispatchCycleLocked 继续尝试发送队列中的下一个事件

—> InputDispatcher:findFocusedWindowTargetsLocked

1.窗口可以接收事件的条件

—> InputDispatcher:isWindowReadyForMoreInputLocked 判断窗口是否可以接收事件:InputPublisher 是否被阻塞以及 Connection 两个队列的状态

2.重试派发与ANR的引发

—> InputDispatcher:handleTargetsNotReadyLocked


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/8611144.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-18
下一篇 2023-04-18

发表评论

登录后才能评论

评论列表(0条)

保存