Elasticsearch學習隨筆

前言:本文內容爲,我在閱讀,學習elasticsearch官方文檔時候的隨筆。以運維工程師的角度學習elasticsearch。內容比較混亂。詳細的內容,請參考官方文檔。

 

1.後臺運行elasticsearch
工作目錄下,./bin/elasticsearch -d   

注意:由於安全問題,elasticsearch不允許root用戶直接運行。因此需要用其他用戶來執行程序(1.chown -R user;./bin/elasticsearch -d)


2.
節點客戶端(Node client)
節點客戶端作爲一個非數據節點加入到本地集羣中。換句話說,它本身不保存任何數據,但是它知道數據在集羣中的哪個節點中,並且可以把請求轉發到正確的節點。
傳輸客戶端(Transport client)
輕量級的傳輸客戶端可以將請求發送到遠程集羣。它本身不加入集羣,但是它可以將請求轉發到集羣中的一個節點上。


3.索引數據文檔

PUT /megacorp/employee/1
{
    "first_name" : "John",
    "last_name" :  "Smith",
    "age" :        25,
    "about" :      "I love to go rock climbing",
    "interests": [ "sports", "music" ]
}
 

megacorp:索引名稱,employee:類型名稱,1:數據的ID


4.檢索文檔
檢索id爲1的數據
GET /megacorp/employee/1

檢索所有數據(默認返回前10條)
GET /megacorp/employee/_search

根據條件檢索(可用於輕量級檢索)
GET /megacorp/employee/_search?q=last_name:Smith

查詢表達式搜索
GET /megacorp/employee/_search
{
    "query" : {
        "match" : {
            "last_name" : "Smith"
        }
    }
}

使用filter進行搜索
GET /megacorp/employee/_search
{
    "query" : {
        "bool": {
            "must": {
                "match" : {
                    "last_name" : "smith" 
                }
            },
            "filter": {
                "range" : {
                    "age" : { "gt" : 30 } 
                }
            }
        }
    }
}

全文搜索
GET /megacorp/employee/_search
{
    "query" : {
        "match" : {
            "about" : "rock climbing"
        }
    }
}
根據相關性得分進行排序輸出跟“rock climbing”有關的文檔

短語搜索
GET /megacorp/employee/_search
{
    "query" : {
        "match_phrase" : {   //使用match_phrase參數,精準匹配短語
            "about" : "rock climbing"
        }
    }
}

高亮搜索
GET /megacorp/employee/_search
{
    "query" : {
        "match_phrase" : {
            "about" : "rock climbing"
        }
    },
    "highlight": {
        "fields" : {
            "about" : {}
        }
    }
}

分析
GET /megacorp/employee/_search
{
  #可添加匹配條件
  "query": { 
    "match": {
      "last_name": "smith"
    }
  },
  "aggs" : {
        "all_interests" : {
            "terms" : { "field" : "interests" },
            #分級彙總
            "aggs" : {
                "avg_age" : {
                    "avg" : { "field" : "age" }
                }
            }
        }
    }
}


5.分佈式特性
Elasticsearch 儘可能地屏蔽了分佈式系統的複雜性。這裏列舉了一些在後臺自動執行的操作:
    --分配文檔到不同的容器 或 分片 中,文檔可以儲存在一個或多個節點中
    --按集羣節點來均衡分配這些分片,從而對索引和搜索過程進行負載均衡
    --複製每個分片以支持數據冗餘,從而防止硬件故障導致的數據丟失
    --將集羣中任一節點的請求路由到存有相關數據的節點
    --集羣擴容時無縫整合新節點,重新分配分片以便從離羣節點恢復


集羣原理
1.健康狀態
GET /_cluster/health
green
所有的主分片和副本分片都正常運行。
yellow
所有的主分片都正常運行,但不是所有的副本分片都正常運行。
red
有主分片沒能正常運行。

