ES在建立索引的時候和Lucene是有一定區別的,因爲它對Lucene進行了一定的優化,內部還牽涉到分佈式索引的分發,下面就詳細的分析一下寫入原理思想以及流程和對應節點的處理
一:寫入原理以及特性
1 寫入索引的時候,首先先寫入到lucene,然後再寫入到translog,主要原因如下
.Lucene的內存寫入會有很複雜的邏輯,很容易失敗
.避免TransLog中有大量無效記錄,減少recover的複雜度和提高速度
2 寫入索引需要考慮到下面各個維度
可靠性:或者是持久性,數據寫入系統成功後,數據不會被回滾或丟失
一致性:數據寫入成功後,再次查詢時必須能保證讀取到最新版本的數據,不能讀取到舊數據
原子性:一個寫入或者更新操作,要麼完全成功,要麼完全失敗,不允許出現中間狀態
隔離性:多個寫入操作相互不影響
實時性:寫入後是否可以立即被查詢到
性能:寫入性能,吞吐量
二:寫入流程
索引的寫入過程是比較複雜的,集羣中的各個節點都需要承擔一部分工作,下面把常規節點在寫入索引過程中具體是幹什麼的,分析一下
1 ClientNode:客戶端節點
> Ingest Pipeline
對原始文檔做一些處理,比如HTML解析,自定義的處理,具體處理邏輯可以通過插件來實現
> Auto Create Index
判斷當前Index是否存在,如果不存在,則需要自動創建Index,這裏需要和Master交互
> Set Routing
如果Request中指定了路由條件,則直接使用Request中的Routing,否則使用Mapping中配置的,如果Mapping中無配置,則使用默認的_id字段值。
> Construct BulkShardRequest
同一個Shard中的請求聚集在一起,構建BulkShardRequest,每個BulkShardRequest對應一個Shard
> Send Request To Primary
將每一個BulkShardRequest請求發送給相應Shard的Primary Node
2 PrimaryNode:主節點
> Index or Update or Delete
循環執行每個Single Write Request,對於每個Request選擇不同的邏輯來處理
> Translate Update To Index or Delete
Update操作的特有步驟:
會通過GetRequest查詢到已經存在的同_id Doc
(如果有)的完整字段和值(依賴_source字段),然後和請求中的Doc合併
獲取到讀到的Doc版本號,記做V1。
> Parse Doc
這裏會解析Doc中各個字段。生成ParsedDocument對象,同時會生成uid Term
> Update Mapping
有個自動更新Mapping的功能,就在這一步生效
> Get Sequence Id and Version
。則會從SequenceNumber Service獲取一個sequenceID和Version
。SequenceID在Shard級別每次遞增1,SequenceID在寫入Doc成功後,會用來初始化LocalCheckpoint
> Add Doc To Lucene
索引寫入LUCENE,此時索引文件是保存在內存中,對查詢不可見
> Write Translog
。索引寫入LUCENE,此時索引文件是保存在內存中,對查詢不可見
。寫完Lucene的Segment後,會以keyvalue的形式寫TransLog,Key是_id,Value是Doc內容
。當查詢的時候,如果請求是GetDocByID,則可以直接根據_id從TransLog中讀取到,滿足NoSQL場景下的實時性要去
> Renew Bulk Request
。這裏會重新構造Bulk Request,原因是前面已經將UpdateRequest翻譯成了Index或Delete請求
。不需要再執行Update邏輯,一是保證Replica中邏輯更簡單,性能更好,二是保證同一個請求在Primary和Replica中的執行結果一樣
> Flush Translog
這裏會根據TransLog的策略,選擇不同的執行方式,要麼是立即Flush到磁盤,要麼是等到以後再Flush
Flush的頻率越高,可靠性越高,對寫入性能影響越大
> Send Requests To Replicas
將剛纔構造的新的Bulk Request並行發送給多個Replica,然後等待Replica的返回,等待多個Replica成功返回後,Primary Node纔會返回用戶
具體需要多少Replica Node返回,可以通過配置或者請求參數設置
> Receive Response From Replicas
Replica中請求都處理完後,且滿足最小Replica返回數後,會更新Primary Node的LocalCheckPoint
3 ReplicaNode:副本節點
Replica中請求都處理完後,且滿足最小Replica返回數後,會更新Primary Node的LocalCheckPoint
三:牽涉源碼類
TransportShardBulkAction:批量傳輸主節點Request
TransportReplicationAction:批量傳輸副本節點Request
PrimaryOperationTransportHandler:處理主節點
ReplicaOperationTransportHandler:處理副本節點之間的數據
對於索引的寫入,如果數據量很大的話,索引也是需要進行一定的優化,這個後面會有專門的章節來講述的.