elasticSearch整理
基礎概念
ElasticSearch是什么?
- Elasticsearch是一個開源的搜索引擎,基于全文搜索引擎庫Lucene。
- Lucene是一個開源的全文搜索引擎庫,但Lucene非常復雜,普通玩家玩不了。為了隱藏Lucene的復雜性,Elasticsearch在Lucene的基礎上進行了封裝,提供了一套簡單一致的RESTful API,提供了分布式存儲,提供了準實時的分析引擎和搜索引擎。
ElasticSearch的使用場景
- 面向搜索 —— 全文檢索,英文分詞/中文分詞
- 面向分析 —— 數據聚合,統計分析
- 時間序列數據庫 —— http://www.infoq.com/cn/articles/database-timestamp-01 / 02 / 03
Near Realtime(NRT)
- ES基本上可以做到實時搜索,從數據寫入ES到可搜索到該數據,延遲大概是1秒左右(這個數值可以配置)
Cluster && Node
- 集群和節點。
- ES是一個分布式的系統,可以通過增加新的服務器,非常便捷的進行橫向擴展。
- 每個ES運行實例稱為一個Node節點。
- 多個ES節點組成一個集群。集群中有有一個Master節點,該節點是動態選舉出來的,一旦當前的Master節點宕機了,集群會自動選舉出新的Master節點。
Index && Type
- 索引。
- 索引是ES中數據的容器。概念上,索引類似mysql中的database。
- 索引下可以有多個Type,Type的概念類似mysql中的table。
- 但是,需要謹記的是,Type跟mysql中的table有很大不同,體現在:
- 1) 同一個index下的所有type,應該具備相似屬性
- 2) 同一個index下,不同的type中的字段,如果字段同名,那么這些字段應該是同一類型的
- 3) ES中有許多優化和操作,都是基于index的
- 4) 在以后的ES版本中,可能會去掉Type的概念
Document
- 文檔。
- ES中的文檔,在概念上相當于mysql的row,但比row更靈活。
- ES中的文檔是一個JSON對象,即使在同一個type中,不同的document的字段可以不一樣。也允許動態增加新的字段。文檔中每個字段有固定的類型,包括整數、日期、文本等等,甚至可以嵌套JSON對象。
Mapping
- 相當于mysql中的schema(即表的結構定義),用來規定文檔中的字段類型
- 但要注意的是,已經創建的索引,不能變更字段的類型。
- 字段的類型很豐富,除了常規的數字、日期、字符串之外,還可以是GEO-Point、GEO-shape、IP
Analyze && Term
- 分詞。
- 對一段文本(text)進行分詞處理,得出一系列的詞(token)。
- ES除了會對存儲的字段進行分詞處理外,在搜索的時候,也會對搜索的文本進行分詞處理。
- ES中內置有很多分詞器,比較常見的有standard、whitespace、english等等。對于中文分詞,則常用ik。
- 我們在mapping中,可以指定字段的分詞器。
- 一個分詞,在ES中,通常稱之為一個Term。
- 中文分詞示例
-
curl -X GET "localhost:9200/_analyze" -H 'Content-Type: application/json' -d'
{
"analyzer" : "ik_max_word",
"text" : "中華人民共和國,我的祖國,我愛你!!!”
}
'
Shards && Replicas
- shard:分片
- replica:分片的副本
- shards和replicas是ES分布式能力的體現,雖然對用戶來說是透明的,但理解它們,有助于你理解ES的查詢和聚合結果
Shard
- 一個index所包含的數據可以非常的大(TB級別),通常一臺單獨的機器是無法承載的。
- 為解決這個問題,ES將一個index分割成多個shard,而shard則分布在各個node上。
- 一個文檔存放在哪個shard上?默認情況下是通過對文檔ID進行哈希后,分配到對應的shard上。也可以通過routing參數,取代文檔ID作為要哈希的值。
- 獲取搜索或聚合結果時,會先從每個shard中獲取數據,然后將每個shard返回的結果歸并起來
Replica
- 對于index中的每個shard,為了提高可用性,可以設置對應的復制shard(replica shards,簡稱replicas)。
- 在index創建的時候,可以指定shard的數量和replicas的數量;但index創建之后,可以動態修改replicas的數量,但不能修改shard的數量。
- replicas的優點:
- 提供了高可用性,即使primary shard崩潰了,依然可以通過replicas來向外提供查詢服務。這包含著一個隱式的要求——replica shard和primary shard不能存儲在同一個node中。
- 對于查詢請求,可以在replica shard中并行執行,這樣提高了ES的性能和吞吐量。
ES搜索
ES提供兩種搜索方式
- DSL搜索,DSL(domain-specific language)領域特定語言,簡單來說,就是ES自己定義的一套搜索語法
- URI搜索,即在url中通過參數q來傳遞搜索條件
- curl "localhost:9200/shakespeare/_search?q=*&pretty”
-
? ? ? ? q=*表示查詢所有內容
- curl "localhost:9200/shakespeare/_search?q=line_id:15&pretty"
-
? ? ? ? q=line_id:15表示精確查詢line_id=15的內容
- curl "localhost:9200/shakespeare/_search?q=text_entry:meet&pretty"
-
? ? ? ? q=text_entry:meet表示模糊查詢text_entry包含meet的內容
ES全文檢索
Match Query
- 匹配查詢。標準的全文檢索方法,包含了模糊匹配。
- match query通常會指定要檢索的字段(如果要檢索所有的字段,可以將字段名設置為_all)。
- match query的基本流程是:首先將輸入的文本進行分析(analyze),分成多個phrase。每個phrase都會嘗試去匹配document中的指定filed??梢愿鶕perator參數,來指定多個phrase的匹配是 and 還是 or 操作,默認是or。
- match query功能很豐富,包括支持模糊查詢。
ES Term level Query
- Term Query
- Prefix Query
- Wildcard Query
- Regexp Query
ES Bool Query
- 最常用的復合查詢,由一個或多個布爾子句組成
- 布爾子句的類型包括:
- must:must中包含的query必須都被匹配到,并且會對分數有貢獻。類似 AND。
- filter:類似must,但filter中query將會在filter context中執行,意味著這些query不會對score造成影響。
- should:類似OR,但也有一些區別。當bool query在query context中執行時,并且擁有一個must或者filter子句,此時,如果某個文檔被must或filter子句匹配到了,即使該文檔沒有被任意一個should query匹配到,該文檔依然會被bool query查詢出來。反之,如果bool query在filter context中執行,或者bool query中沒有must和filter子句,此時,文檔必須匹配至少一個should query。
- must_not:顧名思義,被must_not query匹配到文檔,不能出現在bool query的查詢結果中。特別注意的是,must_not是在filter cotext中執行的,所以must_not query不會對score造成影響,must_not query返回的文檔的score=0。
- 布爾子句的類型包括:
ES Geo Query
- 地理位置搜索
- 搜索車輛方圓 x 米的所有倉庫
- 搜索倉庫方圓 x 米的所有車輛(或者車輛軌跡)
- 可以定義一個多邊形,搜索在該多邊形內部的所有車輛(電子圍欄)
- 還有更多復雜的地理位置的功能
ES聚合分析
- ES中的聚合分析大概可以分成3種
- Metrics Aggregations
- Sum Aggregation
- Avg Aggregation
- Max/Min Aggregation
- Bucket Aggregations
- Terms Aggregation
- Range Aggregation
- Pipeline Aggregations
- 管道聚合
- Metrics Agg和Bucket Agg都是針對同級的query的查詢結果進行計算后的數據聚合分析
- 管道聚合則是對聚合結果再進行進一步的聚合分析
- Metrics Aggregations
ES的PHP Client
- ruflin/elastica
- https://github.com/ruflin/Elastica
ES寫數據過程
- 客戶端選擇一個 node 發送請求過去,這個 node 就是?coordinating node(協調節點)。
- coordinating node?對 document 進行路由,將請求轉發給對應的 node(有 primary shard)。
- 實際的 node 上的?primary shard?處理請求,然后將數據同步到?replica node。
- coordinating node?如果發現?primary node?和所有?replica node?都搞定之后,就返回響應結果給客戶端。
ES讀數據過程
- 通過?doc id?來查詢,會根據?doc id?進行 hash,判斷出來當時把?doc id?分配到了哪個 shard 上面去,從那個 shard 去查詢。
- 客戶端發送請求到任意一個 node,成為?coordinate node。
- coordinate node?對?doc id?進行哈希路由,將請求轉發到對應的 node,此時會使用?round-robin?隨機輪詢算法,在?primary shard?以及其所有 replica 中隨機選擇一個,讓讀請求負載均衡。
- 接收請求的 node 返回 document 給?coordinate node。
- coordinate node?返回 document 給客戶端。
ES寫數據底層原理
數據先寫入內存 buffer,然后每隔 1s,將數據 refresh 到 os cache,到了 os cache 數據就能被搜索到(所以我們才說 es 從寫入到能被搜索到,中間有 1s 的延遲)。每隔 5s,將數據寫入 translog 文件(這樣如果機器宕機,內存數據全沒,最多會有 5s 的數據丟失),translog 大到一定程度,或者默認每隔 30mins,會觸發 commit 操作,將緩沖區的數據都 flush 到 segment file 磁盤文件中。
數據寫入 segment file 之后,同時就建立好了倒排索引。
索引性能優化:
- 使用自動id
- 調大flush時間
- 禁止refresh和replicas
- 禁止OS將es進程swap出去
- 加大 indexing buffer size
讀性能優化:
- 數據預熱,冷熱分離
- filesystem cache越大越好?
- 分頁不要過深
- 避免 join等復雜操作。具體是指
- a.nested 會使得查詢慢 好幾倍
- b.parent-child關系 更是使得查詢慢幾百倍
elasticSearch使用示例:
返回所有索引:curl -XGET 'localhost:9200/_cat/indices?v'
返回所有索引別名(aliases):curl -XGET 'localhost:9200/_cat/aliases?v&pretty'
curl -XPOST "localhost:9200/alias_gold_track_hardware/_mapping?pretty” -d ‘{“channel”:{“index”:true}}’
返回指定size條數據:curl -XPOST 'localhost:9200/index_gold_track_hardware_201904/_search?pretty'? -d '{"query": {"match_all”:{}},? "size:10}’
刪除索引:curl -X DELETE? 'localhost:9200/index_gold_track_history_201905/track/_search?pretty'? -d '{"query": {"match_all”:{}}}’
新建索引:curl -XPUT 'http://localhost:9200/index_gold_track_history_201906'
nested的查詢示例:curl -XPOST? 'localhost:9200/index_gold_vehicle/_search?pretty' -H 'Content-Type: application/json'? -d '{
? "query": {
? ? "bool": {
? ? ? "must": [
? ? ? ? {
? ? ? ? ? "nested": {
? ? ? ? ? ? "path": "vehicle_monitors",
? ? ? ? ? ? "query": {
? ? ? ? ? ? ? "bool": {
? ? ? ? ? ? ? ? "must": [
? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? "match": {
? ? ? ? ? ? ? ? ? ? ? "vehicle_monitors.monitor_type": 1
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ]
? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? }
? ? ? ? }
? ? ? ]
? ? }
? }
}'
term&range查詢示例:
'{
? "query": {
? ? "bool": {
? ? ? "filter": [
? ? ? ? { "term": {"imei" : "0863014531236435"}},
? ? ? ? { "range": { "collect_time": { "gte": "1552454089" }}}
? ? ? ]
? ? }
? }
}
按balance分區聚合:
curl -X GET "localhost:9200/bank/_search?pretty" -H 'Content-Type: application/json' -d'
{
? ? "size": 0,
? ? "aggs" : {
? ? ? ? "balance_ranges" : {
? ? ? ? ? ? "range" : {
? ? ? ? ? ? ? ? "field" : "balance",
? ? ? ? ? ? ? ? "ranges" : [
? ? ? ? ? ? ? ? ? ? { "to" : 10000 },
? ? ? ? ? ? ? ? ? ? { "from" : 10000, "to" : 30000 },
? ? ? ? ? ? ? ? ? ? { "from" : 30000 }
? ? ? ? ? ? ? ? ]
? ? ? ? ? ? }
? ? ? ? }
? ? }
}
'
聚合嵌套:計算每個分區中的平均余額
curl -X GET "localhost:9200/bank/_search?pretty" -H 'Content-Type: application/json' -d'
{
? ? "size": 0,
? ? "aggs" : {
? ? ? ? "balance_ranges" : {
? ? ? ? ? ? "range" : {
? ? ? ? ? ? ? ? "field" : "balance",
? ? ? ? ? ? ? ? "ranges" : [
? ? ? ? ? ? ? ? ? ? { "to" : 10000 },
? ? ? ? ? ? ? ? ? ? { "from" : 10000, "to" : 30000 },
? ? ? ? ? ? ? ? ? ? { "from" : 30000 }
? ? ? ? ? ? ? ? ]
? ? ? ? ? ? },
? ? ? ? ? ? "aggs": {
? ? ? ? ? ? ? ? "avg_balance": {
? ? ? ? ? ? ? ? ? ? "avg": {
? ? ? ? ? ? ? ? ? ? ? ? "field": "balance"
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? }
}
'
聚合嵌套:獲取每個州中的余額最多的賬戶
curl -X POST "localhost:9200/bank/_search?size=0&pretty" -H 'Content-Type: application/json' -d'
{
? ? "aggs": {
? ? ? ? "top_tags": {
? ? ? ? ? ? "terms": {
? ? ? ? ? ? ? ? "field": "state.keyword",
? ? ? ? ? ? ? ? "size": 100
? ? ? ? ? ? },
? ? ? ? ? ? "aggs": {
? ? ? ? ? ? ? ? "top_rich_hits": {
? ? ? ? ? ? ? ? ? ? "top_hits": {
? ? ? ? ? ? ? ? ? ? ? ? "sort": [
? ? ? ? ? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "balance": {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "order": "desc"
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? ],
? ? ? ? ? ? ? ? ? ? ? ? "size" : 1
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? }
}
'
細節待完善....
總結
以上是生活随笔為你收集整理的elasticSearch整理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 赋值具有的非单一 rhs 维度多于非单一
- 下一篇: 最新分布式存储解决方案zData将于闪存