注:單節點時,監控狀態出現yellow:集羣原理裏,如果持有主分片的節點掛掉了,一個副本分片就會晉升爲主分片的角色。那麼可以看出來副本分片和主分片是不能放到一個節點上面的,可是在只有一個節點的集羣裏,副本分片沒有辦法分配到其他的節點上,所以出現所有副本分片都unassigned得情況。因爲只有一個節點,如果存在主分片節點掛掉了,那麼整個集羣理應就掛掉了,不存在副本分片升爲主分片的情況。解決辦法就是,在單節點的elasticsearch集羣,刪除存在副本分片的索引,新建索引的副本都設爲0。然後再查看集羣狀態。

2.創建索引
PUT /blogs
{
   "settings" : {
      #分片數量,副本數量    
      "number_of_shards" : 3, 
      "number_of_replicas" : 1
   }
}

3.單播形式加入集羣
修改elasticsearch.yml文件:
node.name=node-srv1
network.host=0.0.0.0|x.x.x.x
discovery.zen.ping.unicast.hosts: ["host1", "host2:port"]


集羣管理、監控與部署
監控
1.marvel監控

安裝marvel
i)每一個ES安裝licence、marvel插件
      進入elasticsearch/bin下,
    bash plugin install licence 
    bash plugin install marvel-agent
ii)配置elasticsearch.yml配置文件,添加action.auto_create_index: .marvel-*
iii)kibana安裝marvel插件
    bash kibana plugin --install elasticsearch/marvel/latest
iv)重啓ES,kibana服務
    bash elasticsearch -d
    systemctl restart kibana

2.集羣健康
GET _cluster/health
{
    #集羣名稱
   "cluster_name": "elasticsearch_zach",   
    #集羣狀態   
   "status": "green",
   "timed_out": false,
       #node包括node.master、node.data兩種類型,
       #參考:https://blog.csdn.net/J_bean/article/details/80147277
   "number_of_nodes": 1,
   "number_of_data_nodes": 1,
       #主分片數量
   "active_primary_shards": 10,
       #分片總量
   "active_shards": 10,
       #當前正在從一個節點遷往其他節點的分片的數量,當出現擴容或者下線node時會變動
   "relocating_shards": 0,
       #是剛剛創建的分片的個數,臨時事件
   "initializing_shards": 0,
       #已經在集羣狀態中存在的分片,但是實際在集羣裏又找不着
       #通常未分配分片的來源是未分配的副本
       #如果你的集羣是 red 狀態,也會長期保有未分配分片    
   "unassigned_shards": 0
}

集羣狀態
green
所有的主分片和副本分片都已分配。你的集羣是 100% 可用的。
yellow
所有的主分片已經分片了,但至少還有一個副本是缺失的。不會有數據丟失,所以搜索結果依然是完整的。不過,你的高可用性在某種程度上被弱化。如果 更多的 分片消失,你就會丟數據了。把 yellow 想象成一個需要及時調查的警告。
red
至少一個主分片(以及它的全部副本)都在缺失中。這意味着你在缺少數據:搜索只能返回部分數據,而分配到這個分片上的寫入請求會返回一個異常。

進一步查詢狀態
level參數幫助我們進一步查詢狀態細節
查詢索引的情況
GET _cluster/health?level=indices
查詢分片狀態
GET _cluster/health?level=shards

阻塞等待狀態變化
你可以指定一個 wait_for_status 參數,它只有在狀態達標之後纔會返回。
GET _cluster/health?wait_for_status=green
用於避免網絡延時導致的問題:可以用於腳本中,執行創建索引,並寫入文檔之間的操作。來避免因爲創建需要的時間誤差導致寫入失敗

節點監控
參考:https://www.elastic.co/guide/cn/elasticsearch/guide/current/_monitoring_individual_nodes.html#_%E7%B4%A2%E5%BC%95%E9%83%A8%E5%88%86

GET _node/stats 由於輸出內容比較長,下面分段來解析重要的內容

