- 浏览: 837332 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
zjhzwx1212:
为什么用threadLocal后,输出值是从20开始的,而定义 ...
j2ee的线程安全--threadlocal -
aeoluspu:
不错 mysql 测试部分感觉不详细
用sysbench(或者super-smack)测试mysql性能 -
nanPrivate:
有没有例子,只理论,实践起来还是不会啊
JMS可靠消息传送 -
lwclover:
一个网络工程师 装什么b
postfix 如何删除队列中的邮件 -
maimode:
我也欠缺不少啊
理想的计算机科学知识体系
传统的文件同步方案有rsync(单向) 和 unison(双向)等,它们需要扫描所有文件后进行比对,差量传输。如果文件数量达到了百万甚至千万量级,扫描所有文件将非常耗时。而且正在发生变化的往往是其中很少的一部分,这是非常低效的方式。
之前看了Amazon的Dynamo的设计文档,它们每个节点的数据是通过Hash Tree来实现同步,既有通过日志来同步的软实时特点(msyql, bdb等),也可以保证最终数据的一致性(rsync, unison等)。Hash Tree的大体思路是将所有数据存储成树状结构,每个节点的Hash是其所有子节点的Hash的Hash,叶子节点的Hash是其内容的Hash。这样一旦某个节点发生变化,其Hash的变化会迅速传播到根节点。需要同步的系统只需要不断查询跟节点的hash,一旦有变化,顺着树状结构就能够在logN级别的时间找到发生变化的内容,马上同步。
文件系统天然的是树状结构,尽管不是平衡的数。如果文件的修改时间是可靠的,可以表征文件的变化,那就可以用它作为文件的Hash值。另一方面,文件的修改通常是按顺序执行的,后修改的文件比早修改的文件具有更大的修改时间,这样就可以把一个目录内的最大修改时间作为它的修改时间,以实现Hash Tree。这样,一旦某个文件被修改,修改时间的信息就会迅速传播到根目录。
一般的文件系统都不是这样做的,目录的修改时间表示的是目录结构最后发生变化的时间,不包括子目录,否则会不堪重负。因为我们需要自己实现这个功能,利用Linux 2.6内核的新特性inotify获得某个目录内文件发生变化的信息,并把其修改时间传播到它的上级目录(以及再上级目录)。Python 有 pyinotify,watch.py的代码如下:
- #!/usr/bin/python
- from pyinotify import *
- import os, os.path
- flags = IN_CLOSE_WRITE|IN_CREATE|IN_Q_OVERFLOW
- dirs = {}
- base = '/log/lighttpd/cache/images/icon/u241'
- base = 'tmp'
- class UpdateParentDir(ProcessEvent):
- def process_IN_CLOSE_WRITE(self, event):
- print 'modify', event.pathname
- mtime = os.path.getmtime(event.pathname)
- p = event.path
- while p.startswith(base):
- m = os.path.getmtime(p)
- if m < mtime:
- print 'update', p
- os.utime(p, (mtime,mtime))
- elif m > mtime:
- mtime = m
- p = os.path.dirname(p)
- process_IN_MODIFY = process_IN_CLOSE_WRITE
- def process_IN_Q_OVERFLOW(self, event):
- print 'over flow'
- max_queued_events.value *= 2
- def process_default(self, event):
- pass
- wm = WatchManager()
- notifier = Notifier(wm, UpdateParentDir())
- dirs.update(wm.add_watch(base, flags, rec=True, auto_add=True))
- notifier.loop()
<textarea class="Python" style="display: none;" cols="80" rows="40" name="code" readonly="65535">#!/usr/bin/python from pyinotify import * import os, os.path flags = IN_CLOSE_WRITE|IN_CREATE|IN_Q_OVERFLOW dirs = {} base = '/log/lighttpd/cache/images/icon/u241' base = 'tmp' class UpdateParentDir(ProcessEvent): def process_IN_CLOSE_WRITE(self, event): print 'modify', event.pathname mtime = os.path.getmtime(event.pathname) p = event.path while p.startswith(base): m = os.path.getmtime(p) if m < mtime: print 'update', p os.utime(p, (mtime,mtime)) elif m > mtime: mtime = m p = os.path.dirname(p) process_IN_MODIFY = process_IN_CLOSE_WRITE def process_IN_Q_OVERFLOW(self, event): print 'over flow' max_queued_events.value *= 2 def process_default(self, event): pass wm = WatchManager() notifier = Notifier(wm, UpdateParentDir()) dirs.update(wm.add_watch(base, flags, rec=True, auto_add=True)) notifier.loop() </textarea>
在已经有Hash Tree的时候,同步就比较简单了,不停地获取根目录的修改时间并顺着目录结构往下找即可。需要注意的是,在更新完文件后,需要设置修改时间为原文件的修改时间,目录也是,保证Hash Tree的一致性,否则没法同步。mirror.py的代码如下
- #!/usr/bin/python
- import sys,time,re,urllib
- import os,os.path
- from os.path import exists, isdir, getmtime
- src = sys.argv[1]
- dst = sys.argv[2]
- def local_mirror(src, dst):
- if exists(dst) and mtime == getmtime(dst):
- return
- if not isdir(src):
- print 'update:', dst
- open(dst,'wb').write(open(src).read())
- else:
- if not exists(dst):
- os.makedirs(dst)
- for filename in os.listdir(src):
- local_mirror(os.path.join(src,filename), os.path.join(dst,filename))
- os.utime(dst, (mtime,mtime))
- def get_info(path):
- f = urllib.urlopen(path)
- mtime = f.headers.get('Last-Modified')
- if mtime:
- mtime = time.mktime(time.strptime(mtime, '%a, %d %b %Y %H:%M:%S %Z'))
- content = f.read()
- f.close()
- return int(mtime), content
- p = re.compile(r'([\d.]+?) +([\w/]+)')
- def remote_mirror(src, dst):
- mtime, content = get_info(src)
- if exists(dst) and mtime == int(getmtime(dst)):
- return
- print 'update:', dst, src
- if not src.endswith('/'):
- open(dst,'wb').write(content)
- else:
- if not exists(dst):
- os.makedirs(dst)
- for mt,filename in p.findall(content):
- mt = int(float(mt))
- lpath = dst+filename
- if not exists(lpath) or int(getmtime(lpath)) != mt:
- remote_mirror(src+filename, lpath)
- os.utime(dst, (mtime,mtime))
- if src.startswith('http://'):
- mirror = remote_mirror
- else:
- mirror = local_mirror
- while True:
- mirror(src, dst)
- time.sleep(1)
<textarea class="Python" style="display: none;" cols="80" rows="60" name="code" readonly="65535">#!/usr/bin/python import sys,time,re,urllib import os,os.path from os.path import exists, isdir, getmtime src = sys.argv[1] dst = sys.argv[2] def local_mirror(src, dst): if exists(dst) and mtime == getmtime(dst): return if not isdir(src): print 'update:', dst open(dst,'wb').write(open(src).read()) else: if not exists(dst): os.makedirs(dst) for filename in os.listdir(src): local_mirror(os.path.join(src,filename), os.path.join(dst,filename)) os.utime(dst, (mtime,mtime)) def get_info(path): f = urllib.urlopen(path) mtime = f.headers.get('Last-Modified') if mtime: mtime = time.mktime(time.strptime(mtime, '%a, %d %b %Y %H:%M:%S %Z')) content = f.read() f.close() return int(mtime), content p = re.compile(r'([\d.]+?) +([\w/]+)') def remote_mirror(src, dst): mtime, content = get_info(src) if exists(dst) and mtime == int(getmtime(dst)): return print 'update:', dst, src if not src.endswith('/'): open(dst,'wb').write(content) else: if not exists(dst): os.makedirs(dst) for mt,filename in p.findall(content): mt = int(float(mt)) lpath = dst+filename if not exists(lpath) or int(getmtime(lpath)) != mt: remote_mirror(src+filename, lpath) os.utime(dst, (mtime,mtime)) if src.startswith('http://'): mirror = remote_mirror else: mirror = local_mirror while True: mirror(src, dst) time.sleep(1) </textarea>
如果源文件不在同一台机器上,可以通过NFS等共享过来。或者可以通过支持列目录的HTTP服务器来访问远程目录,mirror.py 已经支持这种访问方式。server.py 是用webpy做的一个简单的只是列目录的文件服务器。由于瓶颈在IO上,它的性能不是关键。server.py的代码如下:
- #!/usr/bin/python
- import os,os.path
- import web
- import time
- root = 'tmp'
- HTTP_HEADER_TIME = '%a, %d %b %Y %H:%M:%S %Z'
- class FileServer:
- def GET(self, path):
- path = root + path
- if not os.path.exists(path):
- return 404
- mtime = time.localtime(os.path.getmtime(path))
- web.header('Last-Modified', time.strftime(HTTP_HEADER_TIME, mtime))
- if os.path.isdir(path):
- for file in os.listdir(path):
- if file.startswith('.'): continue
- p = os.path.join(path,file)
- m = os.path.getmtime(p)
- if os.path.isdir(p):
- file += '/'
- print m, file
- else:
- print open(path,'rb').read()
- urls = (
- "(/.*)", "FileServer",
- )
- if __name__ == '__main__':
- web.run(urls, globals())
<textarea class="Python" style="display: none;" cols="80" rows="35" name="code" readonly="65535">#!/usr/bin/python import os,os.path import web import time root = 'tmp' HTTP_HEADER_TIME = '%a, %d %b %Y %H:%M:%S %Z' class FileServer: def GET(self, path): path = root + path if not os.path.exists(path): return 404 mtime = time.localtime(os.path.getmtime(path)) web.header('Last-Modified', time.strftime(HTTP_HEADER_TIME, mtime)) if os.path.isdir(path): for file in os.listdir(path): if file.startswith('.'): continue p = os.path.join(path,file) m = os.path.getmtime(p) if os.path.isdir(p): file += '/' print m, file else: print open(path,'rb').read() urls = ( "(/.*)", "FileServer", ) if __name__ == '__main__': web.run(urls, globals()) </textarea>
为了获得更好性能,以达到更好的实时性,Hash Tree最好是平衡的,比如BTree。如果一个文件发生变化,同步它需要进行的IO操作为N*M,其中N为数的层数,M为每层的文件数目。现在我们N为2,M最大为10000,适当减少它可以获得更好的性能,比如N为4,M为100。在以后创建目录结构时,最好能够考虑这方面的因素。
之前hongqn推荐过一个利用inotify的文件同步方案,同步方式类似于mysql和bdb等,由于过于复杂导致不可靠而没有采用。上面这个方案只用了一百多行Python代码就基本解决问题了,是不是很帅?:-)
发表评论
-
sysctl.conf
2011-07-06 14:54 1711fs.file-max=51200 net.core.net ... -
top的替代工具
2011-06-28 15:06 1430dstat -cgilpymn collectl and ... -
有用的小工具
2010-12-23 11:51 1298pv stream nessus Nikto ski ... -
调优linux i/o 行为
2010-11-25 11:27 2878http://www.westnet.com/~gsmith/ ... -
服务器部署工具
2010-11-12 16:32 2010http://www.linuxlinks.com/artic ... -
开源的配置管理工具
2010-11-12 16:24 1415最佳开源配置管理工具: Puppet / 提名:OpenQ ... -
优化ext3的mount选项
2010-11-12 10:24 1286defaults,commit=600,noatime,nod ... -
恢复r710biso 出厂设置
2010-11-10 10:30 1184ALT+E/F/B -
每进程io监控工具
2010-11-02 14:14 1619iodump iotop iopp pidstat b ... -
Intel Xeon 5500/5600系列 CPU服务器内存设置
2010-11-01 21:29 4774http://www.xasun.com/article/2a ... -
zabbix短信报警脚本文件
2010-10-21 14:28 2743附件 -
天外飞仙级别的Linux Shell命令
2010-10-16 09:59 1360本文编译自commandlinefu.com ( 应该是 Ca ... -
lenny+r710+lvm 重启问题解决方案
2010-10-15 14:22 1072ro rootdelay=10 quiet -
fai,debian 自动安装工具
2010-10-15 13:36 1074http://sys.firnow.com/linux/x80 ... -
十个服务器监控工具
2010-09-26 11:44 1789一位国外的技术博主在 ... -
restrict authorized_keys
2010-09-06 09:45 1217command="/home/someuser/rs ... -
sysctl优化设置
2010-09-05 11:25 1083sysctl 是一个用来在系统运作中查看及调整系统参数的工 ... -
proc文件系统
2010-09-05 11:22 1215什么是proc文件系统? proc文件系统是一个伪 ... -
nfs使用
2010-09-02 17:01 1117http://www.linuxhomenetworking. ... -
lsof example
2010-08-23 12:40 12331、查看文件系统阻塞 ...
相关推荐
由于同步所需的预期大量通信量和高时间复杂度,因此需要开发适当的同步算法。 增量同步是一种同步压缩文件的方法,即使没有进行更改或仅进行了部分更改,也需要上传整个文件。 在本研究中,我们提出了一种基于Delta...
软件特色 简单 Echosync 是不需要安装的便携式软件...借助此程序,可以在大量设备上备份和同步差异数据和其他类型的文件 Echosync 是一种精简而简约的软件解决方案,旨在为您提供备份文件和执行差异数据同步的可能性。
DiskBoss是磁盘文件管理客户端是...此应用程序使您可以快速复制大量的文件,同步磁盘和目录,找出重复的文件和无效空间等。 DiskBoss一些主要特点: -磁盘空间利用率分析. -分类及分类-重复文件查找和清洁. -高速
在 c:\*.rar 压缩文件中的 *.txt 文件执行区分大小写的 "first level" 字符串的搜索 2) rar ih=f0e0aeaeab2d83e3a9 -r e:\text 在 e:\text 目录下的 rar 压缩文件中搜索十六进制字符串 f0 e0 ae ae ab 2d 83 ...
磁盘文件管理(DiskBoss Network)是一个智能的,以规则为基础的文件和磁盘管理解决方案,允许用户搜索,类文件,执行磁盘空间...此应用程序使您可以快速复制大量的文件,同步磁盘和目录,找出重复的文件和无效空间等。
- 20%, 后期会考虑再进行优化 另外因为是同步读DB, 如果大量的cache失效会带来严重的io阻塞, 从而影响性能, 后期考虑加入配置选项在redis启动以后主动从db恢复数据 基于redis 2.6.16修改 标签:redisDB ...
二、解决方案 三、解决方案优势说明 1、高速高效:负载均衡使用特有的负载均衡算法,能够保证大量的流媒体连接请求负载实时 高效均衡。 2、实时在线:负载均衡服务器采用高可用冗余设计,而且对后端每台流媒体...
减少复杂性 更好的可用性 更小的TCO成本 减少部署的时间和成本 虚拟化数据中心 传统数据中心 复杂,混乱 额外的集群软件 大量设备和空间占用 现场实施 虚拟化转变数据中心架构 服务器虚拟化方案全文共39页,当前为...
glocc是一种针对令人尴尬的并行问题的积极并行解决方案。 每个文件和每个子目录的计数都分配给一个单独的 goroutine。 所有生成的 goroutine 都正确同步,并且它们的独立结果稍后在更高级别上合并(级别 = 在每个子...
架构 Intel原装处理器 H.264压缩方式 音/视频同步全实时录像资源 2. 独有的双显示输出端口 既有多分割画面显示,同时也有单画面显示,可以把多画面分割中任意画面切换至 单画面显示器,报警(SPOT)画面及动态感知...
以及适应更复杂的存储管理的需求,从分布式体系设计角度提出一个实现存储控制平面和数据存储平面融合的协同体系模型,为协同存储安全模型设计详细的多级可信管理、密钥管理和数据同步方案。实验结果表明,对于大量...
它会创建临时Pod,并将本地文件同步到所需的容器并执行任何命令。为什么有时您需要在Kubernetes中开发/执行代码,因为访问数据库,本地资源不足,需要访问某些特定设备,使用特定体系结构等。对于实际开发而言,...
3、管理主机可通过网络实时纪录压缩码流,支持借助网络将图像声音同步直接 录入电脑。 4、支持通道名叠加,支持通道录像日期、时间叠加,支持图标叠加、局部马赛 克和遮盖。 放像功能 1、本地放像:精确时间定位...
旅游电子商务网站功能设计方案 主要功能设计: 1. 品牌展示模块 旅游信息发布系统 景区动态、景区公告、行业信息、政策法规等多种信息发布,可自定义分类或无限级 别设置,支持文本、图片、动画、视频等多种表现形式...
第一节 项目名称与项目需求 (1)项目需求: 村安装视频监控系统建设实施方案 近年来,随着改革开放的深入和城乡经济的迅速发展,流动人口的大量增加,带来社会 许多的不安定因素,治安形式日趋严峻。同时由于治安...
提供团队内部、团队之间、团队与管理层 之间的沟通、检查、信息传递手段,通过多元化的主动、被动协同机制,实现团队内部及时 有效地协作, 避免因信息不同步而导致的大量浪费, 并能够完全保留协同和作业过程中的所...
并围绕文件或文件夹提供了大量诸如预览、编辑、压缩等功能,好像一个虚拟的“windows资源管理器”,是一套易用、可靠的文件管理存储系统。是机构或个人大批量电子文档存储管理、超大容量电子文档发送共享的必备工具...
在 c:\*.rar 压缩文件中的 *.txt 文件执行区分大小写的 "first level" 字符串的搜索 2) rar ih=f0e0aeaeab2d83e3a9 -r e:\text 在 e:\text 目录下的 rar 压缩文件中搜索十六进制字符串 f0 e0 ae ae ab 2d 83...
具体内容包括:类和泛型,集合、枚举器和迭代器,数据类型,语言集成查询和lambda表达式,调试和异常处理,反射和动态编程,正则表达式,文件系统I/O,网络和Web,XML,安全,线程、同步和并发,工具箱。本书使用...
-文件属性同步 -完全可定制的UI -无需服务器端代码:普通的HTTP服务器就足够了 -顺序和非顺序补丁处理 -更新的最短路径计算 -通过完全修复触发检测非常老的版本 -自我更新功能 管理工具 -版本管理 -补丁管理 -启动...