ES中創建索引的詳細分析
總覽
ES 創建索引最終都會調用 org/elasticsearch/index/engine/InternalEngine.java
中下面的方法:
public IndexResult index(Index index) throws IOException {
注意這裏的index中包含有要寫入的doc,該方法的執行流程圖如下:
注意:結合上邊的流程圖來看代碼,先對整體有個全局的認識,再深入到各個部分深入分析。切勿在對整體不甚瞭解的情況下,深入到代碼細節,切記,切記。
準備文檔的索引計劃
準備索引計劃根據是否爲主節點分別調用:planIndexingAsPrimary和planIndexingAsNonPrimary函數,接下來我們看下planIndexingAsPrimary的邏輯(位於org/elasticsearch/index/engine/InternalEngine.java 中)。
private IndexingStrategy planIndexingAsPrimary(Index index) throws IOException {
這個方法最終返回一個4個IndexingStrategy(索引的策略)中的一個,四個索引的策略分別如下:
- optimizedAppendOnly
- skipDueToVersionConflict
- processNormally
- overrideExistingAsIfNotThere
不同的策略對應不同的處理邏輯,前面三個是常用的,流程圖如下:
對於1的說明:canOptimizeAddDocument函數中只判斷autoGeneratedIdTimestamp變量是否不等於-1;如果不等於-1意味着這個這個文檔有一個自動生成的id,就意味着這個文檔能以optimized的方式加入到索引中。
對於2的說明:爲了判斷版本是否衝突,首先會根據文檔id從內存中的map中獲取versionValue,獲取不到則從磁盤中獲取,如果還獲取不到說明之前沒有索引過這個文檔,則不存在版本衝突的問題。獲取到versionValue後會和index.version()進行比較,看是否存在版本衝突。index.version()是在發送索引命令時指定的參數。
對於3的說明:maxUnsafeAutoIdTimestamp用於記錄之前處理的文檔的autoGeneratedIdTimestamp的最大值,如果不是retry,且autoGeneratedIdTimestamp小於maxUnsafeAutoIdTimestamp,說明之前已經索引過,反之則沒建立過索引【這兒存在一個問題,分佈式情況下,如何保證到達的順序(小的autoGereratedIdTimestamp先處理),如果這個id是在到達本機之後才生成的就不存在這個問題(如果是一個進程生成纔不存在這個問題,多個進程還是存在這個問題)】。如果是retry,則返回mayHaveBeenIndexBefore(true),如果autoGenerateIdTimestamp小於maxUnsafeAutoIdTimestamp,無操作,如果大於則將其值設置到maxUnsafeAutoIdTimestamp中
對於4的說明:這四種策略最終都會創建一個IndexingStrategy對象。
final boolean currentNotFoundOrDeleted; 這個文檔不存在or已經被刪除(versionValue.isDelete())
final boolean useLuceneUpdateDocument; 使用lucene更新文檔
final long seqNoForIndexing; lucene中從0開始自增的文檔編號
final long versionForIndexing; 版本號
final boolean indexIntoLucene; 與useLuceneUpdateDocument相對,這個是直接寫入而非更新
final Optional<IndexResult> earlyResultOnPreFlightError; 之前的錯誤信息
至此,總覽圖中的1準備文檔的索引計劃就分析完成了。
索引寫入lucene
接着開始分析總覽中的 ——2:寫入lucene返回indexResult。
ing
參考文檔:
https://segmentfault.com/a/1190000011272749