Spiga

分布式文件快速搜索-设计与实现(开源/并行)

2010-07-20 08:50 by 灵感之源, 2961 visits, 收藏, 编辑

 

系列文章

1.分布式文件快速搜索(多计算机并行/多种算法)

2.分布式文件快速搜索的设计与实现(开源/分布式计算/并行)

3.分布式文件快速搜索-技术细节分析(开源/并行)

 

 

 

特点


1.分布式:支持通过互联网查找任意多计算机,支持TCP/HTTP;
2.访问安全:基于角色的访问控制(RBAC),支持定义远程访问的账户、允许访问的目录等;
3.快速:

        a).充分发挥多核CPU的性能,自动进行并行计算;

        b).自动使用NTFS特性快速检索文件,比普通检索速度提升10倍以上
4.智能:自动识别同一部机器上的不同物理磁盘,自动加速;
5.高效:哈希值、全文索引快速存取,网络压缩传输;
6.可扩展性内容搜索:内容匹配、全文索引,支持接口;

 


前世


这个程序的灵感,可以参考这里详细的说明:分布式文件快速搜索(多计算机并行/多种算法)

 

原来的目的只是查找本计算机的重复文件,因为3TB的磁盘空间,放了太多电影、图片、音乐,有不少是重复。刚开始,对每个文件内容都进行哈希值计算,速度非常慢。后来改成先用文件大小碰撞,碰撞后重复的几率就极大地减少了,然后再进行文件内容哈希,速度就有了巨大的提升。再后来,支持了文件名、文件时间和属性等过滤条件,可用性也增大了。

 

但是我不满足现有的速度,觉得现在的CPU都是多核的,我们可以使用多线程来充分利用多核的威力。单纯的多线程处理容易,new Thread就能跑了,但我们的目的是把大量的查找任务切割,分而治之,然后同时执行,并等待所有任务都完成再继续下一步工作,这就是并行计算的目的。

 

.NET 3.5 SP1开始有了Parallel Extensions,4.0内置了Parallel Processing Library(PPL),当然还有一系列的相关类,如ConcurrentDictionary等(终于解决了2.0引入的Dictionary不是线程安全需要自己手工封装的问题了)。有了这些,我们就可以进行并行计算了。

 

在引入了多线程检索文件之后,我还不满足现有的速度。经过分析,可以判断检索的文件是否在不同的物理磁盘(不是一个磁盘的不同分区),则可以在本机动态使用并行计算。

 

我还不满足目前的功能:局限于现有计算机,作为不大。日常工作,我们需要对不同的计算机进行搜索,当然,都是局域网内,我们可以映射网络磁盘。但如果是互联网上的计算机,你就无能为力了。所以就有了现在的网格文件快速搜索。

 

必须说明的是,网格文件快速搜索不是一个完整的软件,只是闲得头痛而拿来练手的实验性程序,目前能做的只是检索、删除相同/不同计算机上的文件。

 


今生


所谓网格,就是分布式,跟Web2.0所谓Tag就是分类一样,互联网包装的概念层出不穷。

 

要实现在不同的计算机之间检索文件,并聚合结果,我们需要做的工作颇多。首先,我参考了google的MapReduce。MapReduce,实际就是2个步骤,分配工作,然后聚合结果。在对多个计算机进行检索,就是分配多个任务,每个任务检索指定的计算机,等待所有检索任务完成,再聚合结果。

 

接着,我们需要对任务进行分配。分配的原则是远程按机器分组,本地按磁盘分组。在分配好任务之后,我们需要在每个计算机运行一个监听程序接受其它机器的请求。监听使用的是异步TCP,使用事件来通知程序进行业务处理。在监听程序运行后,客户端判断要检索的文件夹位于远程计算机,使用异步TCP连接,连接成功后,发送要检索的文件夹以及身份信息,在通过身份认证之后,便可以进行文件检索。当检索完成后,返回结果给请求端,请求端在所有计算机的检索都完成后,对结果进行组合。

 

