日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

集成Lucene和HBase(转)

發布時間:2025/6/15 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 集成Lucene和HBase(转) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Lucene中可搜索的實體都表現為文檔(document),它由字段(field)和值(value)組成。每個字段值都由一個或多個可搜索的元素——即詞匯(term)——組成。Lucene搜索基于反向索引,其中包含了關于可搜索文檔的信息。在使用正常索引時,你可以搜索文檔,以了解它包含哪些字段,但使用反向索引與之不同,你會搜索字段的詞匯,以了解所有包括該詞匯的文檔。

圖1顯示的是高層次的Lucene架構【2】。它的主要組件包括IndexSearcher、IndexReader、IndexWriter 和Directory。IndexSearcher實現了搜索邏輯。IndexWriter為每個插入的文檔寫入反向索引。IndexReader會在IndexSearcher的支持下讀取索引的內容。IndexReader和IndexWriter都依賴于Directory,它會提供操作索引數據集的API,而該API會直接模擬文件系統API。

圖1: 高層次的Lucene架構

標準的Lucene分發包中有多個目錄實現,包括基于文件系統和基于內存的[1]。

標準基于文件系統的后端的缺點在于,隨著索引增加性能會下降。人們使用了各種不同的技術來解決這個問題,包括負載均衡和索引分片(index sharding)——在多個Lucene實例之間切分索引。盡管分片功能很強大,但它讓總體的實現架構變得更復雜,并且需要大量對期望文檔的預測知識,才能對Lucene索引進行合適地分片。

另一種不同的方法是,讓索引后端自身對數據進行正確地分片,并基于這樣的后端構建出實現。這種后端可以是NoSQL數據庫。在本文中我們會描述基于HBase的實現【4】。

實現方法

正如在【3】中所說明的,在高層次上,Lucene會操作兩個單獨的數據集:

  • 索引數據集中保存了所有字段/詞匯對(還有其他信息,像術語頻率、位置等),以及在恰當的字段包含這些詞匯的文檔。
  • 文檔數據集中存儲所有文檔,包括存儲的字段等。

正如我們已經在上面提到的,想要把Lucene移植到新的后端中,直接實現directory接口并不總會是最簡單(最方便)的方法。所以,很多對Lucene的移植,包括從Lucene的contrib.module支持的優先內存索引、Lucandra【5】和HBasene【6】分別采用了不同的方法【2】,不僅重寫了directory,還重寫了高級的Lucene類——IndexReader和IndexWriter,從而繞開了Directory的API(如圖2)。

圖2: 將Lucene和沒有文件系統的后端整合

盡管這種方法通常需要更多工作【2】,但是它能夠帶來更強大的實現,讓我們可以完全利用后端的本地功能。

文中所展現的實現[2]也遵循了這種方法。

總體架構

總體上的實現(如圖3)是在基于內存的后端之上構建的,并將其用作內存緩存、同步緩存和HBase后端的機制。

圖3: 基于HBase的Lucene實現的總體架構

該實現試圖平衡兩種相互沖突的需求,性能: 在內存中,緩存能夠最小化HBase用于搜索和文件返回的數據讀取量,從而極大提升性能;可伸縮性: 按照需要運行為多個Lucene示例以支持日益增長的搜索客戶端的能力。后者需要最小化緩存的生命周期,從而和HBase實例(上面提到實例的副本)中的內容同步。通過為活動參數實現可配置的緩存時間,限制每個Lucene實例中展現的緩存,我們可以達成一種折中方案。

內存緩存中的底層數據模型

正如之前所提到的,內部Lucene數據模型基于兩種主要的數據集——索引和文檔,它們會被實現為兩種模型——IndexMemoryModel和DocumentMemoryModel。在我們的實現中,讀寫操作(IndexReader/IndexWriter)都是通過內存緩存完成的,但是它們的實現有很大區別。對于讀取操作,緩存首先會檢查所需要的數據是否在內存中,并且沒有過期[3],如果那樣的話就會直接使用。否則緩存就會從HBase讀取或者刷新數據,然后把它返回給IndexReader。相反,對于寫操作,數據會直接寫入到HBase,而不會在內存中存儲。盡管這在實際的數據可用性方面會有延遲,但是它會讓實現過程非常簡單——我們不需要考慮把新建或者更新的數據發送給哪個緩存。這里的延遲可以通過設置合適的緩存過期時間來控制,從而符合業務需求。

IndexMemoryModel

索引內存模型的類圖如圖4所示。

圖4: IndexMemoryModel類圖

