ElasticSearch學習總結(四):分佈式特性

本文主要對Elasticsearch的分佈式相關特性進行總結

1. 分片與副本

1.1 分片&副本

索引分片機制用來存儲超過單個節點存儲容量的數據,分片副本用來應對不斷攀升的吞吐量以及確保數據的安全性。

當一個節點的主分片丟失,ElasticSearch可以把任意一個可用的分片副本推舉爲主分片。在默認情況下,ElasticSearch會創建一個分片副本。然而分片副本的數量可以通過設置相關的API隨時更新,這一點與分片數是不同的。

分片副本的動態更新功能使得創建應用程序時十分方便,查詢吞吐量可以隨着分片副本數量的增加而增長,與此同時,使用分片副本還可以處理增加查詢的發並量。

1.2 合適的分片與副本數

上節可以看出分片主要用來解決單節點存儲容量的問題,多副本主要用來解決查詢性能以及高可用的問題,Elasticsearch默認的情況下會爲每個索引創建5個分片1個副本,該配置很多場景下往往不能滿足需求,分片與副本的數量設置情況可參考下列方式

  • 如果數據集的大小有限制而且嚴格定義好的,可以只使用一個分片,一個副本
  • 除了上述情況,可以採用公式 “所需最大節點數=分片數*(副本數+1)”的計算方式,例如你計劃用10個分片和2個分片副本,那麼最大的節點數是30

1.3 分片&副本分配過度

分片分配過度可能會產生以下影響:
1. 增加分發搜索命令到每個分片以及分片結果合併的開銷

副本分配過度可能會產生以下影響:
1. 額外的存儲空間開銷
2. 從主分片複製數據到分片副本時的開銷

1.4 調整集羣分片分配

主節點的主要功能之一是決定將哪些分片分配給哪些節點,以及何時移動節點之間的分片以集羣的數據平衡。

目前Elasticsearch有多種策略可以控制分片的分配:

  • 羣集級別的分片分配策略:分片分配是將分片分配給節點的過程。這可能發生在初始恢復,副本分配,rebalancing或添加/刪除節點時。

  • 基於磁盤的的分片分配策略:Elasticsearch可以基於磁盤的使用情況配置分配策略來決定是將新分片分配給該節點還是主動將分片從該節點遷出.

  • 基於機架/區域感知的分片分配策略:和大多數分佈式集羣的分配策略一樣,ES也支持基於機架/區域感知的分片分配策略,該策略針對大面積基礎設施出現問題時的保證集羣高可用的策略。

  • 基於過濾的分片分配策略:可以在索引或是集羣級別來配置分片的分配,例如那些節點可以分配集羣,那些節點不可以分配某個索引等。

上述策略除了可以通過配置文件配置外,還可以通過API在運行時進行配置。詳細配置可參考:https://www.elastic.co/guide/en/elasticsearch/reference/5.2/modules-cluster.html

2. 路由

2.1 路由和分片

在分佈式環境下一個索引可以分多個shard,在索引數據的時候,索引數據採用以下算法寫到對應的shard上:

shard_num = hash(_routing) % num_primary_shards

默認情況下,Elasticsearch使用文檔ID值作爲依據將其哈希到相應的主分片上,這種算法基本上會保持所有數據在所有分片上的一個平均分佈,而不會產生數據熱點。

而我們爲什麼會需要自定義的Routing模式呢?首先默認的Routing模式在很多情況下都是能滿足我們的需求的——平均的數據分佈、對我們來說是透明的、多數時候性能也不是問題。但是在我們更深入地理解我們的數據的特徵之後,使用自定義的Routing模式可能會給我們帶來更好的性能。

假設你有一個100個分片的索引。當一個請求在集羣上執行時會發生什麼呢?

  1. 這個搜索的請求會被髮送到一個節點
  2. 接收到這個請求的節點,將這個查詢廣播到這個索引的每個分片上(可能是主分片,也可能是複製分片)
  3. 每個分片執行這個搜索查詢並返回結果
  4. 結果在通道節點上合併、排序並返回給用戶

因爲默認情況下,Elasticsearch使用文檔的ID(類似於關係數據庫中的自增ID,當然,如果不指定ID的話,Elasticsearch使用的是隨機值)將文檔平均的分佈於所有的分片上,這導致了Elasticsearch不能確定文檔的位置,所以它必須將這個請求廣播到所有的100個分片上去執行。這同時也解釋了爲什麼主分片的數量在索引創建的時候是固定下來的,並且永遠不能改變。因爲如果分片的數量改變了,所有先前的路由值就會變成非法了,文檔相當於丟失了。

而自定義的Routing模式,可以使我們的查詢更具目的性。我們不必盲目地去廣播查詢請求,取而代之的是:我們要告訴Elasticsearch我們的數據在哪個分片上。

2.2 通過路由控制索引數據

所有的文檔API(get,index,delete,update和mget)都能接收一個routing參數,可以用來形成個性化文檔分片映射。一個個性化的routing值可以確保相關的文檔存儲到同樣的分片上——比如,所有屬於同一個用戶的文檔。

指定方法1:

curl -XPOST 'http://localhost:9200/store/order?routing=user123' -d '
{
    "productName": "sample",
    "customerID": "user123"
}'

指定方法2:

curl -XPUT 'http://localhost:9200/store/order/_mapping' -d '
{
    "order": {
        "_routing": {
            "required": true,
            "path": "customerID"
        }
    }
}'