如果远程计算机HTTP无法连接(如监听程序没有启动),会自动尝试TCP链接,如果仍然失败会自动容错并忽略。

 

现在,网格文件快速搜索正式成为了文件搜索,而不是以前的重复文件查找了。

 


搜索流程

 

上述的步骤只是大概的过程,实际搜索流程要更复杂。整个搜索过程分2大步:第一步是根据文件的大小/名称/时间/属性等进行过滤,然后对存在相同的文件再进行文件内容哈希值判断。

 

对于互联网上的机器搜索,第一步必须返回所有搜索内容,而不是仅仅返回重复的内容,因为我们现在检索不是本地计算机,是多个互联网计算机,譬如计算机A存在文件1.jpg,计算机B也存在同样的1.jpg,但你必须把计算机A和B的结果聚合了才知道2个jpg文件相同,所以检索各个计算机的文件,第一次回返回所有文件信息,在结果返回聚合后,得出大小/名称/时间/属性相同的结果,再对这些文件进行文件内容哈希值处理。文件内容哈希值的处理过程跟文件属性检索类似,但是哈希值是以磁盘文件形式缓存了,每次获取文件内容哈希值之前,先判断文件的基本属性(文件名、大小、修改时间)是否与哈希数据库一致,如果匹配,使用数据库中的值,否则计算新的哈希值。

 

对于文件内容匹配,分3种情况:

1.完全匹配:使用哈希值判断,哈希值会在本地缓存;

2.内容包含:运行时判断;

3.全文索引:对可以抽取内容的文件进行动态索引,本地缓存;

 

全文索引支持接口扩展,目前内置了对微软的IFilter接口的实现,即将添加对lucene.net和hubbledotnet的支持。

 

具体流程看下图:

 

 


 

将来


你可以充分发挥想象力,把它应用到不同的领域。如果你应用了,记得告诉我,我会很高兴它能被别人使用。


TODO

参看分布式文件快速搜索(多计算机并行/多种算法) 。

 

使用

参看分布式文件快速搜索(多计算机并行/多种算法) 和下面的代码。


 

代码下载

点击这里下载:Filio.zip

 

实际使用,不需要V1*-V5*这些类,现在只是用来对比测试速度的,如果不测试,可以删除这些类。

 

 

项目地址

本项目已经在http://filio.codeplex.com/ 开源

 

 

Add your comment