1)開頭部分
{
   "cluster_name": "elasticsearch_zach",
   "nodes": {
      "UNr6ZMf5Qk-YCPA_L18BOQ": {
         "timestamp": 1408474151742,
         "name": "Zach",
         "transport_address": "inet[zacharys-air/192.168.1.131:9300]",
         "host": "zacharys-air",
         "ip": [
            "inet[zacharys-air/192.168.1.131:9300]",
            "NONE"
         ],

節點是排列在一個哈希裏,以節點的 UUID 作爲鍵名。還有一些節點網絡信息。


2)索引部分
 "indices": {
        "docs": {
           "count": 6163666,
           "deleted": 0
        },
        "store": {
           "size_in_bytes": 2301398179,
           "throttle_time_in_millis": 122850
        },

返回的統計值被歸入以下部分:
    docs 展示節點內存有多少文檔,包括還沒有從段裏清除的已刪除文檔數量。
    store 部分顯示節點耗用了多少物理存儲。這個指標包括主分片和副本分片在內。
    如果限流時間很大,那可能表明你的磁盤限流設置得過低。

"indexing": {
           "index_total": 803441,
           "index_time_in_millis": 367654,
           "index_current": 99,
           "delete_total": 0,
           "delete_time_in_millis": 0,
           "delete_current": 0
        },
        "get": {
           "total": 6,
           "time_in_millis": 2,
           "exists_total": 5,
           "exists_time_in_millis": 2,
           "missing_total": 1,
           "missing_time_in_millis": 0,
           "current": 0
        },
        "search": {
           "open_contexts": 0,
           "query_total": 123,
           "query_time_in_millis": 531,
           "query_current": 0,
           "fetch_total": 3,
           "fetch_time_in_millis": 55,
           "fetch_current": 0
        },
        "merges": {
           "current": 0,
           "current_docs": 0,
           "current_size_in_bytes": 0,
           "total": 1128,
           "total_time_in_millis": 21338523,
           "total_docs": 7241313,
           "total_size_in_bytes": 5724869463
        },    

indexing 顯示已經索引了多少文檔。這個值是一個累加計數器。在文檔被刪除的時候,數值不會下降。還要注意的是,在發生內部 索引 操作的時候,這個值也會增加,比如說文檔更新。

還列出了索引操作耗費的時間,正在索引的文檔數量,以及刪除操作的類似統計值。
get 顯示通過 ID 獲取文檔的接口相關的統計值。包括對單個文檔的 GET 和 HEAD 請求。

search描述在活躍中的搜索(open_contexts)數量、查詢的總數量、以及自節點啓動以來在查詢上消耗的總時間。用query_time_in_millis / query_total 計算的比值,可以用來粗略的評價你的查詢有多高效。比值越大,每個查詢花費的時間越多,你應該要考慮調優了。
fetch 統計值展示了查詢處理的後一半流程(query-then-fetch裏的fetch)。如果fetch耗時比query還多,說明磁盤較慢,或者獲取了太多文檔,或者可能搜索請求設置了太大的分頁(比如, size: 10000 )。

merges 包括了 Lucene段合併相關的信息。它會告訴你目前在運行幾個合併,合併涉及的文檔數量,正在合併的段的總大小,以及在合併操作上消耗的總時間。

在你的集羣寫入壓力很大時,合併統計值非常重要。合併要消耗大量的磁盤I/O和CPU資源。如果你的索引有大量的寫入,同時又發現大量的合併數,一定要去閱讀索引性能技巧。

注意:文檔更新和刪除也會導致大量的合併數,因爲它們會產生最終需要被合併的段 碎片 。

 "filter_cache": {
           "memory_size_in_bytes": 48,
           "evictions": 0
        },
        "fielddata": {
           "memory_size_in_bytes": 0,
           "evictions": 0
        },
        "segments": {
           "count": 319,
           "memory_in_bytes": 65812120
        },
        ...
filter_cache 展示了已緩存的過濾器位集合所用的內存數量,以及過濾器被驅逐出內存的次數。過多的驅逐數可能說明你需要加大過濾器緩存的大小,或者你的過濾器不太適合緩存(比如它們因爲高基數而在大量產生,就像是緩存一個 now 時間表達式)。

不過,驅逐數是一個很難評定的指標。過濾器是在每個段的基礎上緩存的,而從一個小的段裏驅逐過濾器,代價比從一個大的段裏要廉價的多。有可能你有很大的驅逐數,但是它們都發生在小段上,也就意味着這些對查詢性能只有很小的影響。

把驅逐數指標作爲一個粗略的參考。如果你看到數字很大,檢查一下你的過濾器,確保他們都是正常緩存的。不斷驅逐着的過濾器,哪怕都發生在很小的段上,效果也比正確緩存住了的過濾器差很多。

field_data 顯示 fielddata 使用的內存,用以聚合、排序等等。這裏也有一個驅逐計數。和filter_cache不同的是,這裏的驅逐計數是很有用的:這個數應該或者至少是接近於0。因爲fielddata不是緩存,任何驅逐都消耗巨大,應該避免掉。如果你在這裏看到驅逐數,你需要重新評估你的內存情況,fielddata 限制,請求語句,或者這三者。

segments 會展示這個節點目前正在服務中的 Lucene 段的數量。 這是一個重要的數字。大多數索引會有大概 50–150 個段,哪怕它們存有 TB 級別的數十億條文檔。段數量過大表明合併出現了問題(比如,合併速度跟不上段的創建)。注意這個統計值是節點上所有索引的匯聚總數。記住這點。

memory 統計值展示了 Lucene 段自己用掉的內存大小。 這裏包括底層數據結構,比如倒排表,字典,和布隆過濾器等。太大的段數量會增加這些數據結構帶來的開銷,這個內存使用量就是一個方便用來衡量開銷的度量值。


3)os,process部分基本是系統的自描述信息,通俗易懂


4)Jvm部分
jvm 部分包括了運行 Elasticsearch 的 JVM 進程一些很關鍵的信息。 最重要的,它包括了垃圾回收的細節,這對你的 Elasticsearch 集羣的穩定性有着重大影響。

因爲垃圾回收對 Elasticsearch 是如此重要,你應該非常熟悉 node-stats API 裏的這部分內容:
"jvm": {
            "timestamp": 1408556438203,
            "uptime_in_millis": 14457,
            "mem": {
               "heap_used_in_bytes": 457252160,
               "heap_used_percent": 44,
               "heap_committed_in_bytes": 1038876672,
               "heap_max_in_bytes": 1038876672,
               "non_heap_used_in_bytes": 38680680,
               "non_heap_committed_in_bytes": 38993920,

jvm 部分首先列出一些和 heap內存使用有關的常見統計值。你可以看到有多少heap被使用了,多少被指派了(當前被分配給進程的),以及 heap被允許分配的最大值。理想情況下,heap_committed_in_bytes應該等於heap_max_in_bytes。如果指派的大小更小,JVM最終會被迫調整 heap 大小——這是一個非常昂貴的操作。如果你的數字不相等,閱讀 堆內存:大小和交換 學習如何正確的配置它。

heap_used_percent指標是值得關注的一個數字。Elasticsearch被配置爲當heap達到75%的時候開始GC。如果你的節點一直>=75%,你的節點正處於 內存壓力 狀態。這是個危險信號,不遠的未來可能就有慢 GC 要出現了。如果 heap 使用率一直 >=85%,你就麻煩了。Heap在90–95% 之間,則面臨可怕的性能風險,此時最好的情況是長達 10–30s 的 GC,最差的情況就是內存溢出(OOM)異常。

   "pools": {
      "young": {
         "used_in_bytes": 138467752,
         "max_in_bytes": 279183360,
         "peak_used_in_bytes": 279183360,
         "peak_max_in_bytes": 279183360
      },
      "survivor": {
         "used_in_bytes": 34865152,
         "max_in_bytes": 34865152,
         "peak_used_in_bytes": 34865152,
         "peak_max_in_bytes": 34865152
      },
      "old": {
         "used_in_bytes": 283919256,
         "max_in_bytes": 724828160,
         "peak_used_in_bytes": 283919256,
         "peak_max_in_bytes": 724828160
      }
   }
},
新生代,倖存代,老年代等使用情況,通常並不重要

"gc": {
   "collectors": {
      "young": {
         "collection_count": 13,
         "collection_time_in_millis": 923
      },
      "old": {
         "collection_count": 0,
         "collection_time_in_millis": 0
      }
   }
}
gc 部分顯示新生代和老生代的垃圾回收次數和累積時間。大多數時候你可以忽略掉新生代的次數:這個數字通常都很大。這是正常的。

與之相反,老生代的次數應該很小,而且 collection_time_in_millis 也應該很小。這些是累積值,所以很難給出一個閾值表示你要開始操心了(比如,一個跑了一整年的節點,即使很健康,也會有一個比較大的計數)。這就是像 Marvel 這類工具很有用的一個原因。GC 計數的 時間趨勢 是個重要的考慮因素。

GC 花費的時間也很重要。比如,在索引文檔時,一系列垃圾生成了。這是很常見的情況,每時每刻都會導致 GC。這些 GC 絕大多數時候都很快,對節點影響很小:新生代一般就花一兩毫秒,老生代花一百多毫秒。這些跟 10 秒級別的 GC 是很不一樣的。

我們的最佳建議是定期收集 GC 計數和時長(或者使用 Marvel)然後觀察 GC 頻率。你也可以開啓慢 GC 日誌記錄,在 日誌記錄 小節已經討論過。

5)線程池
Elasticsearch 在內部維護了線程池。 這些線程池相互協作完成任務,有必要的話相互間還會傳遞任務。通常來說,你不需要配置或者調優線程池,不過查看它們的統計值有時候還是有用的,可以洞察你的集羣表現如何。

 "index": {
     "threads": 1,
     "queue": 0,
     "active": 0,
     "rejected": 0,
     "largest": 1,
     "completed": 1
  }

每個線程池會列出已配置的線程數量( threads ),當前在處理任務的線程數量( active ),以及在隊列中等待處理的任務單元數量( queue )。

如果隊列中任務單元數達到了極限,新的任務單元會開始被拒絕,你會在 rejected 統計值上看到它反映出來。這通常是你的集羣在某些資源上碰到瓶頸的信號。因爲隊列滿意味着你的節點或集羣在用最高速度運行,但依然跟不上工作的蜂擁而入。


這裏的一系列的線程池,大多數你可以忽略,但是有一小部分還是值得關注的:

indexing
普通的索引請求的線程池
bulk
批量請求,和單條的索引請求不同的線程池
get
Get-by-ID 操作
search
所有的搜索和查詢請求
merging
專用於管理 Lucene 合併的線程池

5)文件系統與網絡
fs,transport,http這些都相對易懂。比較好理解,簡單說一下