2.3 通過路由控制檢索數據

利用路由機制的查詢也是非常簡單明瞭的,只需要在查詢中指定對應的路由值即可:

curl -XGET 'http://localhost:9200/store/order/_search?routing=user123' -d '
{
    "query": {
        "filtered": {
            "query": {
                "match_all": {}
            },
            "filter": {
                "term": {
                    "userID": "user123"
                }
            }
        }
    }
}'

通過指定的路由值,我們就可以直接定位到user123的文檔所在的分片,而不用一股腦的向索引的所有節點都發送請求。這樣的話,會大大減少系統資源的浪費。

2.4 多個路由聯合

也可以同時指定多個路由值,方法也是顯而易見的,只需要在查詢參數中指定多個路由值即可:

curl -XGET 'http://localhost:9200/forum/posts/?routing=Admin,Moderator' -d '{}'

3. 查詢執行偏好

在Elasticsearch中,會將相關操作隨機分發到分片或者分片副本上。如果往集羣中發送大量的查詢命令,最終每個分片和分片副本上執行的查詢命令數量會大致相同,但是可以通過preference參數來配置查詢的執行地點。

爲了便於說明,藉助下表對參數進行說明:

節點名稱 節點編號 包含索引 分片與副本分配
node1 6GVd-ktcS2um4uM4AAJQhQ masting primary shard 0
node2 iw76-abdcdefdsdsdsdfsd masting primary shard 1
node3 wJq0kPSHTHCovjuCsVK0-A masting replica shard 1,replica shard 0
  • _primary: 使用該屬性值,發送到集羣的相關操作請求只會在主分片上執行。

  • _primary_first:該屬性值與_primary屬性值導致相似的集羣行爲,但是具有容錯機制。如果發送查詢命令到mastering索引時附帶了值爲_primary_first的preference參數,該命令將在名稱爲node1和node2的節點上執行,但是如果有一個(或者更多)的主分片失效,查詢命令將轉到其它的分片上執行,在本例中會轉到node3上執行。

  • _local: ElasticSearch會優先在本地的節點上執行相關操作。比如,如果我們向node3發送附帶一條preference參數值爲_local的查詢命令,最終該查詢命令會在node3上執行。但是,如果我們把相同的命令發送到node2節點,那麼最終該命令不僅會在編號爲1的分片(節點爲node2)上執行,同時也會分發到node1或者node3上執行,這兩個節點上有編號爲0的分片。該屬性值在減小網絡傳輸時間上特別有用。只要用到了_local preference參數值,我們就能確保查詢命令會儘可能地在本地的節點上執行。

  • _only_node:wJq0kPSHTHCovjuCsVK0-A:這類的操作只會在指定標識(本例中是wJq0kPSHTHCovjuCsVK0-A)的節點上執行。所以在本例中,查詢命令只會在node3節點上的兩個分片副本上執行。需要注意的是,如果指定節點中的分片不足以覆蓋到整個索引的數據,那麼命令就只會在指定節點的相關分片上執行。比如,如果我們將查詢命令的preference參數值設置爲 _only_node:6GVd-ktcS2um4uM4AAJQhQ,我們就只會獲取到一個分片的數據。這個屬性值在如下的應用場景中非常有用:用戶已經知道某個節點所在的服務器處理能力強大,希望一些特定的查詢命令只在該節點上執行。

  • _prefer_node:wJq0kPSHTHCovjuCsVK0-A:這個選項用來把preference參數值設置成_prefer_node:,後面附帶的值是一個節點Id(本例中就是wJq0kPSHTHCovjuCsVK0-A) ,這會導致ElasticSearch優先選擇指定的節點來執行查詢命令,但是如果該節點上缺少索引數據的一些分片,那麼查詢命令會發到含有欠缺分片的節點上。這與_only_node選項是類似的,_prefer_node也可以用來選擇特定的節點,但是具備容錯機制。

  • _shards:0,1:這個preference值用來指定相關操作執行的某類分片(在本例中就是所有的分片,因爲整個mastering索引只有id爲0和1的分片)。這是唯一的一個可以結合其它屬性使用的preference值。比如,如果希望命令只執行在本地節點的id爲0或者1的分片上,我們可以把0,1兩個值和_local值用“;”連接起來,最終得到的preference參數值就是這樣了:0,1:_local。允許用戶發出的命令只在某個分片上執行這一特性用於診斷集羣問題是非常有幫助的。

  • 自定義字符串值:這個自定義值會確保附帶相同custom值的查詢命令會在同樣的分片上執行。比如,如果我們的查詢命令附帶preference參數值爲mastering_Elasticsearch,那麼命令會在node1和node2的主分片上執行。如果我們又發送了另一個附帶同樣preference參數值的查詢命令,該命令也只會在node1和node2的分片上執行。該功能用於應對以下應用場景:假如集羣中的各個節點刷新速率不一樣,我們不希望用戶在重複同一個命令時看到不同的結果,就應該使用該功能。

4. 別名

別名可以理解爲一個虛擬的索引,這個虛擬索引對真在存在的索引進行一些特殊包裝,對於使用者而言可以像使用正常索引那樣來使用別名。大致可以完成如下功能
1. 用來將某個路由值與某個索引綁定
2. 一個別名可以對應多個真實索引
3. 隱藏索引配置的細節

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