Elasticsearch冷熱分離原理和實踐

性能與容量之間的矛盾由來已久,計算機的多級存儲體系就是其中一個經(jīng)典的例子,同樣的問題在Elasticsearch中也存在。為了保證Elasticsearch的讀寫性能,官方建議磁盤使用SSD固態(tài)硬盤。然而Elasticsearch要解決的是海量數(shù)據(jù)的存儲和檢索問題,海量的數(shù)據(jù)就意味需要大量的存儲空間,如果都使用SSD固態(tài)硬盤成本將成為一個很大的問題,這也是制約許多企業(yè)和個人使用Elasticsearch的因素之一。為了解決這個問題,Elasticsearch冷熱分離架構(gòu)應(yīng)運而生。

1. 實現(xiàn)原理

1.1 節(jié)點異構(gòu)

傳統(tǒng)的Elasticsearch集群中所有節(jié)點均采用相同的配置,然而Elasticsearch并沒有對節(jié)點的規(guī)格一致性做要求,換而言之就是每個節(jié)點可以是任意規(guī)格,當(dāng)然這樣做會導(dǎo)致集群各節(jié)點性能不一致,影響集群穩(wěn)定性。但是如果有規(guī)則的將集群的節(jié)點分成不同類型,部分是高性能的節(jié)點用于存儲熱點數(shù)據(jù),部分是性能相對差些的大容量節(jié)點用于存儲冷數(shù)據(jù),卻可以一方面保證熱數(shù)據(jù)的性能,另一方面保證冷數(shù)據(jù)的存儲,降低存儲成本,這也是Elasticsearch冷熱分離架構(gòu)的基本思想,如下圖為一個3熱節(jié)點,2冷節(jié)點的冷熱分離Elasticsearch集群:

image


其中熱節(jié)點為16核64GB 1TB SSD盤,用于滿足對熱數(shù)據(jù)對讀寫性能的要求,冷節(jié)點為8C32GB 5TB HDD在保證一定讀寫性能的基礎(chǔ)之上提供了成本較低的大存儲HDD盤來滿足冷節(jié)點對數(shù)據(jù)存儲的需求。

1.2 數(shù)據(jù)分布

集群節(jié)點異構(gòu)后接著要考慮的是數(shù)據(jù)分布問題,即用戶如何對冷熱數(shù)據(jù)進行標(biāo)識,并將冷數(shù)據(jù)移動到冷節(jié)點,熱數(shù)據(jù)移動到熱節(jié)點。

節(jié)點指定冷熱屬性

僅僅將不同的節(jié)點設(shè)置為不同的規(guī)格還不夠,為了能明確區(qū)分出哪些節(jié)點是熱節(jié)點,哪些節(jié)點是冷節(jié)點,需要為對應(yīng)節(jié)點打標(biāo)簽

Elasticsearch支持給節(jié)點打標(biāo)簽,具體方式是在elasticsearch.yml文件中增加

node.attr.{attribute}: {value}

配置。其中attribute為用戶自定義的任意標(biāo)簽名,value為該節(jié)點對應(yīng)的該標(biāo)簽的值,例如對于冷熱分離,可以使用如下設(shè)置

node.attr.temperature: hot //熱節(jié)點
node.attr.temperature: warm //冷節(jié)點

ps:中文通常叫冷熱,英文叫hot/warm

索引指定冷熱屬性

節(jié)點有了冷熱屬性后,接下來就是指定數(shù)據(jù)的冷熱屬性,來設(shè)置和調(diào)整數(shù)據(jù)分布。冷熱分離方案中數(shù)據(jù)冷熱分布的基本單位是索引,即指定某個索引為熱索引,另一個索引為冷索引。通過索引的分布來實現(xiàn)控制數(shù)據(jù)分布的目的。
Elasticsearch提供了index shard filtering功能(2.x開始),該功能在索引配置中提供了如下幾個配置

index.routing.allocation.include.{attribute}
Assign the index to a node whose {attribute} has at least one of the comma-separated values.

index.routing.allocation.require.{attribute}
Assign the index to a node whose {attribute} has all of the comma-separated values.

