松花皮蛋的黑板報
  • 分享在京東工作的技術感悟,還有JAVA技術和業內最佳實踐,大部分都是務實的、能看懂的、可復現的

掃一掃
關注公眾號

ES學習

博客首頁文章列表 松花皮蛋me 2019-04-17 20:10

一、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的使用經驗

2.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越小區分度就越高。反之,就類似停止詞,”你,是,的”等等

推薦閱讀

    閱讀 1161 次
    黑龙江6+1开奖结果查询