ES學習分享

  • 2019 年 10 月 4 日
  • 筆記

文章轉載自公眾號 松花皮蛋的黑板報 , 作者 梁松華

一、ES是什麼

Elasticsearch是一個基於Apache Lucene的開源搜索引擎,通過簡易的API來隱藏Lucene的複雜性。ES的基本結構包括,Cluster集群(由n個節點組成),Node實例節點,Index索引(一系列documents的集合),Shard分片(索引的數據是分配到各個分片的),Replica備份節點(相應有Primay Shard主分片)

ES架構

ES和RDMS的區別

二、ES不是什麼

1、ES不是資料庫,不是可靠的數據存儲系統。 [Indexing] A network partition can cause in flight documents to be lost 2、ES不是實時系統,數據寫入成功只是translog成功,類似mysql的binlog,同理刪除數據也不是實時的。其實ES內部有一個後台執行緒,定時將記憶體的數據寫入到存儲引擎中。當然可以寫入數據後refresh,但是會重新打開所有索引文件,需要解壓和刷快取等等,性能影響極大 3、ES不是一個強一致性的系統。也就是說同樣的query多次查詢的數據可能會不一致。由於shard的主分片和副本是由獨立的節點去刷新的,刷新的頻率並不同步,這樣同樣的query發送到不同的分片(主片和從片)上看到的數據是不同的,導致的結果是查詢到的數據也不完全同步。簡單說,ES是一個最終一致性系統

三、Mapping映射

mapping相當於資料庫的表結構,決定了ES在建立倒排索引、進行檢索時對文檔採取的相關策略,如數字類型、日期類型、文件類型等。在寫數據前ES不強制要求創建mapping,因為ES有動態識別和創建的機制,但是非常不建議使用ES的動態識別和創建的機制,因為很多情況下這並非你所需要。推薦的做法是在寫數據之前仔細的創建mapping mapping不能更新,存在的欄位不能被更新和刪除,不存在的欄位可以添加 mapping衝突。同一索引不同類型同名欄位的映射會衝突 https://www.elastic.co/blog/great-mapping-refactoring#conflicting-mappings

四、Template模板

模板是描述表結構(mapping)和表設置(setting)的數據結構,在ES中創建一個索引模板,其本質就是包含mapping及分片資訊,模板中有個屬性 template 表示該模板用來匹配什麼樣的索引。比如"template:timingsoa-*「,創建的所有以timingsoa開頭的索引,將會應用這個模板,一般用來匹配按周期創建的索引,例如 timingsoa-20190417

{    "template": "timingsoa-*",    "settings": {      "index": {        "refresh_interval": "1s",        "number_of_shards": "4",        "number_of_replicas": "1"      }    },    "mappings": {      "timingsoa": {        "properties": {          "time": {            "format": "yyyy-MM-dd HH:mm:ss",            "type": "date"          },          "className": {            "type": "keyword"          },          "methodName": {            "type": "keyword"          },          "invokeNo": {            "type": "keyword"          },          "threadId": {            "type": "keyword"          },          "invokeIp": {            "type": "keyword"          },          "message": {             "analyzer": "ik_smart",              "type": "text"          },          "lineNumber": {            "type": "integer"          },          "invokeSerialNum": {            "type": "integer"          }        }      }    }  }

索引存在Linux伺服器的文件系統上,背後是文件系統,不是類似HDFS的文件系統

五、Routing路由

rouing就是hash key,這個key決定寫入和查詢的分片id

六、Alia別名