index.routing.allocation.exclude.{attribute}
Assign the index to a node whose {attribute} has none of the comma-separated values.

用戶可以在創(chuàng)建索引,或后續(xù)的任意時刻設(shè)置這些配置來控制索引在不同標(biāo)簽節(jié)點上的分配動作。

index.routing.allocation.include.{attribute}表示索引可以分配在包含多個值中其中一個的節(jié)點上。

index.routing.allocation.require.{attribute}表示索引要分配在包含索引指定值的節(jié)點上(通常一般設(shè)置一個值)。

index.routing.allocation.exclude.{attribute}表示索引只能分配在不包含所有指定值的節(jié)點上。

數(shù)據(jù)分布控制

Elasticsearch的索引分片分配由ShardAllocator決定,ShardAllocator通過在索引分片創(chuàng)建或rebalance時對每個節(jié)點調(diào)用一系列AllocationDecider來決定是否將節(jié)點分配到指定節(jié)點上,其中一個AllocationDecider是FilterAllocationDecider,該decider用于應(yīng)用集群,節(jié)點的一些基于attr的分配規(guī)則,涉及到節(jié)點級別配置的核心代碼如下

private Decision shouldIndexFilter(IndexMetaData indexMd, RoutingNode node, RoutingAllocation allocation) {
    if (indexMd.requireFilters() != null) {
        if (indexMd.requireFilters().match(node.node()) == false) {
            return allocation.decision(Decision.NO, NAME, "node does not match index setting [%s] filters [%s]",
                IndexMetaData.INDEX_ROUTING_REQUIRE_GROUP_PREFIX, indexMd.requireFilters());
        }
    }
    if (indexMd.includeFilters() != null) {
        if (indexMd.includeFilters().match(node.node()) == false) {
            return allocation.decision(Decision.NO, NAME, "node does not match index setting [%s] filters [%s]",
                IndexMetaData.INDEX_ROUTING_INCLUDE_GROUP_PREFIX, indexMd.includeFilters());
        }
    }
    if (indexMd.excludeFilters() != null) {
        if (indexMd.excludeFilters().match(node.node())) {
            return allocation.decision(Decision.NO, NAME, "node matches index setting [%s] filters [%s]",
                IndexMetaData.INDEX_ROUTING_EXCLUDE_GROUP_SETTING.getKey(), indexMd.excludeFilters());
        }
    }
    return null;
}

2 冷熱集群搭建及使用實踐

2.1 集群規(guī)格選型

根據(jù)業(yè)務(wù)數(shù)據(jù)量及讀寫性能要求選擇合適的冷熱節(jié)點規(guī)格

  • 存儲量計算:根據(jù)冷熱數(shù)據(jù)各自數(shù)據(jù)量及要求保留時間,計算出冷熱數(shù)據(jù)源數(shù)據(jù)量,然后使用如下公式計算出冷熱節(jié)點各自的磁盤需求量
實際空間 = 源數(shù)據(jù) * (1 + 副本數(shù)量) * (1 + 數(shù)據(jù)膨脹) / (1 - 內(nèi)部任務(wù)開銷) / (1 - 操作系統(tǒng)預(yù)留)
        ≈ 源數(shù)據(jù) * (1 + 副本數(shù)量) * 1.45
ES建議存儲容量 = 源數(shù)據(jù) * (1 + 副本數(shù)量) * 1.45 * (1 + 預(yù)留空間)
        ≈ 源數(shù)據(jù) * (1 + 副本數(shù)量) * 2.2
