数据实时同步:inotify + rsync 实现数据实时同步
1 数据实时同步
在生产环境中,某些场景下,要将数据或文件进行实时同步,保证数据更新后其它节点能立即获得最新的数据。
数据同步的两种方式
PULL:拉,使用定时任务的方式配合同步命令或脚本等,从指定服务器上将数据同步到本地,一般是周期性定时同步
PUSH:推,如果当前机器上的数据或文件发生更新了,立即推送到指定的节点上,可以做到实时同步
1.1 实时同步的实现方式
-
inotify + rsync
-
sersync
1.2 inotify + rsync 实现数据实时同步
实现原理
利用内核中的 inotify 监控指定目录,当目录中的文件或数据发生变化时,立即调用 rsync 服务将数据推送到远程主机上。
1.2.1 inotify 服务
inotify 是一个内核用于通知用户空间程序文件系统变化的机制,在监听到文件系统发生变化后,会向相应的应用程序发送事件,如文件增加,修改,删除等事件发生后可以立即让用户空间知道。
https://github.com/rvoicilas/inotify-tools #项目地址
inotify 是内核中的功能,在2.6.13版本的内核开始都默认存在。
[root@ubuntu ~]# grep -i inotify /boot/config-5.15.0-76-generic
CONFIG_INOTIFY_USER=y
[root@rocky ~]# grep -i inotify /boot/config-4.18.0-372.9.1.el8.x86_64
CONFIG_INOTIFY_USER=y
inotify 内核参数
[root@ubuntu ~]# ls -l /proc/sys/fs/inotify
total 0
-rw-r--r-- 1 root root 0 Jul 11 09:46 max_queued_events
-rw-r--r-- 1 root root 0 Jul 11 09:46 max_user_instances
-rw-r--r-- 1 root root 0 Jul 11 09:46 max_user_watches
#inotify 事件队列最大长度,如值太小会出现 Event Queue Overflow 错误,默认 16384,生产环境建议调大,比如 327679
[root@ubuntu ~]# cat /proc/sys/fs/inotify/max_queued_events
16384
#每个用户创建inotify实例最大值,默认值 128
[root@ubuntu ~]# cat /proc/sys/fs/inotify/max_user_instances
128
#每个inotify实例可以监视的文件的总数量
[root@ubuntu ~]# cat /proc/sys/fs/inotify/max_user_watches
14165
#一个用户可以最多开128个inotify实例,每个实例最多可以监控14165个文件
内核参数如果需要修改,可以配置文件
[root@ubuntu ~]# cat /etc/sysctl.conf
fs.inotify.max_queued_events=66666
fs.inotify.max_user_instances=256
fs.inotify.max_user_watches=100000
[root@ubuntu ~]# sysctl -p
fs.inotify.max_queued_events = 66666
fs.inotify.max_user_instances = 256
fs.inotify.max_user_watches = 100000
安装软件
inotify 是内核中的功能模块,只能通过调用API接口的形式使用其功能,我们可以通过相关软件来对其进行操作,能实现内核中 inotify 调用的软件主要有以下几个:
inotify-tools,sersync,lrsyncd
#centos系列中该软件来自于 epel 源
[root@ubuntu ~]# apt install inotify-tools
#主要工具
/usr/bin/fsnotifywait #fsnotify监控工具,fsnotify 是 inotify 的新版本
/usr/bin/fsnotifywatch #fsnotify统计工具
/usr/bin/inotifywait #实时监控指定目录的所有事件,在被监控的文件或目录上等待特定事件发生(open,close,write...)
/usr/bin/inotifywatch #收集被监控的文件系统使用的统计数据,指文件系统事件发生的次数统计
命令格式
inotifywait [ options ] file1 [ file2 ] [ file3 ] [ ... ]
#常用选项
-h|--help #显示帮助
@<file> #排除指定文件
--exclude <pattern> #不监控指定的文件或目录,正则匹配
--excludei <pattern> #不监控指定的文件或目录,正则匹配,不区分大小写
--include <pattern> #仅监控指定的文件或目录,正则匹配
--includei <pattern> #仅监控指定的文件或目录,正则匹配,不区分大小写
-m|--monitor #始终保持监听,直到超时
-d|--daemon #以守护进程方式执行,配合-o使用
-P|--no-dereference #不跟随软链接
-r|--recursive #对目录递归监控,即监控目录内所有内容
--fromfile <file> #从文件中读取要监控的内容
-o|--outfile <file> #将执行结果输出到指定文件
-s|--syslog #错误输出到syslog,而不是标准错误输出
-q|--quiet #简短输出,仅输出事件信息
-qq #禁用输出
--format <fmt> #指定输出格式
--no-newline #不换行输出,配合--format字段
--timefmt <fmt> #指定时间输出格式
-c|--csv #以CSV格式输出
-t|--timeout <seconds> #指定超时时长,值为0则永远不超时
-e|--event <event1> #只监听指定事件,默认监听所有事件
# --format 选项可用字段
%T #输出时间格式中定义的时间格式信息,通过 --timefmt option 语法格式指定时间信息
%w #事件出现时,监控文件或目录的名称信息,相当于dirname
%f #事件出现时,将显示监控目录下触发事件的文件或目录信息,否则为空,相当于basename
%e #显示发生的事件信息,不同的事件默认用逗号分隔
%Xe #显示发生的事件信息,不同的事件指定用X进行分隔
# --timefmt 选项可用字段
%Y #年份信息,包含世纪信息
%y #年份信息,不包括世纪信息
%m #显示月份,范围 01-12
%d #每月的第几天,范围是 01-31
%H #小时信息,使用 24小时制,范围 00-23
%M #分钟,范围 00-59
%S #秒,范例 0-60
# -e 选项可以指定的事件
access #文件或目录内容被读取
modify #内容发生变化
attrib #属性发生变化
close_write #写入模式打开后关闭
close_nowrite #只读打开后关闭
close #关闭事件,无关模式
open #打开事件,无关模式
moved_to #文件或目录被移动到监控的目录中
moved_from #文件或目录从监控的目录中被移动
move #文件或目录不管移动到或是移出监控目录都触发事件
move_self #被移动之后同名文件不再被监控
create #创建文件或目录
delete #文件或目录被删除
delete_self #被删除之后同名文件不再被监控
unmount #取消挂载
只监控一个事件
[root@ubuntu ~]# tree /data/
/data/
├── dir1
└── dir2
2 directories, 0 files
#开始监控
[root@ubuntu ~]# inotifywait /data/
Setting up watches.
Watches established.
#在另一个终端中执行
[root@ubuntu ~]# ls /data/
dir1 dir2
#提示 open事件并退出
[root@ubuntu ~]# inotifywait /data/
Setting up watches.
Watches established.
/data/ OPEN,ISDIR
持续监控
[root@ubuntu ~]# inotifywait -m /data/
Setting up watches.
Watches established.
#另一个终端操作
[root@ubuntu ~]# ls /data
dir1 dir2
[root@ubuntu ~]# ls /data/dir1
[root@ubuntu ~]# touch /data/test.txt
#查看监控,一条命令可能有多个事件
[root@ubuntu ~]# inotifywait -m /data/
Setting up watches.
Watches established.
/data/ OPEN,ISDIR
/data/ ACCESS,ISDIR
/data/ ACCESS,ISDIR
/data/ CLOSE_NOWRITE,CLOSE,ISDIR
/data/ OPEN,ISDIR dir1
/data/ ACCESS,ISDIR dir1
/data/ ACCESS,ISDIR dir1
/data/ CLOSE_NOWRITE,CLOSE,ISDIR dir1
/data/ CREATE test.txt
/data/ OPEN test.txt
/data/ ATTRIB test.txt
/data/ CLOSE_WRITE,CLOSE test.txt
递归监控
[root@ubuntu ~]# ls /data/dir1/
[root@ubuntu ~]# touch /data/dir1/test.txt
[root@ubuntu ~]# rm -f /data/dir1/test.txt
#无法监控 touch 和 rm
[root@ubuntu ~]# inotifywait -m /data/
Setting up watches.
Watches established.
/data/ OPEN,ISDIR dir1
/data/ ACCESS,ISDIR dir1
/data/ CLOSE_NOWRITE,CLOSE,ISDIR dir1
[root@ubuntu ~]# ls /data/dir1/
[root@ubuntu ~]# touch /data/dir1/test.txt
[root@ubuntu ~]# rm -f /data/dir1/test.txt
#递归监控
[root@ubuntu ~]# inotifywait -m -r /data/
Setting up watches. Beware: since -r was given, this may take a while!
Watches established.
/data/ OPEN,ISDIR dir1
/data/dir1/ OPEN,ISDIR
/data/ ACCESS,ISDIR dir1
/data/dir1/ ACCESS,ISDIR
/data/ ACCESS,ISDIR dir1
/data/dir1/ ACCESS,ISDIR
/data/ CLOSE_NOWRITE,CLOSE,ISDIR dir1
/data/dir1/ CLOSE_NOWRITE,CLOSE,ISDIR
/data/dir1/ CREATE test.txt
/data/dir1/ OPEN test.txt
/data/dir1/ ATTRIB test.txt
/data/dir1/ CLOSE_WRITE,CLOSE test.txt
/data/dir1/ DELETE test.txt
将结果输出到文件
[root@ubuntu ~]# inotifywait -m -r /data/ -o inotify.txt
Setting up watches. Beware: since -r was given, this may take a while!
Watches established.
[root@ubuntu ~]# ls /data/
dir1 dir2 test.txt
#查看结果文件
[root@ubuntu ~]# cat inotify.txt
/data/ OPEN,ISDIR
/data/ ACCESS,ISDIR
/data/ CLOSE_NOWRITE,CLOSE,ISDIR
从文件中读取要监控的内容
[root@ubuntu ~]# cat a.txt
/data/
[root@ubuntu ~]# inotifywait -rm --fromfile a.txt
Setting up watches. Beware: since -r was given, this may take a while!
Watches established.
后台守护执行,并指定输出格式
[root@ubuntu ~]# inotifywait -drq /data/ -o inotify.log --timefmt "%Y-%m-%d %H:%M:%S" --format "%T %w %f event: %e"
[root@ubuntu ~]# cat inotify.log
2025-01-12 14:45:53 /data/ event: OPEN,ISDIR
2025-01-12 14:45:53 /data/ event: ACCESS,ISDIR
2025-01-12 14:45:53 /data/ event: CLOSE_NOWRITE,CLOSE,ISDIR
指定输出格式,且只记录特定事件
[root@ubuntu ~]# ls /data/
dir1 dir2 test.txt
[root@ubuntu ~]# touch /data/test.log
[root@ubuntu ~]# touch /data/test.log
[root@ubuntu ~]# rm -f /data/test.log
[root@ubuntu ~]# inotifywait -mrq /data/ --timefmt "%F %H:%M:%S" --format "%T%w%f event:%;e" -e create,delete,moved_to,close_write,attrib
2025-01-12 14:58:03 /data/test.log event:CREATE
2025-01-12 14:58:03 /data/test.log event:ATTRIB
2025-01-12 14:58:03 /data/test.log event:CLOSE_WRITE;CLOSE
2025-01-12 14:58:06 /data/test.log event:ATTRIB
2025-01-12 14:58:06 /data/test.log event:CLOSE_WRITE;CLOSE
2025-01-12 14:58:09 /data/test.log event:DELETE
1.2.2 rsync 服务
rsync 常用于作为 linux系统下的数据镜像备份工具,实现远程同步,支持本地复制,或者与其他SSH、rsync主机同步数据,支持增量备份,配合任务计划,rsync能实现定时或间隔同步,配合 inotify 或 sersync,可以实现触发式的实时数据同步。
http://rsync.samba.org/ #官方网站
安装软件
[root@ubuntu ~]# apt install rsync
命令格式
#Local
rsync [OPTION]... SRC [SRC]... DEST #本地文件同步
#Access via remote shell
rsync [OPTION]... [USER@]HOST:SRC [DEST] #PULL 拉,将远程主机上的文件拉到本地
rsync [OPTION]... SRC [SRC]... [USER@]HOST:DEST #PUSH 推,将本地文件推送到远程主机上
#Access via rsync daemon:
rsync [OPTION]... [USER@]HOST::SRC [DEST] #PULL 拉,将远程主机上的文件拉到本地
rsync [OPTION]... rsync://[USER@]HOST[:PORT]/SRC [DEST] #PULL 拉,将远程主机上的文件拉到本地
rsync [OPTION]... SRC [SRC]... [USER@]HOST::DEST #PUSH 推,将本地文件推送到远程主机上
rsync [OPTION]... SRC [SRC]... rsync://[USER@]HOST[:PORT]/DEST #PUSH 推,将本地文件推送到远程主机上
rsync 有三种工作方式
-
本地文件系统上实现同步。命令行语法格式为上述 "Local" 段的格式
-
本地主机使用远程shell和远程主机通信。命令行语法格式为上述 "Access via remote shell" 段的格式,使用的用户名和密码是 Linux系统的用户名和密码
-
本地主机通过网络套接字连接远程主机上的 rsync daemon。命令行语法格式为上述 "Access via rsync daemon" 段的格式,使用的用户名和密码是 rsync 服务中配置的用户名和密码
前两者的本质是通过本地或远程shell,而第3种方式则是让远程主机上运行 rsyncd 服务,使其监听在一个端口上,等待客户端的连接,此种方式使用的 rsync 的专有协议。
常用选项
--verbose|-v #显示详细过程,最多可以 -vvvv
--quiet|-q #不输出错误信息
--archive|-a #归档模式,保留文件属性
--recursive|-r #递归
--backup|-b #如果目标文件存在,先做备份,默认备份后缀是 ~
--backup-dir=DIR #指定备份目录
--suffix=SUFFIX #指定备份后缀
--update|-u #仅在源mtime比目标已存在文件的mtime新时才拷贝,该选项是接收端判断的,不会影响删除行为
--links|-l #传输软链接文件,而不是传输其指向的文件
--copy-links|-L #跟随软链接,传输其指向的目标文件或目录
--perms|-p #保留权限(不包括特殊权限)
--owner|-o #保持owner属性
--group|-g #保持group属性
-D #传输设备文件和特殊文件,同 --devices --specials
--times|-t #保留mtime属性
--dry-run|-n #测试模式,不实际传输,常合 -vvvv 配合查看细节
--whole-file|-W #不使用增量传输,而使用全量传输,在网络带宽高于磁盘带宽时,该选项比增量传输更高效
--rsh=COMMAND|-e #指定所要使用的远程shell程序,默认为ssh
--existing #只更新远端已存在的文件,远端不存在的文件不传输。使用相对路径时如果上层目录不存在也不会传输
--ignore-existing #只传输远程主机不存在的文件
--remove-source-files #删除己传输成功的源文件
--del #在传输中删除,同 --delete-during
--delete #文件传输时,删除DEST中在SRC 中不存在的文件
--delete-before #传输开始前先删除
--delete-during #在传输过程中删除
--delete-delay #在传输中确定要删除的文件,传输结束后删除
--delete-after #传输结束后再删除
--delete-excluded #删除远程主机上在此项中指定的文件
--force #强制删除目录,哪怕不为空
--max-delete=NUM #最多删除NUM个文件
--max-size=SIZE #限制rsync传输的最大文件大小,可以使用单位后缀,可以写小数值
--min-size=SIZE #限制rsync传输的最小文件大小。可用于禁止传输小文件或垃圾文件,可以写小数值
--size-only #默认传输有变化的文件,默认检查文件大小变化和 mtime,此项表示只检查文件大小变化
--compress|-z #压缩传输
--exclude=PATTERN #用正则来指定排除规则来排除不需要传输的文件
--exclude-from=FILE #从文件中读取不需要被传送的文件
--include=PATTERN #用正则来指定要传输的文件
--include-from=FILE #从文件中读取要传输的文件
--port=PORT #连接daemon时使用的端口号,默认为873端口
--human-readable|-h #以人类友好的格式显示相关信息
--progress #显示进度条
-P #显示进度条,同 --partial --progress
--password-file=FILE #daemon模式时密码文件,读取密码非交互式操作 这不是远程shell认证的密码,而是rsync模块认证的密码
--version|-V #显示版本信息
--help|-h (*) #显示帮助信息
实现 rsync daemon 服务
主机清单
IP | 角色 |
10.0.0.208 | rsync-server |
10.0.0.206 | rsync-client |
#服务端以守护进程运行
[root@ubuntu ~]# systemctl enable --now rsync.service
#启动失败,因为 /etc/rsyncd.conf 配置文件不存在
[root@ubuntu ~]# systemctl status rsync.service
#创建空配置文件
[root@ubuntu ~]# touch /etc/rsyncd.conf
#启动服务
[root@ubuntu ~]# systemctl start rsync.service
#查看服务状态,运行中
[root@ubuntu ~]# systemctl status rsync
#监听 873 端口
[root@ubuntu ~]# ss -tunlp | grep rsync
#客户端连接测试
[root@ubuntu ~]# rsync rsync://10.0.0.208
[root@ubuntu ~]# echo $?
0
#修改服务端配置,指定共享目录
[root@ubuntu ~]# cat /etc/rsyncd.conf
[dir1]
path=/data/dir1/
read only=no
#重启服务
[root@ubuntu ~]# systemctl restart rsync.service
#查看服务端目录
[root@ubuntu ~]# tree /data/
/data/
└── dir1
1 directory, 0 files
#客户端再次测试,可以看到内容
[root@ubuntu ~]# rsync rsync://10.0.0.208
dir1
#两种写法都可以, :: 表示走rsync协议
[root@ubuntu ~]# rsync 10.0.0.208::
dir1
#传输文件到远程失败,此处的 root 是指rsync服务的用户,当前服务端并没有配置此信息,默认会被映射成 nobody
[root@ubuntu ~]# rsync /etc/fstab root@10.0.0.208::dir1
rsync: [receiver] mkstemp "/.fstab.tBlxU2" (in dir1) failed: Permission denied (13)
rsync error: some files/attrs were not transferred (see previous errors) (code 23) at main.c(1338) [sender=3.2.7]
#在服务端配置权限
[root@ubuntu ~]# setfacl -m u:nobody:rwx /data/dir1/
#客户端再次测试,上传成功,现在使用的是匿名连接
[root@ubuntu ~]# rsync /etc/fstab root@10.0.0.208::dir1
[root@ubuntu ~]# rsync /etc/issue tom@10.0.0.208::dir1 #tom 用户在服务端并不存在
#服务端查看,属主属组都是 nobody
[root@ubuntu ~]# ls -l /data/dir1/
total 8
-rw-r--r-- 1 nobody nogroup 771 Jul 12 00:02 fstab
-rw-r--r-- 1 nobody nogroup 24 Jul 12 00:04 issue
#指定映射账号,指定日志文件,指定远程连接用户名和密码,禁用匿名连接
[root@ubuntu ~]# cat /etc/rsyncd.conf
uid=root
gid=root
max connections=0
log file=/var/log/rsyncd.log
pid file=/var/run/rsyncd.pid
lock file=/var/run/rsyncd.lock
[dir1]
path=/data/dir1/
comment=rsync dir1
read only=no
auth users=rsyncer
secrets file=/etc/rsyncd.pwd
#密码文件
[root@ubuntu ~]# cat /etc/rsyncd.pwd
123456
#重启服务
[root@ubuntu ~]# systemctl restart rsync.service
#客户端再次测试,匿名非匿名都报错
[root@ubuntu ~]# rsync 10.0.0.208::dir1
Password:
@ERROR: auth failed on module dir1
rsync error: error starting client-server protocol (code 5) at main.c(1863) [Receiver=3.2.7]
[root@ubuntu ~]# rsync rsyncer@10.0.0.208::dir1
Password:
@ERROR: auth failed on module dir1
rsync error: error starting client-server protocol (code 5) at main.c(1863) [Receiver=3.2.7]
#查看服务端日志,密码文件不能被所有人可读
[root@ubuntu ~]# cat /var/log/rsyncd.log
#修改密码文件权限
[root@ubuntu ~]# chmod 600 /etc/rsyncd.pwd
[root@ubuntu ~]# ll /etc/rsyncd.pwd
-rw------- 1 root root 15 Jul 13 08:58 /etc/rsyncd.pwd
#客户端再次测试
[root@ubuntu ~]# rsync /etc/hosts rsyncer@10.0.0.208::dir1
Password:
[root@ubuntu ~]# rsync rsyncer@10.0.0.208::dir1
Password:
drwxrwxr-x 4,096 2023/07/13 09:23:12 .
-rw-r--r-- 771 2023/07/12 00:02:15 fstab
-rw-r--r-- 270 2023/07/13 09:23:12 hosts
-rw-r--r-- 24 2023/07/12 00:04:37 issue
#服务端查看,新文件属主属组发生了变化
[root@ubuntu ~]# ls -lh /data/dir1/
total 12K
-rw-r--r-- 1 nobody nogroup 771 Jul 12 00:02 fstab
-rw-r--r-- 1 root root 270 Jul 13 09:23 hosts
-rw-r--r-- 1 nobody nogroup 24 Jul 12 00:04 issue
#查看客户端文件
[root@ubuntu ~]# tree /data/www/
/data/www/
├── dira
│ └── os-release
├── f1
├── f2
├── fstab
└── issue
1 directory, 5 files
#查看服务端文件
[root@ubuntu ~]# tree /data/dir1/
/data/dir1/
├── fstab
├── hosts
└── issue
0 directories, 3 files
#将客户端密码保存在单独文件,实现非交互式连接
[root@ubuntu ~]# echo "123456" > /etc/rsyncd.pwd
[root@ubuntu ~]# chmod 600 /etc/rsyncd.pwd
#客户端测试,保证服务端与客户端同步
#--delete 选项,此次同步完成后,删除服务端不在此次同步中的文件
#-a 保留属性
#-v 显示过程
#-z 压缩传输
[root@ubuntu ~]# rsync -avz --delete --password-file=/etc/rsyncd.pwd /data/www/ rsyncer@10.0.0.208::dir1
sending incremental file list
deleting hosts #删除了远程的 hosts 文件
./
f1
f2
fstab
issue
dira/
dira/os-release
sent 1,169 bytes received 147 bytes 2,632.00 bytes/sec total size is 1,182 speedup is 0.90
#再次查看服务端,与客户端保持一致了
[root@ubuntu ~]# tree /data/dir1/
/data/dir1/
├── dira
│?? └── os-release
├── f1
├── f2
├── fstab
└── issue
1 directory, 5 files
rsync 服务常用配置项
#查看配置示例
[root@ubuntu ~]# cat /usr/share/doc/rsync/examples/rsyncd.conf
# GLOBAL OPTIONS #全局配置部份
motd file=/etc/motd #motd 文件路径
log file=/var/log/rsyncd #日志文件
pid file=/var/run/rsyncd.pid #PID 文件
syslog facility=daemon #rsyslog 日志服务中的日志归类
socket options= #socket 选项,具体见 man setsockopt
[ftp] #客户端显示的名称
comment = public archive #客户端列出该共享目录时的说明信息
path = /var/www/pub #服务端具体目录
use chroot = yes #更改映射目录的根目录
max connections=10 #最大连接数,同时有多少客户端可以连接
lock file = /var/lock/rsyncd #锁文件
read only = yes #默认客户端只读访问
list = yes #客户端是否可以列出服务端内容
uid = nobody #默认将客户端上传的文件属主映射成 nobody
gid = nogroup #默认将客户端上传的文件属组映射成 nobody
exclude = #指定排除项,在此处指定的内容在客户端无法显示
exclude from = #从指定文件中读取排除项
include = #指定显示项,配合 exclude,exclude from 使用
include from = #同上
auth users = #客户端用户名,启用此项表示禁用匿名连接
secrets file = /etc/rsyncd.secrets #客户端用户名和密码对应文件
strict modes = yes #严格检查权限,此选项用于 windows 系统上的 rsync
hosts allow = #客户端白名单
hosts deny = #客户端黑名单
ignore errors = no #不忽略错误
ignore nonreadable = yes #
transfer logging = no #是否开启传输日志
log format = %t: host %h (%a) %o %f (%l bytes). Total %b bytes. #默认日志格式
timeout = 600 #超时时长
refuse options = checksum dry-run #服务端拒绝客户端执行的命令列表
dont compress = *.gz *.tgz *.zip *.z *.rpm *.deb *.iso *.bz2 *.tbz #不压缩指定文件
#查看配置帮助
[root@ubuntu ~]# man rsyncd.conf
1.2.3 inotify + rsync 实现数据实时同步
#客户端同步脚本
[root@ubuntu data]# cat ./www_rsync.sh
#!/bin/bash
SRC='/data/www/'
DEST='rsyncer@10.0.0.208::dir1'
dpkg -V inotify-tools &>/dev/null || apt install inotify-tools -y
dpkg -V rsync &>/dev/null || apt install rsync -y
#不间断监控指定目录中的特定事件,当目录中有事件发生变化时,调用 rsync 命令进行同步
inotifywait -mrq --exclude=".*\.swp" --timefmt '%Y-%m-%d %H:%M:%S' --format '%T %w %f' -e create,delete,moved_to,close_write,attrib ${SRC} | while read DATE TIME DIR FILE;do
FILEPATH=${DIR}${FILE}
rsync -az --delete --password-file=./www_rsync.pwd $SRC $DEST && echo "At ${TIME} on ${DATE}, file ${FILEPATH} was backup via rsync" >> ./www_rsync.log
done
#查看客户端
[root@ubuntu ~]# tree /data/
/data/
├── www
├── www_rsync.pwd
└── www_rsync.sh
1 directory, 2 files
#测试,客户端运行脚本
[root@ubuntu data]# ./www_rsync.sh
#在另一个终端中创建文件
[root@ubuntu ~]# touch /data/www/f1
[root@ubuntu ~]# cp /etc/fstab /data/www/
[root@ubuntu ~]# dd if=/dev/zero of=/data/www/test.img bs=1M count=10
10+0 records in
10+0 records out
10485760 bytes (10 MB, 10 MiB) copied, 0.00923138 s, 1.1 GB/s
[root@ubuntu ~]# mkdir -pv /data/www/dira/dirb/dirc
mkdir: created directory '/data/www/dira'
mkdir: created directory '/data/www/dira/dirb'
mkdir: created directory '/data/www/dira/dirb/dirc'
#在服务湍查看
[root@ubuntu ~]# tree /data/dir1/
/data/dir1/
├── dira
│ └── dirb
│ └── dirc
├── f1
├── fstab
└── test.img
3 directories, 3 files
#查看客户端日志,由于某些行为会触发多个事件,导致多次调用脚本,效率不高
[root@ubuntu ~]# cat /data/www_rsync.log
At 03:14:53 on 2025-01-13, file /data/www/f1 was backup via rsync
At 03:14:53 on 2025-01-13, file /data/www/f1 was backup via rsync
At 03:14:53 on 2025-01-13, file /data/www/f1 was backup via rsync
At 03:15:05 on 2025-01-13, file /data/www/fstab was backup via rsync
At 03:15:05 on 2025-01-13, file /data/www/fstab was backup via rsync
At 03:15:45 on 2025-01-13, file /data/www/test.img was backup via rsync
At 03:15:45 on 2025-01-13, file /data/www/test.img was backup via rsync
At 03:16:05 on 2025-01-13, file /data/www/dira was backup via rsync
1.3 sersync 实现数据实时同步
sersync 类似 于inotify,同样用于监控,但它克服了 inotify 的缺点,inotify 最大的不足是会产生重复事件,或者同一个目录下多个文件的操作会产生多个事件,例如,当监控目录中有5个文件时,删除目录时会产生6个监控事件,从而导致重复调用 rsync 命令。另外比如:vim 文件时,inotify 会监控到临时文件的事件,但这些事件相对于 rsync 来说是不应该被监控的。
sersync 特点
-
sersync是使用c++编写,而且对linux系统文件系统产生的临时文件和重复的文件操作进行过滤,所以在结合rsync同步的时候,节省了运行时耗和网络资源。因此更快。
-
sersync 配置很简单,其中提供了静态编译好的二进制文件和 xml 配置文件,直接使用即可
-
sersync 使用多线程进行同步,尤其在同步较大文件时,能够保证多个服务器实时保持同步状态
-
sersync 有出错处理机制,通过失败队列对出错的文件重新同步,如果仍旧失败,则按设定时长对同步失败的文件重新同步
-
sersync 不仅可以实现实时同步,另外还自带 crontab 功能,只需在 xml 配置文件中开启,即也可以 按要求隔一段时间整体同步一次,而无需再额外配置 crontab 功能
-
sersync 可以二次开发
https://code.google.com/archive/p/sersync/ #项目地址
#下载
[root@ubuntu ~]# wget https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/sersync/sersync2.5.4_64bit_binary_stable_final.tar.gz
#解压
[root@ubuntu ~]# tar xf sersync2.5.4_64bit_binary_stable_final.tar.gz
[root@ubuntu ~]# ls
GNU-Linux-x86 sersync2.5.4_64bit_binary_stable_final.tar.gz snap
[root@ubuntu ~]# ls GNU-Linux-x86/
confxml.xml sersync2
#移动
[root@ubuntu ~]# mv GNU-Linux-x86/ /usr/local/sersync
[root@ubuntu ~]# ls /usr/local/sersync/
confxml.xml sersync2
配置文件说明
<?xml version="1.0" encoding="ISO-8859-1"?>
<head version="2.5">
<host hostip="localhost" port="8008"></host>
<debug start="false"/> #是否开启调试模式
<fileSystem xfs="false"/>
<filter start="false"> #不开启文件过滤功能,当为true时,下列文件不同步
<exclude expression="(.*)\.svn"></exclude>
<exclude expression="(.*)\.gz"></exclude>
<exclude expression="^info/*"></exclude>
<exclude expression="^static/*"></exclude>
</filter>
<inotify> #具体监控的事件
<delete start="true"/>
<createFolder start="true"/>
<createFile start="false"/>
<closeWrite start="true"/>
<moveFrom start="true"/>
<moveTo start="true"/>
<attrib start="false"/> #此处改为true,则文件属性发生变化,也会同步
<modify start="false"/>
</inotify>
<sersync> #rsync命令的配置段
<localpath watch="/opt/tongbu"> #需要同步的目录
<remote ip="127.0.0.1" name="tongbu1"/> #远程主机地址和目录
<!--<remote ip="192.168.8.39" name="tongbu"/>-->
<!--<remote ip="192.168.8.40" name="tongbu"/>-->
</localpath>
<rsync>
<commonParams params="-artuz"/> #指定rsync选项
<auth start="false" users="root" passwordfile="/etc/rsync.pas"/>#修改为true,指定rsync用户名和密码文件
<userDefinedPort start="false" port="874"/> #指定非标准端口
<!-- port=874 -->
<timeout start="false" time="100"/>
<!-- timeout=100 -->
<ssh start="false"/> #默认远程rsync daemon运行,true为使用远程shell
</rsync>
<failLog path="/tmp/rsync_fail_log.sh" timeToExecute="60"/>#错误重传及日志文件路径
<!--default every 60mins execute once-->
<crontab start="false" schedule="600"><!--600mins-->#不开启crontab功能
<crontabfilter start="false"> #不开启crontab定时传输的筛选功能
<exclude expression="*.php"></exclude>
<exclude expression="info/*"></exclude>
</crontabfilter>
</crontab>
<plugin start="false" name="command"/>
</sersync>
#以下不需要修改
<plugin name="command">
<param prefix="/bin/sh" suffix="" ignoreError="true"/> <!--prefix /opt/tongbu/mmm.sh suffix-->
<filter start="false">
<include expression="(.*)\.php"/>
<include expression="(.*)\.sh"/>
</filter>
</plugin>
<plugin name="socket">
<localpath watch="/opt/tongbu">
<deshost ip="192.168.138.20" port="8009"/>
</localpath>
</plugin>
<plugin name="refreshCDN">
<localpath watch="/data0/htdocs/cms.xoyo.com/site/">
<cdninfo domainname="ccms.chinacache.com" port="80" username="xxxx" passwd="xxxx"/>
<sendurl base="http://pic.xoyo.com/cms"/>
<regexurl regex="false" match="cms.xoyo.com/site([/a-zA-Z0-9]*).xoyo.com/images"/>
</localpath>
</plugin>
</head>
sersync2 命令用法和参数
[root@ubuntu sersync]# ./sersync2 -h
set the system param
execute:echo 50000000 > /proc/sys/fs/inotify/max_user_watches
execute:echo 327679 > /proc/sys/fs/inotify/max_queued_events
parse the command param
_______________________________________________________
参数-d:启用守护进程模式
参数-r:在监控前,将监控目录与远程主机用rsync命令推送一遍
参数-n:指定开启守护线程的数量,默认为10个
参数-o:指定配置文件,默认使用confxml.xml文件
参数-m:单独启用其他模块,使用 -m refreshCDN 开启刷新CDN模块
参数-m:单独启用其他模块,使用 -m socket 开启socket模块
参数-m:单独启用其他模块,使用 -m http 开启http模块
不加-m参数,则默认执行同步程序
_________________________________________________
客户端测试
#服务端文件
[root@ubuntu ~]# tree /data/dir1/
/data/dir1/
└── f2
0 directories, 1 file
#客户端文件
[root@ubuntu ~]# tree /data/www
/data/www
└── f1
0 directories, 1 file
[root@ubuntu ~]# cd /usr/local/sersync/
[root@ubuntu sersync]# ./sersync2 -dro ./confxml.xml
#查看服务端,己经和客户端保持一致了
[root@ubuntu ~]# tree /data/dir1/
/data/dir1/
└── f1
0 directories, 1 file
#客户端测试
[root@ubuntu ~]# mkdir -pv /data/www/dira/dirb/dirc
mkdir: created directory '/data/www/dira'
mkdir: created directory '/data/www/dira/dirb'
mkdir: created directory '/data/www/dira/dirb/dirc'
[root@ubuntu ~]# cp /etc/fstab /data/www/
[root@ubuntu ~]# dd if=/dev/zero of=/data/www/test.img bs=1M count=10
10+0 records in
10+0 records out
10485760 bytes (10 MB, 10 MiB) copied, 0.00870068 s, 1.2 GB/s
#服务端查看
[root@ubuntu ~]# tree /data/dir1/
/data/dir1/
├── dira
│ └── dirb
│ └── dirc
├── f1
├── fstab
└── test.img
3 directories, 3 files
#客户端查看后台进程
[root@ubuntu ~]# ps aux | grep rsync
root 5249 0.0 0.0 116928 1624 ? Ssl 07:02 0:00 ./sersync2 -dro ./confxml.xml
root 5307 0.0 0.1 6476 2324 pts/0 S+ 07:04 0:00 grep --color=auto rsync
相关文章:
数据实时同步:inotify + rsync 实现数据实时同步
1 数据实时同步 在生产环境中,某些场景下,要将数据或文件进行实时同步,保证数据更新后其它节点能立即获得最新的数据。 数据同步的两种方式 PULL:拉,使用定时任务的方式配合同步命令或脚本等,从指定服务…...
C#学习第24天:程序集和部署
程序集知识点 1.程序集的基本概念 程序集是部署和版本控制的最小单位。它可以是可执行文件(.exe)或动态链接库(.dll)。包含元数据和清单(Manifest),描述程序集的内容和依赖关系。 2.程序集清单…...
mac .zshrc:1: command not found: 0 解决方案
nano ~/.zshrc 使用自带的nano命令打开文件,修改后 Ctrl X 然后输入y 然后回车即可保存成功 一般情况下,不是常用这个命令,除非是遇到有问题的文件,才用, 例如 遇到下面的问题 /Users/xxli/.zshrc:1: command no…...
学习设计模式《十》——代理模式
一、基础概念 代理模式的本质【控制对象访问】; 代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问; 代理模式的功能:代理模式是通过创建一个代理对象,用这个代理对象去代表真实的对象;客户端得…...
RestFul操作ElasticSearch:索引与文档全攻略
RestFul方式操作ES 索引库操作 创建索引库 PUT /索引库名称 {"mappings":{"properties":{"字段名":{"type":"字段类型","analyzer":"分词器","index":"是否参与搜索(布尔值)"},…...
OpenCV 图像读取与显示
一、知识点: 1、读取图像 (1)、Mat imread( const String & filename, int flags IMREAD_COLOR_BGR ); (2)、返回值: Mat,返回读取的图像。 若读取图像失败,则返回一个空的对象,对象.empty()为true。 (3)、参数filename: String是…...
Django快速入门篇
Django官网 https://docs.djangoproject.com/zh-hans/4.2/ 官方介绍 官方版本 推荐LTS版本,python3.9/3.10 djongo 每两年会出一个LTS版本 关于环节djongo,conda直接安装即可 conda create -n myenv python3.9 conda activate myenv pip install dj…...
C++23 新增扁平化关联容器详解
文章目录 一、引言已有关联容器回顾新容器的引入原因 二、std::flat_set定义与特性代码示例适用场景 三、std::flat_multiset定义与特性代码示例适用场景 四、std::flat_map定义与特性代码示例适用场景 五、std::flat_multimap定义与特性代码示例适用场景 六、与其他容器的比较…...
当PLC遇上电焊机器人:EtherCAT转CANopen上演工业级“语言翻译官”
在汽车自动化产线中,PLC与电焊机器人的高效协同是提升生产效率的关键。但PLC常用的EtherCAT协议与电焊机器人采用的CANopen协议存在通信壁垒,JH-ECT009疆鸿智能EtherCAT转CANopen技术成为打破这一障碍的核心方案。 应用拓扑图 EtherCAT是高速工业以太网协…...
LeetCode 1345. 跳跃游戏 IV(困难)
题目描述 给你一个整数数组 arr ,你一开始在数组的第一个元素处(下标为 0)。 每一步,你可以从下标 i 跳到下标 i 1 、i - 1 或者 j : i 1 需满足:i 1 < arr.lengthi - 1 需满足:i - 1 …...
Linux bash shell的循环命令for、while和until
1、for命令 for命令,允许你创建一个遍历一系列值的循环,每次迭代都使用其中一个 值来执行已定义好的一组命令。 for var in list do commands done # 在list参数中,你需要提供迭代中要用到的一系列值。 # 可以通过几种不同的方法指定列表中的…...
三、【数据建模篇】:用 Django Models 构建测试平台核心数据
【数据建模篇】:用 Django Models 构建测试平台核心数据 前言我们要设计哪些核心数据?准备工作:创建 Django App开始设计数据模型 (Models)1. 通用基础模型 (可选但推荐)2. 项目模型 (Project)3. 模块模型 (Module)4. 测试用例模型 (TestCase…...
Mac如何允许安装任何来源软件?
打开系统偏好设置-安全性与隐私,点击右下角的解锁按钮,选择允许从任何来源。 如果没有这一选项,请到打开终端,输入命令行:sudo spctl --master-disable, 输入命令后回车,输入电脑的开机密码后回车。 返回“…...
云原生主要架构模式
云原生(Cloud Native)是一种利用云计算的优势来构建和运行可扩展、弹性和高效应用程序的方法。它不仅仅是技术的集合,更是一种架构和设计理念。本文将围绕你提出的几部分,深入探讨云原生主要的架构模式,帮助你理解如何利用这些模式构建现代化的应用。 1. 服务化架构模式(…...
Neon数据库:让Postgres更智能的选择!
Neon:革新的Serverless PostgreSQL解决方案 在当今快速发展的技术世界,数据库的效率和灵活性成为众多开发者关注的重中之重。Neon,以其独特的serverless架构,正引领着这一变革。本文将深入探讨Neon的独特构架、应用场景以及具体的…...
《Metasploit框架核心模块解析与安全防护实践》
目录 一、框架模块化设计与安全验证价值 1. 漏洞验证模块(Exploit Modules) 2. 安全评估模块(Auxiliary Modules) 3. 安全响应模块(Post-Exploitation) 4. 载荷安全…...
C#:多线程Task使用
一.Task与Thread Task是架构在Thread之上的,也就是说任务最终还是要抛给线程去执行。Task跟Thread不是一对一的关系,比如开10个任务并不是说会开10个线程,这一点任务有点类似线程池,但是任务相比线程池有很小的开销和精确的控制。…...
Nginx笔记
一、概述 Nginx一个具有高性能的【HTTP】和【反向代理】的【WEB服务器】,同时也是一个电子邮件代理服务器。正向代理服务的是客户端(比如VPN),反向代理服务的是服务端。Nginx是多进程的,有一个Master进程控制多个Worke…...
小米便签源码部署流程
一、准备环境 1. 安装必要工具 Android Studio:最新稳定版(需支持 Kotlin 和 Jetpack Compose)。 JDK:建议 JDK 11 或更高(通过 sdkman 或 brew 安装)。 Git:用于克隆源码。 2. 配置国内镜像源&…...
DAY 30 超大力王爱学Python
知识点回顾: 导入官方库的三种手段导入自定义库/模块的方式导入库/模块的核心逻辑:找到根目录(python解释器的目录和终端的目录不一致) 作业:自己新建几个不同路径文件尝试下如何导入 步骤 1:创建项目结构 …...
左右边界策略
这是一套完整的交易逻辑策略,涵盖了从函数定义、指标计算、信号生成到资金和仓位管理、加仓和减仓逻辑、以及止损和止盈逻辑的各个方面。 以下对该交易系统进行详细分析: 交易逻辑思路 1. 函数定义 - DZSell 和 DZBuy 函数:这两个函数用于计算卖出和买入的价格区间。它…...
iOS苹果和Android安卓测试APP应用程序的区别差异
在当今这个移动互联网时代,iOS和Android作为两大主流操作系统,它们在测试应用程序时存在哪些差异呢?这不仅是一个技术问题,也是一个市场策略问题。让我们从一个实际案例开始探讨。 假设我们有一个新的社交应用需要在iOS和Android…...
【Python装饰器深潜】从语法糖到元编程的艺术
目录 🌟 前言🏗️ 技术背景与价值🩹 当前技术痛点🛠️ 解决方案概述👥 目标读者说明🧠 一、技术原理剖析📊 核心概念图解💡 核心作用讲解🔧 关键技术模块说明⚖️ 技术选型对比🛠️ 二、实战演示⚙️ 环境配置要求💻 核心代码实现案例1:基础计时装饰器案…...
Kubernetes中微服务JVM监控与自动发现的解决方案
以下是针对 Kubernetes 中微服务 JVM 监控与自动发现的解决方案,结合 Prometheus 的动态发现机制和 Spring Boot 的监控能力,解决 Pod IP 动态变化和当前微服务监控数据暴露匿名随意访问的安全问题。 一、微服务端配置(Spring Boot 微服务) 1. 依赖配置(pom.xml) <…...
mapbox进阶,纯前端geojson转shape,并将shape相关文件压缩成zip压缩包并下载
👨⚕️ 主页: gis分享者 👨⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨⚕️ 收录于专栏:mapbox 从入门到精通 文章目录 一、🍀前言1.1 ☘️mapboxgl.Map 地图对象1.2 ☘️mapboxgl.Map style属性1.3 ☘️line线图层样式二、🍀纯前端geojson转…...
Oracle ASM Rebalance Power 了解
Oracle ASM Rebalance Power 了解 基本概念 ASM (Automatic Storage Management) 的 Rebalance Power 参数控制磁盘组重新平衡操作的速度和资源使用。当添加、删除或调整 ASM 磁盘时,ASM 会自动执行重新平衡操作来重新分布数据。 ASM_POWER_LIMIT 参数 作用 控…...
sqlite的拼接字段的方法(sqlite没有convert函数)
我在sqlserver 操作方式: /// <summary>///获取当前门店工资列表/// </summary>/// <param name"wheres">其他条件</param>/// <param name"ThisMendian">当前门店</param>/// <param name"IsNotU…...
深入解析 OpenManus:开源 AI 智能体框架的技术原理与实践
深入解析 OpenManus:开源 AI 智能体框架的技术原理与本地部署指南 在当今人工智能快速发展的时代,智能体(Agent)技术正逐渐成为推动自动化和智能化的关键力量。OpenManus,由 MetaGPT 团队开发的开源 AI 智能体框架&am…...
[面试精选] 0001. 两数之和
文章目录 1. 题目链接2. 题目描述3. 题目示例4. 解题思路5. 题解代码6. 复杂度分析 1. 题目链接 1. 两数之和 - 力扣(LeetCode) 2. 题目描述 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个…...
CAP分布式理论
CAP分布式理论 文章目录 CAP分布式理论事务本地事务定义适用场景优点缺点 分布式事务一、分布式事务的定义二、分布式事务的标准与 CAP 理论的关系1. CAP 理论的核心内容2. CAP 理论对分布式事务的指导意义3. 分布式事务的其他关键标 三、总结:CAP 理论与分布式事务…...
如何管理和优化内核参数
Linux 系统中的内核参数(Kernel Parameters)对系统的性能、安全性和稳定性有很大影响。通过调整内核参数,可以优化系统性能、增强网络能力、调整内存管理等。管理和优化内核参数通常涉及以下几个步骤: 1. 查看当前内核参数 在 L…...
sgRNA的靶基因基因组如何获得? for 下游的 T7E1验证
愿武艺晴小朋友一定得每天都开心! 1)在基因组,靶标区域上下游,设计引物(以Zfp532基因为例): a. NCBI(Home - Gene - NCBI)Gene 页面上输入:Zfp532。 b. 在新…...
人工智能+:职业价值的重构与技能升级
当“人工智能”成为产业升级的标配时,一个令人振奋的就业图景正在展开——不是简单的岗位替代,而是职业价值的重新定义。这场变革的核心在于,AI并非抢走工作机会,而是创造了人类与技术协作的全新工作范式。理解这一范式转换的逻辑…...
【前端开发】Uniapp日期时间选择器:实现分钟动态步长设置
技术栈 Uniapp Vue3 uView年份显示前后一年,分钟动态设置间隔 效果图 主体显示 <view class"uni-row selector" click"openPicker"><uni-icons color"#c0c4cc" type"calendar" size"22"></uni-…...
目标检测DN-DETR(2022)详细解读
文章目录 gt labels 和gt boxes加噪query的构造attention maskIS(InStability)指标 在DAB-Detr的基础上,进一步分析了Detr收敛速度慢的原因:二分图匹配的不稳定性(也就是说它的目标在频繁地切换,特别是在训…...
榕壹云上门家政系统:基于Spring Boot+MySQL+UniApp的全能解决方案
一、项目背景:家政服务行业的数字化升级需求 随着城市化进程加快,居民对上门家政服务的需求持续增长。传统家政行业存在服务效率低、信息不透明、管理成本高的问题,亟需通过数字化工具实现服务标准化、流程自动化。榕壹云上门家政系统应运而…...
目标检测DINO-DETR(2023)详细解读
文章目录 对比去噪训练混合查询选择look forward twice 论文全称为:DETR with Improved DeNoising Anchor Boxes for End-to-End Object Detection 提出了三个新的方法: 首先,为了改进一对一的匹配效果,提出了一种对比去噪训练方法…...
LLM笔记(十)vLLM(1)PagedAttention论文笔记
文章目录 PagedAttention论文笔记论文摘要概览1. 引言问题背景提出的解决方案主要贡献和成果 2. 背景2.1 基于Transformer的大语言模型2.2 LLM服务与自回归生成2.3 LLM的批处理技术 3. LLM服务中的内存挑战3.1 现有系统中的内存管理 4. 方法: PagedAttention 和 vLLMvLLM 系统概…...
5.20 note
不用if else实现递归 原代码 class Solution { public: int mechanicalAccumulator(int target) { if (target 0) return 0; // 终止条件:基准情况 return target mechanicalAccumulator(target - 1); // 递归累加 } }; 变形 class Solution { public: int…...
vuejs处理后端返回数字类型精度丢失问题
标题问题描述 后端返回数据有5.00和3.30这种数据,但是前端展示的时候返回对应分别为5和3.0,小数点后0都丢失了。 接口返回数据展示network-Response: 接口返回数据展示network-Preview: 错误数据效果展示 发现问题 浏览器接口…...
指令烧录ORIN NANO操作系统
1 概述 模组为ORIN NANO 4GB版本 Ubuntu系统为18.04虚拟机 说明:刷机过程会有重新连接USB的操作,烧写过程需要注意虚拟机提示,官方不建议使用虚拟机,建议直接使用ubuntu操作系统的机器。 2 下载烧录所需文件 进入到下载网址&am…...
每日算法刷题Day11 5.20:leetcode不定长滑动窗口求最长/最大6道题,结束不定长滑动窗口求最长/最大,用时1h20min
6. 1695.删除子数组的最大得分(中等) 1695. 删除子数组的最大得分 - 力扣(LeetCode) 思想 1.给你一个正整数数组 nums ,请你从中删除一个含有 若干不同元素 的子数组**。**删除子数组的 得分 就是子数组各元素之 和 。 返回 只删除一个 子…...
List介绍
什么是List 在集合框架中,List是一个接口,继承自Collection Collection也是一个接口,该接口中规范了后序容器中常用的一些方法 Iterable也是一个接口,表示实现该接口的类是可以逐个元素进行遍历的,具体如下࿱…...
List更简洁的编码构建
List的链式构建需求 jdk1.8,编码时需要手动构建一个List 传统List构建方式 - 声明列表,依次添加元素; - 利用Arrays.asList方法声明并添加元素 //1 先声明创建 List<String> createList new ArrayList<>();//2 逐个添加元素 c…...
Java 单元测试框架比较:JUnit、TestNG 哪个更适合你?
Java 单元测试框架比较:JUnit、TestNG 哪个更适合你? 在 Java 开发领域,单元测试是保证代码质量的重要环节。而选择一个合适的单元测试框架,对于提升测试效率和代码可靠性至关重要。本文将深入比较 JUnit 和 TestNG 这两个主流的…...
变频器如何通过Profibus DP主站转Modbus RTU/TCP接入到上位机
变频器如何通过Profibus DP主站转Modbus RTU/TCP接入到上位机 在工业自动化领域,Profibus DP和Modbus RTU是两种常见的通信协议。Profibus DP广泛应用于工厂自动化,而Modbus RTU则常用于串行通信。当需要将支持Profibus DP的设备(如变频器&a…...
ElasticSearch性能优化
ES基础概念介绍: 索引:类似于MySQL中的表,它是具有相同特征的一个数据集。文档:格式为JSON格式,类似于MySQL中的一条数据,它是数据存储的基本数据单元,每一条文档都有一个唯一的ID。查询&#x…...
pom.xml中的runtime
在 Maven 的 pom.xml 文件中,<scope> 元素可以指定依赖项的作用范围,而 runtime 是其中的一个作用范围值。以下是 runtime 作用范围的含义: 定义:runtime 作用范围表示该依赖项在编译时不需要,但在运行时需要。…...
第一章走进java世界
第一章 走进 java 世界 1.1 java 语言的特点(小面经) 使用简单、高效 去掉了 C 和 C++中的指针和多重继承技术通过垃圾自动回收机制简化了程序内存管理对于数据类型在不同字长的计算机上实现统一字节数占用完全面向对象 抽象、封装、继承、多态自动内存管理(Auto Garbage C…...
tigase源码学习笔记-事件总线EventBus
前言 最近看到了一些tigase关于异步事件解耦的地方的设计,做一个笔记记录一下。什么是事件总线,我自己对于事件总线的理解是,事件总线是一个对事件(Event)进行集中处理的基于发布订阅模式的一种处理机制。个人拙见&am…...