中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

?Lucene的Directory怎么實現

發布時間:2021-12-23 09:17:25 來源:億速云 閱讀:115 作者:iii 欄目:互聯網科技

這篇文章主要介紹“Lucene的Directory怎么實現”,在日常操作中,相信很多人在Lucene的Directory怎么實現問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Lucene的Directory怎么實現”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

在此之前,我們先來看下Directory家族的層級分布圖。
?Lucene的Directory怎么實現

從上圖中,我們可以看出Directory共有11個直接或者間接的子類,不同的子類的作用和功能不一樣,那么Directory作為此繼承圖的頂級父類,在Lucene中確實發揮重要的根基作用,就像Hadoop的根基是HDFS一樣,Directory肩負著索引存儲的重任,如果沒有存儲,那么檢索就無從談起了,雖然我們經常稱全文檢索,搜索引擎什么的,其實它們的背后,Directory才是默默無聞的”雷鋒“。

下面就來詳細的剖析下Directory的核心實現。 
Directory是由lucene中的一些列索引文件組成的目錄,一個典型索引文件結構圖的截圖如下:

?Lucene的Directory怎么實現

而Directory的作用,就是負責管理這些索引文件,包括數據的讀取和寫入,以及索引文件的添加,刪除和合并。從這樣的角度來分析,Directory更像一個系統的管理員,下面,散仙再具體的分析下一些核心方法的作用。 

我們都知道Lucene的索引體系,支持讀共享,寫獨占的方式來訪問索引目錄,也就是說,它允許多個線程實例同時并發的讀取,而不允許多個線程同時寫入,大家可能會有疑問,為什么不支持多線程寫入呢?這其實是因為索引目錄有自己的某一時刻的內部狀態,比如說文件指針,而多線程寫入時,會造成指針混亂,從而引起索引結構損壞或某些數據丟失,所以lucene任何時候都禁止有多個線程并發的寫入索引,即使是多線程寫,每次也只能通過隊列的方式,一次只允許一個線程操作索引,按這樣的情況分析,多線程寫入與單線程寫入,在性能上的提升,并不是明顯的,那么lucene又是怎么控制一次只能有一個線程寫入呢,打開Directory的源碼,我們就會發現,它其實是在內部維護了一個鎖的實例,通過加鎖方式,來禁止后來線程的寫入操作,當然鎖的作用不僅僅是防止并發寫入,它還可以通過鎖名字來判斷,這兩份索引是否為同一份索引,那么如果我們想使用多線程來提升寫入速度,一個折中的辦法就是,每個線程寫一份目錄,最后在對這些目錄,進行合并,下面給出了一些源碼中鎖的實現方法

protected LockFactory lockFactory;//鎖實現,只能由子類覆蓋
//設置鎖名
  public Lock makeLock(String name) {
      return lockFactory.makeLock(name);
  }
  //清除鎖
  public void clearLock(String name) throws IOException {
    if (lockFactory != null) {
      lockFactory.clearLock(name);
    }
  }

下面我們來分析下Directory源碼中另外一個變量isOpen的作用

    //注意,使用的是volatile關鍵字修飾
  volatile protected boolean isOpen = true;

isOpen是用來判斷當前的Directory實例,在內存中的狀態,它使用的是volatile 關鍵字修飾的,被此變量修飾的內容,JVM虛擬機讀取的時候會直接在主存中讀取該變量的值,而不會在各個線程的本地內存中讀,這樣一來,當并發讀的時候,如果Directory實例關閉了,那么各個讀的線程會立即獲取最新的狀態,如果不做處理的話,將會拋出一個目錄實例關閉的異常。isOpen 確保了索引在并發讀的時候,各個線程實例獲取Directory狀態的一致性。

  private static final class SlicedIndexInput extends BufferedIndexInput {
    IndexInput base;
    long fileOffset;
    long length;
    
    SlicedIndexInput(final String sliceDescription, final IndexInput base, final long fileOffset, final long length) {
      this(sliceDescription, base, fileOffset, length, BufferedIndexInput.BUFFER_SIZE);
    }
    
    SlicedIndexInput(final String sliceDescription, final IndexInput base, final long fileOffset, final long length, int readBufferSize) {
      super("SlicedIndexInput(" + sliceDescription + " in " + base + " slice=" + fileOffset + ":" + (fileOffset+length) + ")", readBufferSize);
      this.base = base.clone();
      this.fileOffset = fileOffset;
      this.length = length;
    }

接下來,來分析Directory的靜態常量內部類SlicedIndexInput的作用,Lucene的索引文件是非常松散的,不同類型的數據存儲在不同的文件里,我們可以通過文件名,來單獨讀取指定索引文件的內容,同樣道理我們也可以,在寫入信息時候,單獨寫入某部分數據的信息,這樣一來,就避免了操作整個目錄的可能,按需所用,從一定程度上來說,這樣的設計提升了性能,保證了數據的穩定與可靠性,雖然也從某種程度上加大了Directory目錄管理的復雜度,但這些都是微不足道的。 


SlicedIndexInput這個類的作用保證了Lucene可以單獨讀取部分索引文件的內容,注意這些內容都不是最原始的數據,而是SlicedIndexInput克隆的一份副本,這樣一來在并發讀的環境下是非常有利的,每個線程都會從主存中load一份副本出來。在我們的源碼中,我們并沒有發現它具有深度克隆的功能,但是通過一系列繼承的追蹤,我們發現,SlicedIndexInput==》BufferedIndexInput==》IndexInput==》DataInput,在最后的這個父類中實現了Cloneable和Closeable接口,從而確保保證了SlicedIndexInput可以正常的工作,以及釋放一些占用的IO資源。
 

到此,關于“Lucene的Directory怎么實現”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

西华县| 广水市| 邢台市| 雅安市| 彭阳县| 武川县| 新竹市| 乐山市| 阳谷县| 通州市| 富川| 柳江县| 曲阳县| 洪江市| 孟村| 喀喇沁旗| 义马市| 察隅县| 湟中县| 隆安县| 天门市| 武陟县| 公安县| 石首市| 寿光市| 泰兴市| 云林县| 白朗县| 琼中| 石嘴山市| 罗甸县| 庄浪县| 大冶市| 榆社县| 靖边县| 余江县| 罗城| 通榆县| 凉城县| 吴川市| 承德市|