在這個實現中:

  • LuceneIndexMemoryModel類包含了當前存在于內存中所有字段的FieldTermDocuments類。它還提供了所有對于實現IndexReader和IndexWriter必要的內部API。
  • FieldTermDocuments類會為每個字段值管理TermDocuments。通常,對于可掃描的數據庫,字段的列表和字段值的列表可以組合在可導航的字段/詞匯值列表中。對于基于內存的緩存實現,我們已經把它們切分為兩個獨立的部分,從而讓搜索的時間更可預測。
  • TermDocuments類為每個文檔ID包含了一系列TermDocument類。
  • TermDocument類包含了針對給定文檔在索引中存儲的信息——文檔使用頻度和位置的數組。
DocumentMemoryModel

文檔內存模型的類圖如圖5所示。

圖5: DocumentMemoryModel類圖

在這個實現中:

  • LuceneDocumentMemoryModel類包含DocumentStructure類與每個被索引文檔的映射關系。
  • DocumentStructure類中包含了單個文檔的信息。針對每個文檔,它都包含了為每個索引后字段保存的字段和信息。
  • FieldData類包含為存儲字段(stored field)所保存的信息,包括字段名稱、值和二進制或者字符串型的標識。
  • DocumentTermFrequency類包含了關于每個被索引字段的信息,包括對相應索引結構(索引、詞匯)的向后引用、文檔中詞匯使用頻率、詞匯在文檔中的位置以及從文檔開始的偏移量。
LuceneDocumentNormMemoryModel

正如在【9】中說明的,規范(norm)是用于表現文檔或字段的加權因子,從而提供更好的搜索結果排序,這需要耗費大量內存。類的實現基于對映射的映射(map of maps),內部映射會存儲規范和文檔的映射關系,而外部映射會存儲規范和字段的映射關系。

盡管規范信息的鍵值是字段名稱,從而可以添加到LuceneIndexMemoryModel類中,但是我們還是決定把對規范的管理實現為單獨的類——LuceneDocumentNormMemoryModel。這么做的原因在于,在Lucene使用規范是可選的操作。

IndexWriter

有了之前所描述的底層內存模型,實現索引寫入程序就很簡單了。因為Lucene不會定義IndexWriter接口,所以想要實現IndexWriter,我們需要實現所有標準Lucene實現中的方法。這個類的主要內容在于addDocument方法。這個方法會遍歷所有文檔的字段。對于每個字段,方法都會檢查它是否可以令牌化(tokenized),并使用特定的分析器來做到這一點。這個方法還會更新所有三種內存結構——索引、文檔和(可選的)規范,它們會為新增的文檔存儲信息。

IndexReader

IndexReader會實現Lucene核心所提供的IndexReader接口。因為Hbase中所獲得的列表和單獨的讀操作相比要快很多,所以我們使用一些方法來擴展這個類,從而可以讀取多個文檔。類本身沒有把更多的處理轉交給幾個類,它會對其進行管理:

  • 盡管文檔ID通常是字符串,但Lucene內部還是對整型數操作。DocIDManager這個類會負責管理從字符串到數字的轉換。IndexReader會以ThreadLocalStorage的形式使用這個類,從而可以在線程結束之后自動清理。
  • MemoryTermEnum類擴展了Lucene提供的TermEnum類,負責掃描字段/詞匯的值。
  • MemoryTermFrequencyVector類會實現Lucene提供的TermDocs和TermPositions接口,負責為給定的字段/詞匯對(field/tem pair)處理與文檔相關的信息。
  • MemoryTermFrequencyVector類實現了Lucene提供的TermFreqVector和TermPositionVector接口,負責針對給定的文檔ID返回文檔字段頻率和位置信息。

HBase表

以上提出的解決方案基于兩個主要的HBase表——Index表(圖6)和document表(圖7)。

圖6: HBase的Index表

(點擊圖像可以放大)

圖7: HBase的document表

如果需要支持規范的話,可選擇實現第三個表(圖8)。

圖8: HBase的norm表

HBase的Index表(圖6)會完成實現的主要工作。這個表對每個Lucene實例所知道的字段/詞匯組合都設置了入口,其中包含一個列族(column family)——documents族。這個列族為包含這個字段或詞匯的所有文檔都包含了一列(名稱是文檔的ID)。每個列的內容都是TermDocument類的值。

