zoukankan      html  css  js  c++  java
  • [ lucene高级 ] 研讨如何进行Lucene的分布式应用 [转]

    Lucene是个高度优化的倒转索引搜索引擎。它将倒转的索引存储在定制的文件格式中,文件格式被高度优化以确保能被搜索器快速的加载以及有效的搜索。Lucene产生这些结构以致索引几乎完全的被预先计算好

    Lucene 通过使用Directory接口的实现来存储索引,注意不要将Directoryjava.io混淆了.FSDirectory Directory接口的一个标准的实现,它将索引保存在文件系统中.还有一些其他的实现,比如有的实现将索引切分小的数据块保存在文件系统中,有的通过使用Map Reduce(google)的集群来分布索引.还有一种数据库的实现,它将索引作为数据块保存在数据库中

    (Lucene 的快速是因为它的索引结构,为了能出色的搜索,Lucene需要能有效的寻址扇区块,正是这些扇区块组成了索引.如果底层的存储机制支持这种寻址,那么就没什么好说的,如果不支持那么这就是问题了.在这个问题上,基于文件的FSDirectory 是有效的.如果索引文件保存在本地的文件系统中,那么这种访问效果还不错.如果被放在共享的文件系统中,那么总是会存在一些延迟和潜在的IO阻塞. 上面说的那种数据库的实现方式高度依赖于目标数据库blob实现,而且几乎总是比FSDirectory).一些数据库支持可寻址的blob,比如说oracle.mysql也模拟了这种行为(当你将MySQL的参数 emulateLocators设置为true)其他的数据库就是不支持,所以真的是慢(我的意思是指实际上就是很慢)

    所有的这些将影响到集群环境中的lucene. 每个进行搜索的节点需要访问索引。所以为了能使实现集群环境中的搜索,我们必须提供共享的索引文件。有3(译注:应该是5 )种方式提供参考。

    1)在所有的节点间使用共享文件,而且使用FSDirectory

    2)使用节点本地文件系统中的索引,并且保持各节点间的同步

    3)使用JDBCDirectory操作数据库(译注:将索引文件保存在数据库中实现节点间的共享)

    4)使用分布式的文件系统(例如google文件系统和Nutch 分布式文件系统)

    5)使用本地缓存保存数据库中备份

    使用共享文件系统存在一些问题.性能会明显低于使用本地文件系统. 如果SAN不能使用,那么一个SAN共享文件系统必须是个真正的SAN file system比如Redhat Global File SystemApple XSan.对于文件系统块的修改必须能立即镜像到所有连接节点的块缓存中,否则文件系统会崩溃.记住SAN是个网络化的块设备,没有额外的帮助,不可能同时被多个计算节点共享.如果共享文件系统的性能可以保证的话,Lucene使用FSDirectory的实现会一如既往地表现出色.Sakai Search组件管理的锁实现解决了Lucene社区提交的锁问题.

    以上所说的机制现在在 Sakai Search是可用的

    这种集群的架构并非一个共享的架构,Lucene索引写到本地磁盘然后在创建索引结束后同步到各节点.这是集群环境中Lucene最佳部署方案,因为这样能确保所有的IO是在本地磁盘因此很快.为了确保总是有一个索引的备份,同步应该制定备份路径

    这种方案的困难在于缺乏搜索引擎实现的支持,它需要部署支持.这可能会采用连接镜像来加速同步过程.Lucene索引非常适合采用rsync同步.rsync是一个基于块的同步机制.

    这种方案的主要缺陷是本地保存了所有的索引文件.在一个大型的搜索环境中,这种复制是很浪费空间的.然而从搜索引擎的条件看, Sakai的单个部署决不可能占用很大空间(100多兆的documents的索引占用了2TB空间)

    但需要实现简单的集群的时候,使用基于数据库的索引是个直接的选择.然而这种方法有明显的缺陷.最值得注意的是性能下降.索引作为块以blob的形式保存在数据库中.这些blob以块结构保存用以消除一些不必要的加载.然而每个快会绕开任何本地磁盘块缓存,而且必须通过网络传递数据流.如果数据库支持可寻址的块,对数据库本身而言,最小化不必要的网络阻塞时可能的.Oracle提供了这种支持, 然而当数据库仅仅是模拟这种行为(比如mysql)的话,当整个blob需要通过流化再在网络上传递的时候,性能是很差的.而且,访问的速度比较慢,因为访问数据时得执行sql statement总之性能会下降.

    这种机制是可以使用的,但性能很可能是不可接受的

    一些真实的搜索引擎使用分布式的文件系统.这种分布式系统提供了一个自治的系统,数据通过多节点分布,这样的系统能从一个或多个节点的损坏中恢复.Google 文件系统和 Nutch分布式文件系统(建模在.Google 文件系统之上)就是这样一个例子.两种实现采用了一种聚合扫描算法,GoogleMap-Reduce详述了这种算法(Google labs)

    这种方法使每个节点包含文件系统的一个部分.但索引变得庞大以致保存在每个节点时,这个方法变得更具吸引力. Sakai目前还没有计划提供分布式文件系统的实现

    本方法中,索引通过本地磁盘使用,但作为Lucene扇区备份在数据库中,可以安装一个集群应用节点在本地拷贝和数据库之间同步.当接受到索引重载事件,所有的集群应用节点再次与数据库同步从而下载更新和全新的搜索扇区.

    这种机制处于测试阶段,我发现当搜索200MB的索引(包含80000文档)的时候,这种机制的性能和基于本地的索引相当.

    一旦这种机制经过完全测试,当工作在一个或多个集群节点的环境中,这种机制将变成默认的OOTB机制.额外的优点是索引保存在数据中.

    也可以采用共享的文件存储作为一个备份路径来实现这种机制.

     

    ----------------------------------------------------

    提问:

      现在有个项目,有10台服务器,每台服务器负责某一部分的index。另外有一台web服务器,它可以根据用户提交的查询请求到特定的服务器上进行查找。比如用户提交查询A,根据index的分配情况,可以将查询请求分发给服务器a来负责,而用户提交查询请求B,则将它提交给服务器b来负责。不知lucene目前的index机制和search机制是否能够支持这种需求?


     

    回答:

      1. 目前lucene的机制不支持这种需求

      2. 你可以很容易的扩展lucene,从而满足你的需求.

      实际上,你这是涉及到 indexing的分布式存储的问题, 涉及到结构, 传输,等等.

      所以,你必须要设计一个robust的分布式index结构,然后再考虑如何实现.不要一开始就拿一个开源的lucene就上.

      google当然是分布式的索引. 只不过这个分布式可能不是你想象中的那么神秘.


     

    --------------------------------------------------

    提问:

    刚才看了一下lucene的index结构,感觉不需要对index进行修改,比如10台检索服务器,每个服务器负责一个网站的crawl以及index。然后我的web服务器将用户的query广播到10台检索服务器去,10台服务器同时进行搜索(用lucene的api),然后每台服务器将最符合的topN条记录发送回web服务器,web服务器再对这topN×10条记录进行重新排序,取最前面的topN条记录就行了。

      你觉得我这种方法可行吗?

      我觉得这种方法的缺点在于web服务器和检索服务器之间的通讯量问题:

      1、首先要对10个服务器进行广播查询,有没有方法可以根据query的情况,能够确定对某台服务器查询?感觉这确实要对index进行分布式的存储,但是如何进行分布式存储呢?按照term进行分布式存储肯定不行,因为对单一的term进行查询,返回的文档肯定很多(按照lucene里面的算法),难道按照term vector来分布式存储?好像lucene不太支持这个吧。

      2、其次,每台检索服务器都返回了topN条结果,这好像比较浪费,有没有什么办法让它返回少点,同时又不影响结果?

     

    回答:

    你的这个结构理论上是可以的,不过有一点:

      按照你目前的应用规模,你的索引完全可以放在一台机器上。

      为什么要分开10台机器存储?

      集中在一台机器上,就没有检索的时候,通讯量的这个问题了。

      如果你真的是想要分开,就要涉及到分布式索引,和索引之间的通讯压缩的问题,这个也是你提到的困惑,我觉得如果你不是专业SE,你最好绕过这个技术难点。

      现在的版本已经有进度显示,以及支持索引更新。至于与Jxta有一个based On grid的distributed fulltextsearch项目的区别,我们目前还没有做过比较,呵呵。distributedsearch项目意在于提供多个节点之间架构一个平台提供有效的资源查找与资源共享方式。该项目采用lucene(http://lucene.apache.org)开放源项目作为底层的搜索引擎,采用网格技术实现分布式机制。

      为什么非要扯上“分布”去?

      我看了半天,还不是太理解你的问题,就我目前的了解,似乎是两种情况。

      1、检索的负载大,想用多台服务器分散检索的压力。(相对的,全文内容的更新相对压力较小,可以集中用一台高性能服务器来处理全文内容的更新)

      由于lucene是基于文件的,实现起来比较方便一些。你可以使用NAS做为你的存储,或者是直接采用廉价的同步复制方案(比如rsyncd)。

      比如10台服务器,用一台处理全文内容更新,另外9台对外提供检索。当全文内容更新后,通过rsyncd这样的同步复制,把更新后的内容同步到9台检索服务器去,供用户检索。

      至于负载,10台服务器都有了,再花几万块钱买台均衡交换机(比如aleton)也没有太大难处吧?

      2、检索压力小,全文内容的更新量大。

      在单台服务器下面,可能就是表现在你的全文库分散在不同的目录下面(比如/full/app1、/full/app2.。),想检索的时候能检索所有的全文记录,而不是某一目录(比如/full/app1),是否?

      也就是说,你希望用9台服务器来处理全文的增加,比如一台服务器对应一个应用。如果采用NAS(或是其它高速的存储解决方案),或是rsyncd这类同步复制,在任何一个全文服务器有更新后,及时的把这台的更新内容同步到用于检索的10服务器上。

      在检索的这台服务器上,如同单一服务器一样,同步后的数据按服务器存储在不同目录下,而lucene检索时,好象它的api是支持多目录检索的。

      另:

      我觉得你的需求,实际上没有必要扯到“分布”上面去,如果能在存储上花点功夫,比如选择一个比较好的统一存储方案,或是实现存储的“主--镜像”同步复制,也许就不是问题了。

      对于存储引出来的传输性能问题,你可以在构建网络的时候考虑一下,比如在每个服务器上多加网卡,用光口或是GE口构建一个专门的“传输网络”,避免与“业务网络”、“管理网络”这类塞车,在传输上的问题应该影响不大。

      我做的分布式lucene搜索,可以把数据源分时间建到不同机器上,每台机器做个seachserver,web服务器同时向各个seachserver发送请求,10台seachserver同时查询,返回查询条数再从最近的索引库返回结果,翻页的话判断每个每台seacherserver的条数,以时间最近的机器返回结果!

  • 相关阅读:
    shell脚本
    数据分析学习笔记(1):工作环境以及建模理论基础
    spark复习笔记(7):sparkstreaming
    mybatis复习笔记(1):
    spark复习笔记(7):sparkSQL
    spark复习笔记(6):RDD持久化
    spark复习笔记(6):数据倾斜
    spark复习笔记(4):RDD变换
    C#重启IIS
    mongodb学习记录
  • 原文地址:https://www.cnblogs.com/huangfox/p/1852206.html
Copyright © 2011-2022 走看看