transport 顯示和 傳輸地址 相關的一些基礎統計值。包括節點間的通信(通常是 9300 端口)以及任意傳輸客戶端或者節點客戶端的連接。

http 顯示 HTTP 端口(通常是 9200)的統計值。如果你看到 total_opened 數很大而且還在一直上漲,這是一個明確信號,說明你的 HTTP 客戶端裏有沒啓用 keep-alive 長連接的。


6)斷路器
跟 fielddata 斷路器(在 斷路器 介紹過)相關的統計值:
"fielddata_breaker": {
            "maximum_size_in_bytes": 623326003,
            "maximum_size": "594.4mb",
            "estimated_size_in_bytes": 0,
            "estimated_size": "0b",
            "overhead": 1.03,
            "tripped": 0
         }

這裏你可以看到斷路器的最大值(比如,一個請求申請更多的內存時會觸發斷路器)。這個部分還會讓你知道斷路器被觸發了多少次,以及當前配置的間接開銷。間接開銷用來鋪墊評估,因爲有些請求比其他請求更難評估。

主要需要關注的是 tripped 指標。如果這個數字很大或者持續上漲,這是一個信號,說明你的請求需要優化,或者你需要添加更多內存(單機上添加,或者通過添加新節點的方式)。


集羣統計
提供跟節點統計類似的信息,但是針對的是整個集羣的情況,並且更加簡潔
GET _cluster/stats