HBase的document表(圖7)存儲了文檔本身、對索引或規范的向后引用,它會為文檔處理引用這些文檔以及一些Lucene使用的附加信息。它對所有Lucene實例知道的文檔都設置了入口(row)。每個文檔都通過文檔ID(鍵值)唯一標識,并包含兩個列族——字段族和索引族。字段列族針對所有存儲在Lucene中的文檔字段包含一列(名稱為字段的名稱)。列的值是值的類型(字符串或者字符數組)和值本身的組合。索引列族為每個引用這個文檔的索引包含了一列(名稱是字段或者術語)。列的值包括給定字段/詞匯在文檔的使用頻率、位置和偏移量。

HBase的norm表(圖8)為每個字段存儲了文檔的規范。它對所有Lucene實例知道的每個字段(鍵值)都設置了入口(行)。每行都只包含一個列族——規范族。這個族對每個需要存儲給定字段規范的文檔都有一列(名稱是文檔ID)。

數據格式

最終的設計方案確定了在HBase中存儲數據的數據格式。對于這個實現,我們基于性能、結果數據的最小規模以及和Hadoop的緊密整合程度選擇了Avro【10】。

實現主要使用的數據結構是TermDocument(代碼1)、文檔的FieldData(代碼2)和DocumentTermFrequency(代碼3)。

{"type" : "record","name" : "TermDocument","namespace" : "com.navteq.lucene.hbase.document","fields" : [ {"name" : "docFrequency","type" : "int"}, {"name" : "docPositions","type" : ["null", {"type" : "array","items" : "int"}]} ] }

代碼1 詞匯文檔AVRO定義

{"type" : "record","name" : "FieldsData","namespace" : "com.navteq.lucene.hbase.document","fields" : [ {"name" : "fieldsArray","type" : {"type" : "array","items" : {"type" : "record","name" : "singleField","fields" : [ {"name" : "binary","type" : "boolean"}, {"name" : "data","type" : [ "string", "bytes" ]} ]}}} ] }

代碼2 字段數據AVRO定義

{"type" : "record","name" : "TermDocumentFrequency","namespace" : "com.navteq.lucene.hbase.document","fields" : [ {"name" : "docFrequency","type" : "int"}, {"name" : "docPositions","type" : ["null",{"type" : "array","items" : "int"}]}, {"name" : "docOffsets","type" : ["null",{"type" : "array","items" : {"type" : "record","name" : "TermsOffset","fields" : [ {"name" : "startOffset","type" : "int"}, {"name" : "endOffset","type" : "int"} ]}}]} ] }

代碼3 TermDocumentFrequency的AVRO定義

結論

本文中描述的簡單實現完全支持所有Lucene功能,針對Lucene核心和普通模塊的單元測試都驗證了這一點。我們可以將它作為基礎,構建可擴展性很強的搜索實現,支持HBase固有的可擴展性以及完全對稱的設計,讓我們可以添加任意數量服務于HBase數據的進程。它還可以避免需要關閉打開狀態的Lucene索引讀取程序,就可以包含新的索引數據,那會經過一定延遲之后為用戶所用,而延遲是通過活動參數的緩存時間所控制的。在下一篇文章中我們會展示如何擴展這個實現,以包含地理搜索支持。

關于作者

Boris Lublinsky是NAVTEQ的首席架構師,他的工作是為大型數據管理和處理、SOA以及實現各種NAVTEQ項目定義架構的愿景。他還是InfoQ的SOA編輯,并且參與了OASIS的SOA RA工作組。Boris是一位作者,并經常發表演講,他最新的著作是《Applied SOA》。

Michael Segel擁有二十多年和客戶協作的經驗,和他們一起確定并解決業務問題。Michael曾經在多個領域以多種角色工作過。他是一位獨立顧問,期望解決任何有挑戰性的問題。Michael擁有俄亥俄州立大學的軟件工程學位。

參考文獻
  • Lucene-java Wiki
  • Animesh Kumar. Apache Lucene and Cassandra
  • 3. Animesh Kumar. Lucandra - an inside story!
  • HBase
  • Lucandra
  • HBasene
  • Bigtable
  • Cassandra
  • Michael McCandless, Erik Hatcher, Otis Gospodnetic. Lucene in Action, Second Edition.
  • Boris Lublinsky. Using Apache Avro.

  • [1]附加的Lucene程序包含了為Berkley DB構建的DB目錄。

    [2]這個實現受到了Lusandra源代碼【3】的啟發。

    [3]沒有在內存中存在太長時間。

    查看英文原文:Integrating Lucene with HBase

    轉載于:https://www.cnblogs.com/ShortHinny/archive/2012/04/24/2468718.html

    總結

    以上是生活随笔為你收集整理的集成Lucene和HBase(转)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。