- 副本數(shù)量:副本有利于增加數(shù)據(jù)的可靠性,但同時會增加存儲成本。默認和建議的副本數(shù)量為1,對于部分可以承受異常情況導(dǎo)致數(shù)據(jù)丟失的場景,可考慮設(shè)置副本數(shù)量為0。
- 數(shù)據(jù)膨脹:除原始數(shù)據(jù)外,ES 需要存儲索引、列存數(shù)據(jù)等,在應(yīng)用編碼壓縮等技術(shù)后,一般膨脹10%。
- 內(nèi)部任務(wù)開銷:ES 占用約20%的磁盤空間,用于 segment 合并、ES Translog、日志等。
- 操作系統(tǒng)預(yù)留:Linux 操作系統(tǒng)默認為 root 用戶預(yù)留5%的磁盤空間,用于關(guān)鍵流程處理、系統(tǒng)恢復(fù)、防止磁盤碎片化問題等。
- 預(yù)留空間:為保證集群的正常運行建議預(yù)留50%的存儲空間
  • 計算資源預(yù)估:

    ES 的計算資源主要消耗在寫入和查詢過程,而不同業(yè)務(wù)場景在寫入和查詢方面的復(fù)雜度不同、比重不同,導(dǎo)致計算資源相比存儲資源較難評估
    • 日志場景:日志屬于典型的寫多讀少類場景,計算資源主要消耗在寫入過程中。我們在日志場景的經(jīng)驗是:2核8GB內(nèi)存的資源最大可支持0.5w/s的寫入能力,但注意不同業(yè)務(wù)場景可能有偏差。由于實例性能基本隨計算資源總量呈線性擴容,您可以按實例資源總量估算寫入能力。例如6核24GB內(nèi)存的資源可支持1.5w/s的寫入能力,40核160GB內(nèi)存的資源可支持10w/s的寫入能力。
    • Metric 及 APM 等結(jié)構(gòu)化數(shù)據(jù)場景:這也是寫多讀少類場景,但相比日志場景計算資源消耗較小,2核8GB內(nèi)存的資源一般可支持1w/s的寫入能力,您可參照日志場景線性擴展的方式,評估不同規(guī)格實例的實際寫入能力。
    • 站內(nèi)搜索及應(yīng)用搜索等搜索場景:此類為讀多寫少類場景,計算資源主要消耗在查詢過程,由于查詢復(fù)雜度在不同使用場景差別非常大,計算資源也最難評估,建議您結(jié)合存儲資源初步選擇計算資源,然后在測試過程中驗證、調(diào)整。

2.2 搭建集群

  • 自建

按照選定冷熱節(jié)點規(guī)格部署服務(wù)器,搭建集群,熱節(jié)點使用SSD盤,冷節(jié)點使用HDD盤,對熱節(jié)點elasticsearcy.yml增加如下配置

node.attr.temperature: hot 

對冷節(jié)點增加如下配置

node.attr.temperature: warm

啟動集群,冷熱分離的Elasticsearch集群即搭建完成

  • 購買云ES服務(wù)

騰訊云預(yù)計于12月中旬上線冷熱分離集群,用戶只需要在創(chuàng)建頁面上根據(jù)需要即可分鐘級拉起一個冷熱分離架構(gòu)的ES集群,方便快速,擴展性好,運維成本低

  • 驗證
    使用如下命令可以驗證節(jié)點冷熱屬性
GET _cat/nodeattrs?v&h=node,attr,value&s=attr:desc
node        attr        value
node1   temperature     hot
node2   temperature     hot
node3   temperature     warm
node4   temperature     hot
node5   temperature     warm
...

可以看到該集群為三熱二冷的冷熱分離集群(當(dāng)然要注意如果其中有專用主節(jié)點或?qū)S脜f(xié)調(diào)節(jié)點這類無法分配shard的節(jié)點,即使設(shè)置了冷熱屬性也不會有分片可以分配到其上)

3. 為索引設(shè)置冷熱屬性

業(yè)務(wù)方可以根據(jù)實際情況決定索引的冷熱屬性

  • 對于熱數(shù)據(jù),索引設(shè)置如下
PUT hot_data_index/_settings
{
  "index.routing.allocation.require.temperature": "hot"
}
  • 對于冷數(shù)據(jù),索引設(shè)置
PUT hot_data_index/_settings
{
  "index.routing.allocation.require.temperature": "warm"
}
  • 驗證

    創(chuàng)建索引
PUT hot_warm_test_index
{
  "settings": {
    "number_of_replicas": 1,
    "number_of_shards": 3
  }
}

查看分片分配,可以看到分片均勻分配在五個節(jié)點上