PUT timingsoa  {     "mappings": {          "timingsoa": {            "properties": {              "time": {                "format": "yyyy-MM-dd HH:mm:ss",                "type": "date"              },              "className": {                "type": "keyword"              },              "methodName": {                "type": "keyword"              },              "invokeNo": {                "type": "keyword"              },              "threadId": {                "type": "keyword"              },              "invokeIp": {                "type": "keyword"              },              "message": {                 "analyzer": "ik_smart",                  "type": "text"              },              "lineNumber": {                "type": "integer"              },              "invokeSerialNum": {                "type": "integer"              }             }            },         "aliases": {            "admin_w": {},            "admin_r": {}         }      }

為什麼需要別名https://www.elastic.co/guide/en/elasticsearch/guide/current/index-aliases.html

七、ES集群

1、節點發現

多播方式,也是ES的默認使用方式,但是無法跨網路組建集群。另外一種是單播方式,可以跨網路組建集群

2、主節點選舉

所有配置有master:true的節點,根據節點id進行排序,然後取出第一個作為主節點

3、存活檢測

有兩種錯誤檢測方式,一種是master節點ping集群中所有其他的節點來驗證他們是否存活,另一種是每個節點ping master節點來驗證它是否存活

4、容災

ES中的index,首先會進行分片,每一個分片數據一般都會有自己的副本數據,ES分配分片的策略會保證同一個分片數據和自己的副本不會分配到同一個節點上 當集群中的某一節點宕機後,ES的master在ping該節點時通過一定的策略會發現該節點不存活;此時,ES開啟恢復過程,恢復的策略如下: 恢復的目標是保證集群中分片的副本數不變

4.1 恢復的目標是保證集群中分片的副本數不變 4.2 如果宕機的節點上承載某分片的主分片,那麼此時(恢復過程)會將該分片分配在其他節點上的某一副本提升為主分片(記住:同一分片和其副本總是不在同一節點上,保證有對應的副本可供提升的) 4.3 根據4.1保證副本數不變,如果宕機的節點承載某分片的副本,那麼ES會在其他非宕機節點上用主分片複製一個副本 4.4 整個過程不影響集群的讀寫功能;但是由於多了複製分片和遷移分片的過程,集群的讀寫性能受影響

5、擴容和縮容

整個過程不影響集群的讀寫功能,但是由於多了複製分片和遷移分片的過程,集群的讀寫性能受影響

八、ES寫入文檔過程

圖片來自https://zhuanlan.zhihu.com/p/34669354

另外ES沒有原地update的能力,所有的update都是標記刪除老文檔。並發update同一條document,ES內部採用了樂觀並發的處理,並發修改的操作直到最後要提交是才加鎖檢查版本號,如果發現修改之前獲取的版本號已經改變(即已經被人修改),那麼會拋出這個異常,然後由用戶決定如何處理該異常

九、ES查詢文檔過程

圖片來自 https://zhuanlan.zhihu.com/p/34674517

當然你可以指定perference,指定在主分片查詢或者先主後副等等

十、ES索引創建過程

十一、ES新節點加入過程

十二、ES規範

12.1、Mapping設計規範

1、禁用mapping的dynamic 當 indices的mapping已經確定時(即不會改變時),強烈建議將 dynamic設置為false,這樣可以避免非法數據被ES索引 2、避免不必要的tokenizer ES在進行analyzer時,會經過以下三個步驟:character -> tokenizer -> token filer,當text不需要進行 tokenizer時,需要設置index:not_analyzed(5.X版本設置為type:keyword) 3、nested結構 結構化的JSON文檔會平整成索引內的簡單鍵值對,會造成交叉對象匹配,數據間的關聯性就會丟失。而nested將list里的每個doc單獨變成子文檔進行存儲,避免了這個問題 https://www.elastic.co/guide/en/elasticsearch/guide/master/nested-objects.html 4、列式存儲doc_values(大部分type默認為true) ES提供了doc_value屬性,如果對某欄位設置了doc_value,那麼該欄位被用來排序或者聚合的情況下,並不會載入到記憶體而是仍然從硬碟讀取,防止OOM。實際上Lucene在構建索引時,會額外建立一個有序的基於document=>field value的映射列表 5、TTL的使用經驗 ES2.X對TTL已經是deprecated, 在最新版本5.X里已經是remove了

12.2、索引設計規範

1、設置合理的number_of_shards number_of_shards決定indices在ES集群中,如何均衡的分布在各個 data node,而使用ES進行搜索時,ES會並行的查詢分布在各個data node的shard(而都在同一個節點的 shards,只能進行串列的操作),最後將各個data node返回的數據進行聚合,並返回給客戶端 2、合理設置 routing key 可以通過合理設置routing key,可以避免在查詢時查詢多個shards。因為相同的routing key都在同一個shard 3、定期創建索引 有些業務需要定期創建索引,比如日誌等 4、索引數據刪除 建議基於索引刪除數據,新版本已不推薦使用type,應考慮多建索引 5、Type 在很多數據能分為獨立index的情況下,不要放到一個index里用type去分。但是type能減少index的數量,而且在父子文檔和文檔映射相似的情下,使用type更佳,因為搜索一個index下的多個type,和只搜索一個 type相比沒有額外的開銷,需要合併結果的分片數量是一樣的 https://www.elastic.co/blog/index-vs-type

12.3、查詢規範

1、search type不要用dfs_query_then_fetch,用query_then_fetch足夠 這裡再提下前面的ES默認查詢流程,也就是scatter多分片-gather-sort,而dfs_query_then_fetch多了初始化發散(initial scatter),進行真正的查詢之前,先把各個分片的詞頻率和文檔頻率收集一下,然後進行詞搜索的時候,各分片依據全局的詞頻率和文檔頻率進行搜索和排名,查詢效率慢但是精度高 2、儘可能的用filter,它快 3、使用scroll/scan,相當於資料庫的游標方式代替深分頁(size=10&from=10000) 4、不要使用post filter,post filter的內部實現相當於資料庫的掃表,因此非常非常慢 5、非常不推薦依賴delete-by-query這個插件做刪除操作 性能很差,對集群也有不良影響,推薦按日期去建索引,速度快、性能高

十三、其他

1、倒排索引 倒排索引一般表示為一個關鍵詞,然後是它的頻度,位置等,類似圖書的目錄 2、TF-IDF 詞頻(TF)表示一個給定詞語t在給定文檔d中出現的概率,概率越高重要程度越高 文檔頻率(DF)表示文檔集中包含給定詞語t的所有文檔數目,顯然TF越高同時DF越小區分度就越高。反之,就類似停止詞,"你,是,的"等等