索引統計
以索引爲中心,看統計值
單個關注的索引,多個索引,全部索引
GET my_index/_stats
GET my_index,another_index/_stats
GET _all/_stats

返回的統計信息和 節點統計 的輸出很相似:search 、 fetch 、 get 、 index 、 bulk 、 segment counts 等等。

索引爲中心的統計在有些時候很有用,比如辨別或驗證集羣中的 熱門 索引,或者試圖找出某些索引比其他索引更快或者更慢的原因。

實踐中,節點爲中心的統計還是顯得更有用些。瓶頸往往是針對整個節點而言,而不是對於單個索引。因爲索引一般是分佈在多個節點上的,這導致以索引爲中心的統計值通常不是很有用,因爲它們是從不同環境的物理機器上匯聚的數據。

索引爲中心的統計作爲一個有用的工具可以保留在你的技能表裏,但是通常它不會是第一個用的上的工具。


等待中的任務
有一些任務只能由主節點去處理,比如創建一個新的索引或者在集羣中移動分片。由於一個集羣中只能有一個主節點,所以只有這一節點可以處理集羣級別的元數據變動。在 99.9999% 的時間裏,這不會有什麼問題。元數據變動的隊列基本上保持爲零。

在一些 罕見 的集羣裏,元數據變動的次數比主節點能處理的還快。這會導致等待中的操作會累積成隊列。