GET _cat/shards/hot_warm_test_index?v&h=index,shard,prirep,node&s=node
index          shard prirep node
hot_data_index 1     p      node1
hot_data_index 0     r      node1
hot_data_index 2     r      node2
hot_data_index 2     p      node3
hot_data_index 1     r      node4
hot_data_index 0     p      node5

設(shè)置索引為熱索引

PUT hot_warm_test_index/_settings
{
  "index.routing.allocation.require.temperature": "hot"
}

查看分片分配,發(fā)現(xiàn)分片均分配在熱節(jié)點上

GET _cat/shards/hot_warm_test_index?v&h=index,shard,prirep,node&s=node
index          shard prirep node
hot_data_index 1     p      node1
hot_data_index 0     r      node1
hot_data_index 0     p      node2
hot_data_index 2     r      node2
hot_data_index 2     p      node4
hot_data_index 1     r      node4

設(shè)置索引為冷索引

PUT hot_warm_test_index/_settings
{
  "index.routing.allocation.require.temperature": "warm"
}

查看分片分配,發(fā)現(xiàn)分片均分配到冷節(jié)點上

GET _cat/shards/hot_warm_test_index?v&h=index,shard,prirep,node&s=node
index          shard prirep node
hot_data_index 1     p      node3
hot_data_index 0     r      node3
hot_data_index 2     r      node3
hot_data_index 0     p      node5
hot_data_index 2     p      node5
hot_data_index 1     r      node5

4. 索引生命周期管理

從ES6.6開始,Elasticsearch提供索引生命周期管理功能,索引生命周期管理可以通過API或者kibana界面配置,詳情參考[index-lifecycle-management], 本文僅通過kibana界面演示如何使用索引生命周期管理結(jié)合冷熱分離架構(gòu)實現(xiàn)索引數(shù)據(jù)的動態(tài)管理。

kibana中的索引生命周期管理位置如下圖(版本6.8.2):

image

點擊創(chuàng)建create policy,進入配置界面,可以看到索引的生命周期被分為:Hot phrase,Warm phase, Cold phase,Delete phrase四個階段

  • Hot phrase: 該階段可以根據(jù)索引的文檔數(shù),大小,時長決定是否調(diào)用rollover API來滾動索引,詳情可以參考[indices-rollover-index],因與本文關(guān)系不大不再詳細贅述。
  • Warm phrase: 當(dāng)一個索引在Hot phrase被roll over后便會進入Warm phrase,進入該階段的索引會被設(shè)置為read-only, 用戶可以為這個索引設(shè)置要使用的attribute, 如對于冷熱分離策略,這里可以選擇temperature: warm屬性。另外還可以對索引進行forceMerge, shrink等操作,這兩個操作具體可以參考官方文檔。

    image
  • Cold phrase: 可以設(shè)置當(dāng)索引rollover一段時間后進入cold階段,這個階段也可以設(shè)置一個屬性。從冷熱分離架構(gòu)可以看出冷熱屬性是具備擴展性的,不僅可以指定hot, warm, 也可以擴展增加hot, warm, cold, freeze等多個冷熱屬性。如果想使用三層的冷熱分離的話這里可以指定為temperature: cold, 此處還支持對索引的freeze操作,詳情參考官方文檔。
  • Delete phrase: 可以設(shè)置索引rollover一段時間后進入delete階段,進入該階段的索引會自動被刪除。

    image

冷熱分離架構(gòu)是Elasticsearch的經(jīng)典架構(gòu)之一,使用該架構(gòu)用戶可以在保證熱數(shù)據(jù)良好讀寫性能的同時,仍可以存儲海量的數(shù)據(jù),極大地豐富了ES的應(yīng)用場景,解決了用戶的成本問題。再結(jié)合ES在6.6推出的索引生命周期管理,使得ES集群在使用性和自動化方面表現(xiàn)出色,真正地解決了用戶在性能,存儲成本,自動化數(shù)據(jù)管理等方面的問題。

歡迎關(guān)注公眾號Elastic慕容,和我一起進入Elastic的奇妙世界吧

image

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容