ElasticSearch是建立在全文搜索引擎 Apache Lucene(TM) 基礎上的分布式、高性能、高可用、可伸縮的實時搜索和分析引擎??芍С謹U展到上百臺服務器,處理PB級別的結構化或非結構化數據。常用于日志數據分析、商品檢索等場景。
索引的寫入機制
Elasticsearch索引是以分片的形式進行保存的,一個索引由多個主分片(默認為5個)組成,每一個主分片通常有一個或多個副本。
當數據寫入的時候,Elasticsearch首先根據路由規則對路由參數(路由參數默認使用_id,當然Index Request中也可以設置使用哪個Filed的值作為路由參數)進行Hash取模,確定要寫入的主分片。
shard = hash(routing) % number_of_primary_shards
然后,通過集群狀態信息,找出要寫入的主分片所在的節點,將請求轉發到此節點。當主分片成功寫入數據后,會并行地將請求轉發送給它的副本。當請求在全部副本上執行成功,并響應主分片后,主分片將結果返回給客戶端。
在Elasticsearch將索引數據寫入分片的過程中,首先會將索引數據保存到內存緩存中,與此同時還生成translog(這是保證數據一致性的關鍵)。然后,再以默認1秒的速度,將內存緩存中的數據按片段(segment)為單位刷新到文件系統的緩存中。要保證索引數據能被搜索,將索引數據刷新到文件系統的緩存中是關鍵。
由于內存緩存中的數據,默認每1秒都會以片段(segment)的方式刷新至文件系統緩存中,所以,如果不進行片段合并,文件緩存中的片段數將非常龐大。因此,為減少片段(segment)數量,在將內存中的索引片段刷新到文件系統的緩存中時,Elasticsearch會將多個小的片段(segment)合并成一個大的片段(segment),當大片段合成完后,小的片段將會被刪除掉。
前面已經提到,Elasticsearch索引數據的一致性是通過translog來保證的,默認情況下,Elasticsearch每5秒,或每次請求操作結束前,就會強制刷新translog到磁盤上,當translog成功保存到磁盤后,translog就會被Elasticsearch刪除。
分片的分配機制
每一個索引數據都是由多個分片租成的,當創建索引、刪除索引、新增索引副本、增減節點時,就會發生分片分配操作。某個分片分配到哪個節點,一般來說,是由Elasticsearch自動決定的。
Elasticsearch中,比較常見的分配策略有兩種:
- 磁盤限額:為了保護節點數據安全,Elasticsearch會定時(默認30秒)檢查一下各節點的數據目錄磁盤使用情況。當達到cluster.routing.allocation.disk.watermark.low(默認85%)時,新索引分片就不會再分配到這個節點上。當達到cluster.routing.allocation.disk.watermark.high(默認90%)時,就會觸發該節點現存分片的數據均衡,把數據挪到其他節點上去。這兩個值不但可以寫百分比,還可以寫具體的字節數。
- 熱索引分片不均勻:默認情況下,Elasticsearch集群的數據均衡策略時以各節點的分片總數作為基準的。這對于搜索服務來說無疑是均衡搜索壓力、提升性能的好辦法。但對于ELK stack場景,一般壓力集中在新索引的數據寫入方面。正常運行的時候,也沒有問題。但當集群擴容時,新加入集群的節點,分片總數遠低于其他節點。這個時候如果有新索引創建,Elasticsearch的默認策略會導致新索引的所有主分片幾乎全部分配到這臺新節點上。整個集群的寫入壓力,壓在一個節點上,結果很可能是這個節點直接被壓死,集群出現異常。所以,對于ELK stack場景,強烈建議大家預先計算好索引的分片數后,配置好單節點分片的限額。