等待中的任務 API 會給你展示隊列中(如果有的話)等待的集羣級別的元數據變更操作:
GET _cluster/pending_tasks
無等待任務情況
{
   "tasks": []
}

有等待任務情況
{
   "tasks": [
      {
         "insert_order": 101,
         "priority": "URGENT",
         "source": "create-index [foo_9], cause [api]",
         "time_in_queue_millis": 86,
         "time_in_queue": "86ms"
      },
      {
         "insert_order": 46,
         "priority": "HIGH",
         "source": "shard-started ([foo_2][1], node[tMTocMvQQgGCkj7QDHl3OA], [P],
         s[INITIALIZING]), reason [after recovery from gateway]",
         "time_in_queue_millis": 842,
         "time_in_queue": "842ms"
      },
  ]
}

可以看到任務都被指派了優先級(比如說URGENT要比HIGH更早的處理,任務插入的次序、操作進入隊列多久,以及打算處理什麼。在上面的列表中,有一個 創建索引(create-index) 和啓動分片(shard-started) 的操作在等待。

Q:什麼時候應該擔心等待中的任務?
主節點很少會成爲集羣的瓶頸。唯一可能成爲瓶頸的是集羣狀態非常大而且更新頻繁。例如,如果你允許客戶按照他們的意願創建任意的動態字段,而且每個客戶每天都有一個獨立索引,那麼你的集羣狀態會變得非常大。集羣狀態包括 ( 但不限於 )所有索引及其類型,以及每個索引的全部字段。
所以如果你有 100000 客戶,然後每個客戶平均有1000個字段,而且數據有90天的保留期—這就有九十億個字段需要保存在集羣狀態中。不管它何時發生變更,所有的節點都需要被通知。主節點必須處理這些變動,這需要不小的CPU開銷,加上推送更新的集羣狀態到所有節點的網絡開銷。
這就是那些可以看到集羣狀態操作隊列上漲的集羣。沒有簡單的辦法可以解決這個問題,不過你有三個選擇:
    --使用一個更強大的主節點。不幸的是,這種垂直擴展只是延遲這種必然結果出現而已。
    --通過某些方式限定文檔的動態性質來限制集羣狀態的大小。
    --到達某個閾值後組建另外一個集羣。

cat API
用 Linux 的 cat 命令命名,這些 API 也就設計成像 *nix 命令行工具一樣工作了。
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章