场景描述:
在 Linux 服务器上,通过使用 Nginx 实现负载均衡,或者在阿里云直接购买负载均衡,根据配置的转发规则,不同的请求会被转发到其不同的服务器上进行处理。如果遇到需要上传图片的情况,那最后只有其中一台服务器存有这张图片,而其他服务器则没有。随后,如果请求获取这张图片,但是转发到的恰好是没有存有这张图片的服务器,那么请求就失败了。为了避免这类问题,就需要同步相应的目录上的文件。
Lsyncd 简述:
Lsyncd 是一个简单高效的文件同步工具,通过lua语言封装了 inotify 和 rsync 工具,采用了 Linux 内核(2.6.13 及以后)里的 inotify 触发机制,然后通过rsync去差异同步,达到实时的效果。
安装过程:
1、安装 lua 语言依赖包
yum install lua
yum install lua-devel
2、安装 Lsyncd
yum install lsyncd
这里一定要注意,最好安装最新的版本,笔者安装的版本是 2.2.2 。网上很多教程的版本是2.1.5 ,这个版本有 bug ,但在后续的版本里已经修复,直接安装即可。之后,你可以发现在 etc 目录下,不但多了 lsyncd.conf 配置文件,而且还多了 rsync 工具的配置文件 rsyncd.conf 。这说明 Lsyncd 工具确是使用 rsync 工具创建起来的,通过 rsync 去进行目录的差异同步。
远程前提:
通过 Lsyncd 工具同步负载均衡转发规则下的服务器,需要在涉及的服务器上都安装好 Lsyncd ,一般通过 SSH 远程登录,进行远程同步。因此,在远端被同步的服务器上开启 SSH 无密码登录,请注意用户身份,将对应的用户 user 公钥 id_rsa.pub 复制到被同步的服务器的 .ssh 文件目录下的 authorized_keys 文件里,最后测试是否可以无密码登陆。
如果要实现文件的双向同步,那就要对两台服务器进行差不多的 SSH 配置操作,就可以相互进行无密码登陆了。
chmod 600 /user/.ssh/id_rsa
ssh user@192.168.0.3
配置文件:
vi /etc/lsyncd.conf
----
-- User configuration file for lsyncd.
-- Simple example for default rsync, but executing moves through on the target.
-- For more examples, see /usr/share/doc/lsyncd*/examples/
settings{
logfile = "/var/log/lsyncd/lsyncd.log",
statusFile = "/var/log/lsyncd/lsyncd.status",
inotifyMode = "CloseWrite",
maxProcesses = 10,
nodaemon = false,
maxDelays = 7
sync{
default.rsync,
source = "/data/wwwroot/default/application",
target = "user@192.168.0.3:/data/wwwroot/default/application",
init = false,
delete = true,
delay = 3,
rsync = {
binary = "/usr/bin/rsync",
compress = true,
archive = true,
verbose = true
sync{
default.rsync,
source = "/data/wwwroot/default/public",
target = "user@192.168.0.3:/data/wwwroot/default/public",
init = false,
delete = true,
delay = 3,
rsync = {
binary = "/usr/bin/rsync",
compress = true,
archive = true,
verbose = true
}
lsyncd /etc/lsyncd.conf
如果要实现文件的双向同步,那就要对两台服务器进行差不多的 Lsyncd 配置操作,下面列出具体需要更改的参数。
logfile 本地存放 Lsyncd 日志的路径,一般直接使用默认的路径就可以了。
statusFile 本地存放 状态文件的路径
,一般直接使用默认的路径就可以了。
source 本地源目录路径。
target 远程目的目录路径,注意这里的SSH远程同步写法。
其他参数具体解释(略)
注意事项:
运行 Lsyncd 工具后,可以到源目录下创建几个文本,查看是否能成功同步到远程的目的目录下。如果没有成功,可以到 /var/log/lsyncd/lsyncd.log 文件查看详情。
如果配置了 lsyncd.conf 文件,可以不配置 rsyncd.conf 了。
操作环境:
Linux version 3.10.0-693.11.6.el7.x86_64 (builder@kbuilder.dev.centos.org) (gcc version 4.8.5 20150623 (Red Hat 4.8.5-16) (GCC) ) #1 SMP Thu Jan 4 01:06:37 UTC 2018
附(lua语言配置示例,可忽略不看):
lalarm.lua
-----
-- User configuration file for lsyncd.
-- While this example does not do anything it shows
-- how user custom alarms can be now. It will log
-- "Beep!" every 5 seconds.
settings.nodaemon = true
local function noAction (inlet)
-- just discard any events that happes in source dir.
inlet.discardEvent(inlet.getEvent())
-----
-- Adds a watch to some not so large directory for this example.
local in1 = sync{source="/usr/local/etc/", action = noAction }
local function myAlarm(timestamp, extra)
log("Normal", extra.message)
spawn(extra.inlet.createBlanketEvent(), "/bin/echo", extra.message)
alarm(timestamp + 5, myAlarm, extra)
alarm(now() + 5, myAlarm, {inlet = in1, message = "Beep"})
lbash.lua
-----
-- User configuration file for lsyncd.
-- This example uses local bash commands to keep two local
-- directory trees in sync.
settings {
logfile = "/tmp/lsyncd.log",
statusFile = "/tmp/lsyncd.stat",
statusIntervall = 1,
nodaemon = true,
-----
-- for testing purposes. prefix can be used to slow commands down.
-- prefix = "sleep 5 && "
prefix = ""
-----
-- for testing purposes. uses bash command to hold local dirs in sync.
bash = {
delay = 0,
maxProcesses = 1,
-- calls `cp -r SOURCE/* TARGET` only when there is something in SOURCE
-- otherwise it deletes contents in the target if there.
onStartup = [[
if [ "$(ls -A ^source)" ]; then
cp -r ^source* ^target;
if [ "$(ls -A ^target)" ]; then rm -rf ^target/*; fi
fi]],
onCreate = prefix..[[cp -r ^sourcePath ^targetPathdir]],
onModify = prefix..[[cp -r ^sourcePath ^targetPathdir]],
onDelete = prefix..[[rm -rf ^targetPath]],
onMove = prefix..[[mv ^o.targetPath ^d.targetPath]],
sync{bash, source="src", target="/path/to/trg/"}
lecho.lua
-----
-- User configuration file for lsyncd.
-- This example uses just echos the operations
-----
-- for testing purposes. just echos what is happening.
echo = {
maxProcesses = 1,
delay = 1,
onStartup = "/bin/echo telling about ^source",
onAttrib = "/bin/echo attrib ^pathname",
onCreate = "/bin/echo create ^pathname",
onDelete = "/bin/echo delete ^pathname",
onModify = "/bin/echo modify ^pathname",
onMove = "/bin/echo move ^o.pathname -> ^d.pathname",
sync{echo, source="src", target="/path/to/trg/"}
lftp.lua
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- User configuration file for lsyncd.
-- Syncs with 'lftp'.
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
lftp = {
-----
-- Spawns rsync for a list of events
action = function(inlet)
-- gets all events ready for syncing
local elist = inlet.getEvents(
function(event)
return event.etype ~= 'Init' and event.etype ~= 'Blanket'
-----
-- replaces filter rule by literals
local function sub(p)
if not p then
return
return p:gsub('%?', '\\?'):
gsub('%*', '\\*'):
gsub('%[', '\\['):
gsub('%]', '\\]')
local config = inlet.getConfig()
local commands = elist.getPaths(
function(etype, path1, path2)
if etype == 'Delete' then
if string.byte(path1, -1) == 47 then
return 'rm -r '..
config.targetdir..sub(path1)
return 'rm '..
config.targetdir..sub(path1)
elseif
etype == 'Create' or
etype == 'Modify' or
etype == 'Attrib'
if string.byte(path1, -1) == 47 then
return 'mirror -R '..
config.source..sub(path1)..' '..
config.targetdir..sub(path1)
return 'put '..
config.source..sub(path1)..
' -o '..config.targetdir..sub(path1)
if #commands == 0 then
spawn(elist, '/bin/true')
return
commands = table.concat(commands, ';\n')
log('Normal', 'Calling lftp with commands\n', commands)
spawn(elist, '/usr/bin/lftp',
'<', commands,
'-u', config.user..','..config.pass, config.host
-----
-- Spawns the recursive startup sync
init = function(event)
local config = event.config
local inlet = event.inlet
local excludes = inlet.getExcludes()
local delete = nil
if config.delete then delete = { '--delete', '--ignore-errors' }; end
if #excludes ~= 0 then
error('lftp does not work with excludes', 4)
log('Normal', 'recursive startup lftp: ', config.source, ' to host: ', config.host)
spawn(event, '/usr/bin/lftp',
'-c',
'open -u '..config.user..','..config.pass..' '..config.host..'; '..
'mirror -R -e '..config.source..' '..config.targetdir..';'
-----
-- Checks the configuration.
prepare = function(config)
if not config.host then
error('lftps needs "host" configured', 4);
if not config.user then
error('lftps needs "user" configured', 4);
if not config.pass then
error('lftps needs "pass" configured', 4);
if not config.targetdir then
error('lftp needs "targetdir" configured', 4)
if config.target then
error('lftp needs NOT "target" configured', 4)
if config.exclude then
error('lftp does not work with excludes', 4)
if config.rsyncOpts then
error('lftp needs NOT "rsyncOpts" configured', 4)
if string.sub(config.targetdir, -1) == '/' then
error('please make targetdir not end with a /', 4)
-----
-- Exit codes for rsync.
exitcodes = {
[ 0] = 'ok',
[ 1] = 'ok',
-----
-- Default delay
delay = 1,
sync{
lftp,
host = 'localhost',
user = 'test',
pass = 'test',
source = 'src',
targetdir = '.',
}
lgforce.lua
-----
-- User configuration file for lsyncd.
-- This example refers to one common challenge in multiuser unix systems.
-- You have a shared directory for a set of users and you want
-- to ensure all users have read and write permissions on all
-- files in there. Unfortunally sometimes users mess with their
-- umask, and create files in there that are not read/write/deleteable
-- by others. Usually this involves frequent handfixes by a sysadmin,
-- or a cron job that recursively chmods/chowns the whole directory.
-- This is another approach to use lsyncd to continously fix permissions.
-- One second after a file is created/modified it checks for its permissions
-- and forces group permissions on it.
-- This example regards more the handcraft of bash scripting than lsyncd.
-- An alternative to this would be to load a Lua-Posix library and do the
-- permission changes right within the onAction handlers.
-- forces this group.
fgroup = "staff"
-----
-- script for all changes.
command =
-- checks if the group is the one enforced and sets them if not
perm=`stat -c %A ^sourcePathname`
if [ `stat -c %G ^sourcePathname` != ]]..fgroup..[[ ]; then
/bin/chgrp ]]..fgroup..[[ ^sourcePathname || /bin/true;
]] ..
-- checks if the group permissions are rw and sets them
if [ `expr match $perm "....rw"` == 0 ]; then
/bin/chmod g+rw ^sourcePathname || /bin/true;
]] ..
-- and forces the executable bit for directories.
if [ -d ^sourcePathname ]; then
if [ `expr match $perm "......x"` == 0 ]; then
/bin/chmod g+x ^^sourcePathname || /bin/true;
-- on startup recursevily sets all group ownerships
-- all group permissions are set to rw
-- and to executable flag for directories
-- the carret as first char tells Lsycnd to call a shell altough it
-- starts with a slash otherwisw
startup =
[[^/bin/chgrp -R ]]..fgroup..[[ ^source || /bin/true &&
/bin/chmod -R g+rw ^source || /bin/true &&
/usr/bin/find ^source -type d | xargs chmod g+x
gforce = {
maxProcesses = 99,
delay = 1,
onStartup = startup,
onAttrib = command,
onCreate = command,
onModify = command,
-- does nothing on moves, they won't change permissions
onMove = true,
sync{gforce, source="/path/to/share"}
limagemagic.lua
----
-- Lsyncd user-script that creates a "magic" image converter directory.
-- This configuration will automatically convert all images that are placed
-- in the directory 'magicdir' all resulting images are placed in the same
-- directory!
-- Be sure to mkdir 'magicdir' first.
-----
-- Fileformats: .jpg .gif .png
local formats = { jpg=true, gif=true, png=true, }
convert = {
delay = 0,
maxProcesses = 99,
action = function(inlet)
local event = inlet.getEvent()
if event.isdir then
-- ignores events on dirs
inlet.discardEvent(event)
return
-- extract extension and basefilename
local p = event.pathname
local ext = string.match(p, ".*%.([^.]+)$")
local base = string.match(p, "(.*)%.[^.]+$")
if not formats[ext] then
-- an unknown extenion
log("Normal", "not doing something on ."..ext)
inlet.discardEvent(event)
return
-- autoconvert on create and modify
if event.etype == "Create" or event.etype == "Modify" then
-- builds one bash command
local cmd = ""
-- do for all other extensions
for k, _ in pairs(formats) do
if k ~= ext then
-- excludes files to be created, so no
-- followup actions will occur
inlet.addExclude(base..'.'..k)
if cmd ~= "" then
cmd = cmd .. " && "
cmd = cmd..
'/usr/bin/convert "'..
event.source..p..'" "'..
event.source..base..'.'..k..
'" || /bin/true'
log("Normal", "Converting "..p)
spawnShell(event, cmd)
return
-- deletes all formats if you delete one
if event.etype == "Delete" then
-- builds one bash command
local cmd = ""
-- do for all other extensions
for k, _ in pairs(formats) do
if k ~= ext then
-- excludes files to be created, so no
-- followup actions will occur
inlet.addExclude(base..'.'..k)
if cmd ~= "" then
cmd = cmd .. " && "
cmd = cmd..
'rm "'..event.source..base..'.'..k..
'" || /bin/true'
log("Normal", "Deleting all "..p)
spawnShell(event, cmd)
return
-- ignores other events.
inlet.discardEvent(event)
-----
-- Removes excludes when convertions are finished
collect = function(event, exitcode)
local p = event.pathname
local ext = string.match(p, ".*%.([^.]+)$")
local base = string.match(p, "(.*)%.[^.]+$")
local inlet = event.inlet
if event.etype == "Create" or
event.etype == "Modify" or
event.etype == "Delete"
for k, _ in pairs(formats) do
inlet.rmExclude(base..'.'..k)
-----
-- Does not collapse anything
collapse = function()
return 3
sync{convert, source="magicdir", subdirs=false}
lpostcmd.lua
-----
-- User configuration file for lsyncd.
-- This needs lsyncd >= 2.0.3
-- This configuration will execute a command on the remote host
-- after every successfullycompleted rsync operation.
-- for example to restart servlets on the target host or so.
local rsyncpostcmd = {
-- based on default rsync.
default.rsync,
checkgauge = {
default.rsync.checkgauge,
host = true,
targetdir = true,
target = true,
postcmd = true,
-- for this config it is important to keep maxProcesses at 1, so
-- the postcmds will only be spawned after the rsync completed
maxProcesses = 1,
-- called whenever something is to be done
action = function(inlet)
local event = inlet.getEvent()
local config = inlet.getConfig()
-- if the event is a blanket event and not the startup,
-- its there to spawn the webservice restart at the target.
if event.etype == "Blanket" then
-- uses rawget to test if "isPostcmd" has been set without
-- triggering an error if not.
local isPostcmd = rawget(event, "isPostcmd")
if isPostcmd then
spawn(event, "/usr/bin/ssh",
config.host, config.postcmd)
return
-- this is the startup, forwards it to default routine.
return default.rsync.action(inlet)
error("this should never be reached")
-- for any other event, a blanket event is created that
-- will stack on the queue and do the postcmd when its finished
local sync = inlet.createBlanketEvent()
sync.isPostcmd = true
-- the original event is simply forwarded to the normal action handler
return default.rsync.action(inlet)
-- called when a process exited.
-- this can be a rsync command, the startup rsync or the postcmd
collect = function(agent, exitcode)
-- for the ssh commands 255 is network error -> try again
local isPostcmd = rawget(agent, "isPostcmd")
if not agent.isList and agent.etype == "Blanket" and isPostcmd then
if exitcode == 255 then
return "again"
return
--- everything else, forward to default collection handler
return default.collect(agent,exitcode)
error("this should never be reached")
-- called before anything else
-- builds the target from host and targetdir
prepare = function(config, level, skipTarget)
if not config.host then
error("rsyncpostcmd neets 'host' configured", 4)
if not config.targetdir then
error("rsyncpostcmd needs 'targetdir' configured", 4)
if not config.target then
config.target = config.host .. ":" .. config.targetdir
return default.rsync.prepare(config, level, skipTarget)
sync {
rsyncpostcmd,
source = "src",
host = "beetle",
targetdir = "/path/to/trg",
postcmd = "/usr/local/bin/restart-servelt.sh",
}
lrsync.lua
----
-- User configuration file for lsyncd.
-- Simple example for default rsync.
settings {
statusFile = "/tmp/lsyncd.stat",
statusInterval = 1,
sync{
default.rsync,
source="src",
target="trg",
}
lrsyncssh.lua
----
-- User configuration file for lsyncd.
-- Simple example for default rsync, but executing moves through on the target.
sync{default.rsyncssh, source="src", host="localhost", targetdir="dst/"}
lsayirc.lua
-----
-- An Lsyncd+IRC-Bot Config
-- Logs into an IRC channel and tells there everything that happens in the
-- watched directory tree.
-- The challenge coding Lsyncd configs taking use of TCP sockets is
-- that they must not block! Otherwise Lsyncd will block, no longer
-- empty the kernels monitor queue, no longer collecting zombie processes,
-- no longer spawning processes (this example doesnt do any, but maybe you
-- might want to do that as well), blocking is just bad.
-- This demo codes just minimal IRC functionality.
-- it does not respond to anything else than IRC PING messages.
-- There is no flood control, if a lot happens the IRC server will disconnect
-- the bot.
-- Requires "luasocket" to be installed
require("socket")
-- For demo reasons, do not detach
settings.nodaemon = true
hostname = "irc.freenode.org"
--hostname = "127.0.0.1"
port = 6667
nick = "lbot01"
chan = "##lfile01"
-- this blocks until the connection is established
-- for once lets say this ok since Lsyncd didnt yet actually
-- start.
local ircSocket, err = socket.connect(hostname, port)
if not ircSocket then
log("Error", "Cannot connect to IRC: ", err)
terminate(-1)
-- from now on, the socket must not block!
ircSocket:settimeout(0)
-- Buffers for stuff to send and receive on IRC:
local ircWBuf = ""
local ircRBuf = ""
-- Predeclaration for functions calling each other
local writeIRC
-----
-- Called when the IRC socket can be written again.
-- This happens when writeIRC (see below) couldnt write
-- its buffer in one go, call it again so it can continue its task.
local function ircWritey(fd)
writeIRC()
-- Called when there is data on the socket
local function ircReady(socket)
local l, err, ircRBuf = ircSocket:receive("*l", ircRBuf)
if not l then
if err ~= "timeout" then
log("Error", "IRC connection failed: ", err)
terminate(-1)
ircRBuf = ""
log("Normal", "ircin :", l)
--- answers ping messages
local ping = l:match("PING :(.*)")
if ping then
writeIRC("PONG :", ping, "\n")
-----
-- Writes on IRC socket
-- Do not forget to add an "/n".
function writeIRC(...)
-- Appends all arbuments into the write buffer
ircWBuf = ircWBuf..table.concat({...})
-- Gives it to the socket and sees how much it accepted
local s, err = ircSocket:send(ircWBuf)
-- If it cant the socket terminated.
if not s and err~="timeout" then
log("Error", "IRC connection failed: ", err)
terminate(-1)
--- logs what has been send, without the linefeed.
if (ircWBuf:sub(s, s) == "\n") then
log("Normal", "ircout:", ircWBuf:sub(1, s - 1))
log("Normal", "ircout: ", ircWBuf:sub(1, s), "\\")
---- reduces the buffer by the amount of data sent.
ircWBuf = ircWBuf:sub(s + 1, -1)
-- when the write buffer is empty tell the core to no longer
-- call ircWritey if data can be written on the socket. There
-- is nothing to be written. If there is data in the buffer
-- asks to be called as soon it can be written again
if ircWBuf == "" then
observefd(ircSocket:getfd(), ircReady, nil)
observefd(ircSocket:getfd(), ircReady, ircWritey)
-- Aquires the nick on IRC and joins the configured channel
-- This will also register the ircReady/ircWritey function at the core
-- to be called when the socket is ready to be read/written.
writeIRC("NICK ", nick, "\n")
writeIRC("USER ", nick, " 0 * :lsyncd-sayirc-bot", "\n")
writeIRC("JOIN ", chan, "\n")
-- As action tells on IRC what the action is, then instead of
-- spawning somthing, it discards the event.
local function action(inlet)
-- event2 is the target of a move event
local event, event2 = inlet.getEvent()
if not event2 then
writeIRC("PRIVMSG ",chan," :",event.etype," ",
event.path, "\n")
writeIRC("PRIVMSG ",chan," :",event.etype," ",
event.path," -> ",event2.path, "\n")
inlet.discardEvent(event)
-- Watch a directory, and use a second for delay to aggregate events a little.
sync{source = "src",
action = action,
delay = 1,
onMove = true}
转载本文,请注明出处、作者。
rsync可实现文件的同步/备份,安装配置移步linux下rsync备份/同步文件lsyncd实现了触发式或定时通知事件,可以近实时的同步文件(封装了rsync),github地址:https://g...
来自:
jam00的博客
Lsyncd监视本地目录树事件监视器接口(inotify或fsevents)。它聚合并将事件组合在一起几秒钟,然后生成一个(或多个)进程来同步这些更改。默认情况下,由rsync实现同步。因此,Lsyn...
来自:
Linuxprobe18的博客
rsync+lsyncd实现文件实时同步yum-yinstallrsyncd(同步端、被同步端都需要安装)1.提供lsyncd的安装源rpm-ivhhttp://dl.fedoraproject.or...
来自:
mager的专栏
转载自:http://seanlook.com/2015/05/06/lsyncd-synchronize-realtime/ https://blog.csdn.net/magerguo/ar...
来自:
ZERO
1.利用ssh+rsync 只需要在服务器端打开ssh服务,并启动xinetd中rsync服务则可使用 a.增量同步 rsync-av/src-dir/. user@ipadress:/dest-d...
来自:
Terry Tsang
1、描述,,Lsyncd+ssh 开源lsyncd采用inotify原理监听某一个目录,如果目录内发生变化,利用rsync协议自动同步多服务器,因此lsyncd是一个轻量级的实时镜像解决方案。 ...
来自:
lwh9606的博客
安装lsyncdwget-P/etc/yum.repos.d/http://mirrors.aliyun.com/repo/epel-6.repoyuminstall-ylsyncdvim/etc/l...
来自:
junweicn的博客
1.几大实时同步工具比较1.1inotify+rsync最近一直在寻求生产服务服务器上的同步替代方案,原先使用的是inotify+rsync,但随着文件数量的增大到100W+,目录下的文件列表就达20...
来自:
crx05的专栏
Rsync简介rsync是类unix系统下的数据镜像备份工具——remotesync。一款快速增量备份工具RemoteSync,远程同步支持本地复制,或者与其他SSH、rsync主机同步。Rsync传...
来自:
静静是我女朋友
在通常的情况下业务系统的产品在架构的时候都会考虑到将用户可能上传的文件全部上传到同一个源,可以是数据库、httpserver、ftpserver等,这样保证了数据源的唯一,在引用时就会保证一致性。下面...
来自:
小小竹排江中流
lsyncd可以达到的要求:1.采用开源软lsyncd采用inotify原理监听某一目录,如果目录内发生增、删、改、利用rsync协议自动同步到多服务器。2.inotify,从kernel2.6.13...
来自:
良玉的博客 http://blog.uouo123.com/,欢迎收录
两台服务器间的双向文件同步完整后,要完成3台及以上服务器的双向同步问题,就要来画图说明了。图中箭头所指的方向表示指向方执行定时任务以向被指向方双向同步文件;如图中Aapp1指向了app2则由app1执...
来自:
小小竹排江中流
注:转载请注明出处,并请保持文章的完整性。 如果你有多台计算机,并且你希望它们的某些目录保持一致(例如,你经常更改文件的目录),那么如果用手工复制、粘贴的方法,就太没有效率了,文件夹多的话,能把你累...
来自:
编码无悔
大数据最广泛的一个应用场景就是构建数据仓库,数据仓库中的数据生命周期一般包括:数据的获取,数据的分类,数据的解析清洗,上传到hdfs。或多或少,主要都是这几个过程,asiainfo这边的离线分析的...
来自:
Java_Soldier的博客
前言文章参考价值:初步了解进程、线程和协程,三者的特点和应用上的区别。进程、线程和协程的区别进程:充分利用多CPU线程:充分利用多核(达到真正的多任务并行)协程:充分利用单核(充分挖掘不断提高性能的单...
来自:
weixin_39584864的博客
每天都去接触一些新的问题,生活就会少一些问题,来吧,让我们在技术的路上一探到底吧进程拥有自己独立的堆和栈,既不共享堆,亦不共享栈,进程由操作系统调度。线程拥有自己独立的栈和共享的堆,共享堆,不共享栈,...
来自:
liu_zhuang_love的专栏
环境:主192.168.2.191备192.168.2.1931,在备服务器上安装rsync和xinetdyuminstallrsyncxinetd配置xinetdvim/etc/xinetd.d/r...
来自:
su4416160的博客
一、进程 进程,直观点说,保存在硬盘上的程序运行以后,会在内存空间里形成一个独立的内存体,这个内存体有自己的地址空间,有自己的堆,上级挂靠单位是操作系统。操作系统会以进程为单位,分配系统资源,所以我...
来自:
青萍之末的博客
参考:http://moqiang02.iteye.com/blog/2107473IP:120.77.244.96IP:47.92.27.140客户端A安装rsync+inotify-tools主服...
来自:
xiaosevenliang的专栏
由于在搞网站,最近要开始负载均衡架构方面的探索,对于资源同步方面,自己折腾的一个解决方案的Demo
目前demo可实现全内网环境中,Master(client)通过socket方式(ip地址,端口)连接多台Slave(server),调...
lsyncd全称是LiveSyncing(Mirror)Daemon,它是一款能实时同步本地文件或目录到远端的机器, 它的工作原理:监视本地的目录,当源数据有文件或目录更新时,更新本地文件或目录到远端...
来自:
流云随风
使用lsyncd+rsync实现linux服务器间的实时同步环境:源服务器:192.168.241.11,centos7-1804目标服务器:192.168.241.12,centos7-1611一、...
来自:
guan0005的博客
转载声明:http://blog.csdn.net/sever2012/article/details/7531615一.环境准备两台linux主机,操作系统为ubuntu10.04:一台作为rsyn...
来自:
极客点儿
负载均衡----文件服务策略客串:屌丝的坑人表单神器、数据库那点事儿面向对象升华:面向对象的认识----新生的初识、面向对象的番外----思想的梦游篇(1)、面向对象的认识---如何找出类PHP项目起...
目的使用lsyncd+ssh实现两台服务器之间目录的同步;环境Centos6.4lsyncd2.1.5安装配置配置SSH无密码访问在ServerA上执行#ssh-keygen-trsa#cat~/.s...
来自:
bobpen的专栏
官网开源地址https://github.com/axkibe/lsyncd官网配置手册https://axkibe.github.io/lsyncd/简介Lysncd实际上是lua语言封装了inot...
来自:
weixin_33774308的博客
研究了两天也没找到个很好的办法,这里记录一下研究过的办法以及提出一个设想 1,inotify-tools+rsync 使用inotify-watch监视文件夹,有改动即执行rsync 安装使用...
来自:
Arthur的随笔
只能完成单向 (a--》b是成功的) 但反过来始终不成功的(从b到a 失败), 最终没有完成任务 ,结果搞成了单向。 1a--》b是成功的 2 从b到a 失败 错误提示如下 ysql> slave s
lsyncd配置方式很简单,lua本身就是一种配置语言,可读性非常强。lsyncd也有多种工作模式可以选择,本地目录cp,本地目录rsync,远程目录rsyncssh。2.使用lsyncd本地目录实时...
来自:
u012718713的专栏
php安装swoole1.下载swoole安装```wgethttp://pecl.php.net/get/swoole-1.9.1.tgztar-zxvfswoole-1.9.1.tgzcdswoo...
来自:
亮
两台服务器间的文件同步是最简单的,也是多台服务器间同步的基础。笔者参考了一篇使用Unison工具进行文件双向同步的文章,并用自己的实践加以改版如下Linux系统间文件双向同步搭建Unison版一、Un...
来自:
小小竹排江中流
unison+inotify实现文件实时双向同步部署步骤一.编译安装unisonunison各版本下载地址http://www.seas.upenn.edu/~bcpierce/unison//dow...
来自:
u010154380的专栏
需求:需要98和99互相同步,现在先以98为Master,99为Slave,98-&amp;amp;amp;amp;amp;amp;gt;99。9899sersyncrsync/data/98...
来自:
ha_123_qq的博客
使用nginx进行负载均衡后(使用ip_hash;策略),存在一个问题,有A、B两台服务器,使用相同的数据库,用户访问被分配到了A服务器,成功上传一张照片,刷新后在A服务器可以看到;但是连接B服务器的...
来自:
记事本
一、为什么要用Rsync+sersync架构?1、sersync是基于Inotify开发的,类似于Inotify-tools的工具2、sersync可以记录下被监听目录中发生变化的(包括增加、删除、修...
来自:
阿吉的技术总结博客
一、概述一般rsync软件是通过crond这支后台进行(计划任务)来实现自动同步数据,如今已有更好的开源软件来代替使用crond了,那就是lsyncd(LiveSyncing(Mirror)Daemo...
来自:
胡亮的专栏
读到本文前总以为id重复需要修改程序才能解决,原来mysql本身为我们提供了这个功能,自己太小白了!!!解决多台写服务器主自增长ID重复问题,值得参考,希望对大家所帮助。二台Mysql服务器,他们的I...
来自:
云枫的专栏
首先配置:ssh免密码登录ssh免密码登录同步脚本:/usr/bin/rsync-avz/datamnt/dbbackup/root@hostname:/datamnt/dbbackup/>>/dat...
来自:
偶是一只小小鸟~
前提:两台ubuntu服务器,且两台服务器之间通信正常。服务器需要同步的文件做好备份。两台服务器IP分别为:192.168.1.20 和 192.168.1.30首先,用lsof -i:873命令,查...
来自:
心随梦飞
此次测试使用三台服务器,CentOS7(1511)版本:192.168.254.1 web服务器+线上测试环境+源站192.168.254.2 web服务器192.168.254.3 web服务器 其...
来自:
勤能补拙
Linux系统间文件双向同步搭建Unison版 一、Unison简介 Unison是Windows、Linux以及其他Unix平台下都可以使用的文件同步工具,它能使两个文件夹(本地或网络上的)保持内容...
来自:
qq_35912734的博客
负载均衡----文件服务策略客串:屌丝的坑人表单神器、数据库那点事儿面向对象升华:面向对象的认识----新生的初识、面向对象的番外----思想的梦游篇(1)、面向对象的认识---如何找出类PHP项目起...
来自:
苦海无涯的博客
1. 例如:用户点击了导出,文件生成都服务器上了。但是服务器做了负载均衡,文件现在生成到了A服务器,但是但用户看到提示文件导出成功提示后,用户在去点击下载文件的时候 却到了B服务器,结果返回了空文件。
环境:CENTOS安装REDISyuminstall-yredisphp-redisserviceredisstartchkconfigresdison负载均衡的代码主/从rsync定时同步A服务器(...
来自:
echobar的博客
转载地址http://ask.supermap.com http://blog.csdn.net/supermapsupport/article/details/51752272...
来自:
shen_zhu的博客
aapt即Android Asset Packaging Tool.本文小结了一下该工具的用法。
1. aapt l[ist] [-v] [-a] file.{zip,ja...
来自:
苦练杀敌本领
一、概述最近在springboot项目引入thymeleaf模板时,使用非严格标签时,运行会报错。默认thymeleaf模板对html5标签是严格检查的。二、在项目中加NekoHTML库在Maven中...
来自:
Luck_ZZ的博客
nginx是个好东西,Nginx (engine x) 是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器。Nginx是由伊戈尔·赛索耶夫为俄罗斯访问量第二的Rambl...
来自:
maoyuanming0806的博客
一、代理模式为某个对象提供一个代理,从而控制这个代理的访问。代理类和委托类具有共同的父类或父接口,这样在任何使用委托类对象的地方都可以使用代理类对象替代。代理类负责请求的预处理、过滤、将请求分配给委托...
来自:
小小本科生成长之路
天地图2.0(http://www.chinaonmap.com)于2013年3月份上线,基本情况如下:
1) 基于OGC的WMTS 1.0.0版本;
2) 提供矢量地图、影像地图和地...
来自:
ArcGIS产品与技术专栏
微信小程序wx.uploadfile, 利用接口把本地图片转化为base64流.
网上到处都是粘贴复制的wx.uploadfile的解决方案, 但目前还没有具体的代码:
特意呈现出来给需要的伙伴们:...
来自:
Websites
更多代码请见:https://github.com/xubo245/SparkLearning 版本:Spark-2.0.01解释
从【2】中下载release版,idea打开mvn packag...
来自:
Keep Learning
Java中的ThreadLocal类允许我们创建只能被同一个线程读写的变量。因此,如果一段代码含有一个ThreadLocal变量的引用,即使两个线程同时执行这段代码,它们也无法访问到对方的Thread...
来自:
u011860731的专栏
作者:fbysssmsn:jameslastchina@hotmail.com blog:blog.csdn.net/fbysss声明:本文由fbysss原创,转载请注明出处关键字:tomcat监控...
来自:
fbysss的专栏
本帖慢慢扩充……1. 假设是实现namespace Abc中的一个class,不要因为是在.cc中就肆无忌惮的在global scope或者namespace Abc{}中定义辅助变量和函数,或者ty...
1.Loom的原理Loom继承自MonoBehaviour,在Unity流程管理中Update方法下检查需要回调的Action进行加锁并回调,确保在主线程执行,回调序列本身又作为静态数据保存,在任意线...
来自:
wlz1992614的专栏
最近在搞一些东西,例如WebService,参考了很多教程,但是毕竟每一个环境都有不一样的问题,在此记录下我在开发这个过程当中遇到的一些问题。工具:IntelliJ IDEA 15.0.4
IDEA...
来自:
吴林
问题场景描述整个项目通过Maven构建,大致结构如下:
核心Spring框架一个module spring-boot-base
service和dao一个module server-core
提供系统...
来自:
开发随笔
Nginx启动失败,80端口已被占用
weixin_39636098:
一直杀重启后又有另一个pid占用了呢,已经杀了好几个占用80端口的pid了,重启后还是有[code=java]
[/code]