16 条回复

  1. #1楼 Kevin.Jee      2010-07-20 09:14
    首先,很高兴您能够分享您的技术成果。
    但是,这篇文章给我的感觉是,“华丽而缺乏实用性”。
    一个很简单的道理,互联网上的计算机并不可能让您的请求来搜索磁盘文件,单单从安全性与用户的角度考虑,这种情况就是不现实的,用户害怕自己的隐私被侵犯,所以,您应该改一下。最基础的是由一个搜索电脑磁盘,改为搜索用户所主动公布的文件,OK,用户可将所需要公布的文件,放到一个平台上,然后这个平台再去接受您的SEARCH请求,这样是一个最基础的实现。

    其次,互联网上的机器,好多哇,如果有好几万台个人PC连接到您的CENTER,您又该如何处理? 负载均衡? 分组,分地域划分? 还是按照逻辑划分PC?

    这都是要考虑的问题。
    最后,还是很谢谢您能分享此文章, Thx.
     回复 引用 查看   
  2. #2楼[楼主] 灵感之源      2010-07-20 09:24
    @Kevin.Jee

    首先这个不是P2P之类的软件。

    其次,你只是搜索你可以访问的计算机。第三,客户端和服务器端都是你自己根据实际情况发布和应用的,而且用户访问机制本来就有了:用户名、密码、只允许访问的文件夹等。当然你还可以实现自己的严格的安全访问。

    文章已经说明,这只是一个实验性的程序,不是软件,更不是产品。

    综上所述,不存在用户担心安全等问题,也没有考虑负载均衡等忧虑。

    如果我,或者大家,有时间,有兴趣,或许会针对load balance进行改造。譬如我以前实现过根据IP地址来判断区域,然后分配不同的计算机来执行任务。

    添加发现协议已经实现。
     回复 引用 查看   
  3. #3楼 李占卫      2010-07-20 09:25
    看了你的文档感觉有些功能还是蛮吸引人的,打算用到Lucene。如果应用了我告诉你。
     回复 引用 查看   
  4. #4楼[楼主] 灵感之源      2010-07-20 09:29
    @李占卫
    先谢谢,有什么进展通知一下我
     回复 引用 查看   
  5. #5楼 Tony Qu      2010-07-20 09:52
    如果我的理解没有错的话,楼主目前实现了分布式搜索算法和分布式索引存储。请问文件filter parser这块有实现吗?还是只是根据文件名搜索?

    不过从实验的角度讲还是蛮不错的,支持一下!
     回复 引用 查看   
  6. #6楼 eaglet      2010-07-20 10:26
    是只能找到相同的文件还是可以根据某些关键字来查找呢?
     回复 引用 查看   
  7. #7楼[楼主] 灵感之源      2010-07-20 10:28
    @Tony Qu
    没有实现存储。。。其实你的目的是想实现真正的搜索引擎吧。。。

    filter/parser倒是可以考虑的,但要实现这个,就得实现存储,如果拿现成的lucene.net,还不如直接用eaglet写的HubbleDotNet。
     回复 引用 查看   
  8. #8楼[楼主] 灵感之源      2010-07-20 10:29
    @eaglet

    可以根据关键字的。你可以纯粹找完全一致的文件,也可以找文件名一样或类似的文件。

    其实你的HubbleDotNet可以考虑一下添加对分布式的支持:)
     回复 引用 查看   
  9. #9楼 eaglet      2010-07-20 10:45
    @灵感之源
    分布式我后面要考虑的,目前主要还是在完善功能。你这个分布式的hash表不存储,是不是每次启动要重新计算一遍?另外你的 hash 是用的什么算法,多少位的?我最近打算做指纹消重功能,正在考虑这方面的算法。
     回复 引用 查看   
  10. #10楼[楼主] 灵感之源      2010-07-20 10:56
    @eaglet
    我的hash是runtime的,没存储,不过下一个版本大改的话可能会引入。

    .net自带的System.Security.Cryptography.MD5CryptoServiceProvider,标准算法,32bytes,速度比Managed的要快2-3倍


    using (FileStream stream = new FileStream(FooFile, FileMode.Open, FileAccess.Read, FileShare.Read, BUFFER_SIZE))
    {
    using (MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider())
    {
    md5.ComputeHash(stream);
    stream.Close();
    byte[] hash = md5.Hash;
    return BitConverter.ToString(hash).Replace("-", string.Empty);
    }
    }
     回复 引用 查看   
  11. #11楼 peace      2010-07-20 21:38
    纯顶!
     回复 引用 查看   
  12. #12楼[楼主] 灵感之源      2010-07-21 10:18
    @eaglet
    已经添加了对文件哈希值的快速存取
     回复 引用 查看   
  13. #13楼 iTech      2010-07-21 10:47
    对的,可以用md5来唯一标示文件!

    按我的理解网格的话,表示计算需要在分布的机器上进行,即在远程的机器上运行程序来查找那个机器上的文件。
     回复 引用 查看   
  14. #14楼[楼主] 灵感之源      2010-07-21 19:03
    @iTech
    用md5来判断文件是否唯一只是一种办法,虽然给验证了不是完全可靠,但目前还是够用的
     回复 引用 查看   
  15. #15楼[楼主] 灵感之源      2010-07-22 20:28
    实现了全文索引内容查找接口,内置IFilter实现,明天发布

    即将添加对lucene.net和hubbledotnet的接口支持
     回复 引用 查看   
  16. #16楼[楼主] 灵感之源      2010-07-23 14:59
    @eaglet

    在v6.6 添加了对HTTP协议、内容匹配、全文索引的支持;
     回复 引用 查看