百億級(jí)實(shí)時(shí)查詢優(yōu)化實(shí)戰(zhàn),讓你的Elasticsearch飛起來(lái)!-創(chuàng)新互聯(lián)

最近的一個(gè)項(xiàng)目是風(fēng)控過(guò)程數(shù)據(jù)實(shí)時(shí)統(tǒng)計(jì)分析和聚合的一個(gè) OLAP 分析監(jiān)控平臺(tái),日流量峰值在 10 到 12 億上下,每年數(shù)據(jù)約 4000 億條,占用空間大概 200T。

站在用戶的角度思考問(wèn)題,與客戶深入溝通,找到恭城網(wǎng)站設(shè)計(jì)與恭城網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗(yàn),讓設(shè)計(jì)與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個(gè)性化、用戶體驗(yàn)好的作品,建站類型包括:成都做網(wǎng)站、網(wǎng)站設(shè)計(jì)、外貿(mào)營(yíng)銷網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣、域名注冊(cè)、虛擬主機(jī)、企業(yè)郵箱。業(yè)務(wù)覆蓋恭城地區(qū)。

面對(duì)這樣一個(gè)數(shù)據(jù)量級(jí)的需求,我們的數(shù)據(jù)如何存儲(chǔ)和實(shí)現(xiàn)實(shí)時(shí)查詢將是一個(gè)嚴(yán)峻的挑戰(zhàn)。

經(jīng)過(guò)對(duì) Elasticsearch 多方調(diào)研和超過(guò)幾百億條數(shù)據(jù)的插入和聚合查詢的驗(yàn)證之后,我們總結(jié)出以下幾種能夠有效提升性能和解決這一問(wèn)題的方案:

  1. 集群規(guī)劃
  2. 存儲(chǔ)策略
  3. 索引拆分
  4. 壓縮
  5. 冷熱分區(qū)等

本文所使用的 Elasticsearch 版本為 5.3.3。

百億級(jí)實(shí)時(shí)查詢優(yōu)化實(shí)戰(zhàn),讓你的Elasticsearch飛起來(lái)!

什么是時(shí)序索引?其主要特點(diǎn)體現(xiàn)在如下兩個(gè)方面:

存,以時(shí)間為軸,數(shù)據(jù)只有增加,沒(méi)有變更,并且必須包含 timestamp(日期時(shí)間,名稱隨意)字段。

其作用和意義要大于數(shù)據(jù)的 id 字段,常見(jiàn)的數(shù)據(jù)比如我們通常要記錄的操作日志、用戶行為日志、或股市行情數(shù)據(jù)、服務(wù)器 CPU、內(nèi)存、網(wǎng)絡(luò)的使用率等。

取,一定是以時(shí)間范圍為第一過(guò)濾條件,然后是其他查詢條件,比如近一天、一周、本月等等,然后在這個(gè)范圍內(nèi)進(jìn)行二次過(guò)濾。

比如性別或地域等,查詢結(jié)果中比較關(guān)注的是每條數(shù)據(jù)和 timestamp 字段具體發(fā)生的時(shí)間點(diǎn),而非 id。

此類數(shù)據(jù)一般用于 OLAP、監(jiān)控分析等場(chǎng)景。

一、集群部署規(guī)劃

百億級(jí)實(shí)時(shí)查詢優(yōu)化實(shí)戰(zhàn),讓你的Elasticsearch飛起來(lái)!

我們都知道在 Elasticsearch(下稱 ES)集群中有兩個(gè)主要角色:Master Node 和 Data Node,其他如 Tribe Node 等節(jié)點(diǎn)可根據(jù)業(yè)務(wù)需要另行設(shè)立。

為了讓集群有更好的性能表現(xiàn),我們應(yīng)該對(duì)這兩個(gè)角色有一個(gè)更好的規(guī)劃,在 Nodes 之間做讀取分離,保證集群的穩(wěn)定性和快速響應(yīng),在大規(guī)模的數(shù)據(jù)存儲(chǔ)和查詢的壓力之下能夠坦然面對(duì),各自愉快的協(xié)作。

1、Master Nodes

Master Node,整個(gè)集群的管理者,負(fù)有對(duì) index 的管理、shards 的分配,以及整個(gè)集群拓?fù)湫畔⒌墓芾淼裙δ堋?/p>

眾所周知,Master Node 可以通過(guò) Data Node 兼任,但是,如果對(duì)群集規(guī)模和穩(wěn)定要求很高的話,就要職責(zé)分離,Master Node 推薦獨(dú)立,它的狀態(tài)關(guān)乎整個(gè)集群的存活。

Master 的配置:

node.master: true

        node.data: false

        node.ingest: false

這樣 Master 不參與 I、O,從數(shù)據(jù)的搜索和索引操作中解脫出來(lái),專門負(fù)責(zé)集群的管理工作,因此 Master Node 的節(jié)點(diǎn)配置可以相對(duì)低一些。

另外防止 ES 集群 split brain(腦裂),合理配置 discovery.zen.minimum_master_nodes 參數(shù),官方推薦 master-eligible nodes / 2 + 1 向下取整的個(gè)數(shù)。

這個(gè)參數(shù)決定選舉 Master 的 Node 個(gè)數(shù),太小容易發(fā)生“腦裂”,可能會(huì)出現(xiàn)多個(gè) Master,太大 Master 將無(wú)法選舉。

2、Data Nodes

Data Node 是數(shù)據(jù)的承載者,對(duì)索引的數(shù)據(jù)存儲(chǔ)、查詢、聚合等操作提供支持。

這些操作嚴(yán)重消耗系統(tǒng)的 CPU、內(nèi)存、IO 等資源,因此,應(yīng)該把最好的資源分配給 Data Node,因?yàn)樗鼈兪钦嬲衫刍畹慕巧?,同?Data Node 也不兼任 Master 的功能。

Data 的配置:

node.master: false

        node.data: true

        node.ingest: false
3、Coordinating Only Nodes

百億級(jí)實(shí)時(shí)查詢優(yōu)化實(shí)戰(zhàn),讓你的Elasticsearch飛起來(lái)!

ES 本身是一個(gè)分布式的計(jì)算集群,每個(gè) Node 都可以響應(yīng)用戶的請(qǐng)求,包括 Master Node、Data Node,它們都有完整的 Cluster State 信息。

正如我們知道的一樣,在某個(gè) Node 收到用戶請(qǐng)求的時(shí)候,會(huì)將請(qǐng)求轉(zhuǎn)發(fā)到集群中所有索引相關(guān)的 Node 上,之后將每個(gè) Node 的計(jì)算結(jié)果合并后返回給請(qǐng)求方。

我們暫且將這個(gè) Node 稱為查詢節(jié)點(diǎn),整個(gè)過(guò)程跟分布式數(shù)據(jù)庫(kù)原理類似。那問(wèn)題來(lái)了,這個(gè)查詢節(jié)點(diǎn)如果在并發(fā)和數(shù)據(jù)量比較大的情況下,由于數(shù)據(jù)的聚合可能會(huì)讓內(nèi)存和網(wǎng)絡(luò)出現(xiàn)瓶頸。

因此,在職責(zé)分離指導(dǎo)思想的前提下,這些操作我們也應(yīng)該從這些角色中剝離出來(lái),官方稱它是 Coordinating Nodes,只負(fù)責(zé)路由用戶的請(qǐng)求,包括讀、寫等操作,對(duì)內(nèi)存、網(wǎng)絡(luò)和 CPU 要求比較高。

本質(zhì)上,Coordinating Only Nodes 可以籠統(tǒng)的理解為是一個(gè)負(fù)載均衡器,或者反向代理,只負(fù)責(zé)讀,本身不寫數(shù)據(jù)。

它的配置是:

 ? node.master: false

? ? ? ? node.data: false

? ? ? ? node.ingest: false

? ? ? ? search.remote.connect: false

增加 Coordinating Nodes 的數(shù)量可以提高 API 請(qǐng)求響應(yīng)的性能,我們也可以針對(duì)不同量級(jí)的 Index 分配獨(dú)立的 Coordinating Nodes 來(lái)滿足請(qǐng)求性能。

那是不是越多越好呢?在一定范圍內(nèi)是肯定的,但凡事有個(gè)度,過(guò)了負(fù)作用就會(huì)突顯,太多的話會(huì)給集群增加負(fù)擔(dān)。

在做 Master 選舉的時(shí)候會(huì)先確保所有 Node 的 Cluster State 是一致的,同步的時(shí)候會(huì)等待每個(gè) Node 的 Acknowledgement 確認(rèn),所以適量分配可以讓集群暢快的工作。

search.remote.connect 是禁用跨集群查詢,防止在進(jìn)行集群之間查詢時(shí)發(fā)生二次路由:

二、Routing

類似于分布式數(shù)據(jù)庫(kù)中的分片原則,將符合規(guī)則的數(shù)據(jù)存儲(chǔ)到同一分片。ES 通過(guò)哈希算法來(lái)決定數(shù)據(jù)存儲(chǔ)于哪個(gè) Shard:

shard_num = hash(_routing) % num_primary_shards

其中 hash(_routing) 得出一個(gè)數(shù)字,然后除以主 Shards 的數(shù)量得到一個(gè)余數(shù),余數(shù)的范圍是 0 到 number_of_primary_shards - 1,這個(gè)數(shù)字就是文檔所在的 Shard。

Routing 默認(rèn)是 id 值,當(dāng)然可以自定義,合理指定 Routing 能夠大幅提升查詢效率,Routing 支持 GET、Delete、Update、Post、Put 等操作。

如:

PUT my_index/my_type/1?routing=user1

{

"title": "This is a document"

}

GET my_index/my_type/1?routing=user1

不指定 Routing 的查詢過(guò)程:

百億級(jí)實(shí)時(shí)查詢優(yōu)化實(shí)戰(zhàn),讓你的Elasticsearch飛起來(lái)!

簡(jiǎn)單的來(lái)說(shuō),一個(gè)查詢請(qǐng)求過(guò)來(lái)以后會(huì)查詢每個(gè) Shard,然后做結(jié)果聚合,總的時(shí)間大概就是所有 Shard 查詢所消耗的時(shí)間之和。

指定 Routing 以后:

百億級(jí)實(shí)時(shí)查詢優(yōu)化實(shí)戰(zhàn),讓你的Elasticsearch飛起來(lái)!

會(huì)根據(jù) Routing 查詢特定的一個(gè)或多個(gè) Shard,這樣就大大減少了查詢時(shí)間,提高了查詢效率。

當(dāng)然,如何設(shè)置 Routing 是一個(gè)難點(diǎn),需要一點(diǎn)技巧,要根據(jù)業(yè)務(wù)特點(diǎn)合理組合 Routing 的值,來(lái)劃分 Shard 的存儲(chǔ),最終保持?jǐn)?shù)據(jù)量相對(duì)均衡。

可以組合幾個(gè)維度做為 Routing ,有點(diǎn)類似于 Hbase Key,例如不同的業(yè)務(wù)線加不同的類別,不同的城市和不同的類型等等,如:

 ? _search?routing=beijing:按城市。

? ? ? ? _search?routing=beijing_user123:按城市和用戶。

? ? ? ? _search?routing=beijing_android,shanghai_android:按城市和手機(jī)類型等。

數(shù)據(jù)不均衡?假如你的業(yè)務(wù)在北京、上海的數(shù)據(jù)遠(yuǎn)遠(yuǎn)大于其他二三線城市的數(shù)據(jù)。

再例如我們的業(yè)務(wù)場(chǎng)景,A 業(yè)務(wù)線的數(shù)據(jù)量級(jí)遠(yuǎn)遠(yuǎn)大于 B 業(yè)務(wù)線,有時(shí)候很難通過(guò) Routing 指定一個(gè)值保證數(shù)據(jù)在所有 Shards 上均勻分布,會(huì)讓部分 Shard 變的越來(lái)越大,影響查詢性能,怎么辦?

一種解決辦法是單獨(dú)為這些數(shù)據(jù)量大的渠道創(chuàng)建獨(dú)立的 Index

這樣可以根據(jù)需要在不同 Index 之間查詢,然而每個(gè) Index 中 Shards 的數(shù)據(jù)可以做到相對(duì)均衡。

另一種辦法是指定 Index 參數(shù) index.routing_partition_size,來(lái)解決最終可能產(chǎn)生群集不均衡的問(wèn)題,指定這個(gè)參數(shù)后新的算法如下:

shard_num = (hash(_routing) + hash(_id) % routing_partition_size) % num_primary_shards

index.routing_partition_size 應(yīng)具有大于 1 且小于 index.number_of_shards 的值。

最終數(shù)據(jù)會(huì)在 routing_partition_size 幾個(gè) Shard 上均勻存儲(chǔ),是哪個(gè) Shard 取決于 hash(_id) % routing_partition_size 的計(jì)算結(jié)果。

指定參數(shù) index.routing_partition_size 后,索引中的 Mappings 必須指定 _routing 為 "required": true,另外 Mappings 不支持 parent-child 父子關(guān)系。

很多情況下,指定 Routing 后會(huì)大幅提升查詢性能,畢竟查詢的 Shard 只有那么幾個(gè),但是如何設(shè)置 Routing 是個(gè)難題,可根據(jù)業(yè)務(wù)特性巧妙組合。

三、索引拆分

Index 通過(guò)橫向擴(kuò)展 Shards 實(shí)現(xiàn)分布式存儲(chǔ),這樣可以解決 Index 大數(shù)據(jù)存儲(chǔ)的問(wèn)題。

但在一個(gè) Index 變的越來(lái)越大,單個(gè) Shard 也越來(lái)越大,查詢和存儲(chǔ)的速度也越來(lái)越慢。

更重要的是一個(gè) Index 其實(shí)是有存儲(chǔ)上限的(除非你設(shè)置足夠多的 Shards 和機(jī)器),如官方聲明單個(gè) Shard 的文檔數(shù)不能超過(guò) 20 億(受限于 Lucene index,每個(gè) Shard 是一個(gè) Lucene index)。

考慮到 I、O,針對(duì) Index 每個(gè) Node 的 Shards 數(shù)最好不超過(guò) 3 個(gè),那面對(duì)這樣一個(gè)龐大的 Index,我們是采用更多的 Shards,還是更多的 Index,我們?nèi)绾芜x擇?

Index 的 Shards 總量也不宜太多,更多的 Shards 會(huì)帶來(lái)更多的 I、O 開(kāi)銷,其實(shí)答案就已經(jīng)很明確,除非你能接受長(zhǎng)時(shí)間的查詢等待。

Index 拆分的思路很簡(jiǎn)單,時(shí)序索引有一個(gè)好處就是只有增加,沒(méi)有變更,按時(shí)間累積,天然對(duì)索引的拆分友好支持,可以按照時(shí)間和數(shù)據(jù)量做任意時(shí)間段的拆分。

ES 提供的 Rollover Api + Index Template 可以非常便捷和友好的實(shí)現(xiàn) Index 的拆分工作,把單個(gè) index docs 數(shù)量控制在百億內(nèi),也就是一個(gè) Index 默認(rèn) 5 個(gè) Shards 左右即可,保證查詢的即時(shí)響應(yīng)。

簡(jiǎn)單介紹一下 Rollover API 和 Index Template 這兩個(gè)東西,如何實(shí)現(xiàn) index 的拆分。

1、Index Template

我們知道 ES 可以為同一目的或同一類索引創(chuàng)建一個(gè) Index Template,之后創(chuàng)建的索引只要符合匹配規(guī)則就會(huì)套用這個(gè) Template,不必每次指定 Settings 和 Mappings 等屬性。

一個(gè) Index 可以被多個(gè) Template 匹配,那 Settings 和 Mappings 就是多個(gè) Template 合并后的結(jié)果。

有沖突通過(guò) Template 的屬性"order" : 0 從低到高覆蓋(這部分據(jù)說(shuō)會(huì)在 ES6 中會(huì)做調(diào)整,更好的解決 Template 匹配沖突問(wèn)題)。

示例:

 ? PUT _template/template_1{

? ? ? ? "index_patterns" : ["log-*"],

? ? ? ? "order" : 0,

? ? ? ? "settings" : {

? ? ? ? ? ? "number_of_shards" : 5

? ? ? ? },

? ? "aliases" : {

? ? ? ? ?"alias1" : {}

? ? ? ? }

? ? }
2、Rollover Index

百億級(jí)實(shí)時(shí)查詢優(yōu)化實(shí)戰(zhàn),讓你的Elasticsearch飛起來(lái)!

Rollover Index 可以將現(xiàn)有的索引通過(guò)一定的規(guī)則,如數(shù)據(jù)量和時(shí)間,索引的命名必須是 logs-000001 這種格式,并指定 aliases,示例:

 ? PUT /logs-000001

? ? {

? ? ? ? ?"aliases": {

? ? ? ? ?"logs_write": {}

? ? ? ? }

? ? }

? ? # Add > 1000 documents to logs-000001

? ? ?POST /logs_write/_rollover

? ? ?{

? ? ? "conditions": {

? ? ? ? ? ? "max_age": "7d",

? ? ? ? ? ? ?"max_docs": 1000

? ? ? ? }

? ? }

先創(chuàng)建索引并指定別名 logs_write,插入 1000 條數(shù)據(jù),然后請(qǐng)求 _rollover api 并指定拆分規(guī)則。

? 如果索引中的數(shù)據(jù)大于規(guī)則中指定的數(shù)據(jù)量或者時(shí)間過(guò)時(shí),新的索引將被創(chuàng)建,索引名稱為 logs-000002,并根據(jù)規(guī)則套用 Index Template, 同時(shí)別名 logs_write 也將被變更到 logs-000002。

注意事項(xiàng):

索引命名規(guī)則必須如同:logs-000001。

索引必須指定 aliases。

Rollover Index API 調(diào)用時(shí)才去檢查索引是否超出指定規(guī)則,不會(huì)自動(dòng)觸發(fā),需要手動(dòng)調(diào)用,可以通過(guò) Curator 實(shí)現(xiàn)自動(dòng)化。

如果符合條件會(huì)創(chuàng)建新的索引,老索引的數(shù)據(jù)不會(huì)發(fā)生變化,如果你已經(jīng)插入 2000 條,拆分后還是 2000 條。

插入數(shù)據(jù)時(shí)一定要用別名,否則你可能一直在往一個(gè)索引里追加數(shù)據(jù)。

技巧是按日期滾動(dòng)索引:

PUT /<logs-{now/d}-1>

{

"aliases": {

"logs_write": {}

}

}

假如生成的索引名為 logs-2017.04.13-1,如果你在當(dāng)天執(zhí)行 Rollover 會(huì)生成 logs-2017.04.13-000001,次日的話是 logs-2017.04.14-000001。

這樣就會(huì)按日期進(jìn)行切割索引,那如果你想查詢 3 天內(nèi)的數(shù)據(jù)可以通過(guò)日期規(guī)則來(lái)匹配索引名,如:

GET /<logs-{now/d}-*>,<logs-{now/d-1d}-*>,<logs-{now/d-2d}-*>/_search

到此,我們就可以通過(guò) Index Template 和 Rollover API 實(shí)現(xiàn)對(duì) Index 的任意拆分,并按照需要進(jìn)行任意時(shí)間段的合并查詢,這樣只要你的時(shí)間跨度不是很大,查詢速度一般可以控制在毫秒級(jí),存儲(chǔ)性能也不會(huì)遇到瓶頸。

四、Hot-Warm 架構(gòu)

百億級(jí)實(shí)時(shí)查詢優(yōu)化實(shí)戰(zhàn),讓你的Elasticsearch飛起來(lái)!

冷熱架構(gòu),為了保證大規(guī)模時(shí)序索引實(shí)時(shí)數(shù)據(jù)分析的時(shí)效性,可以根據(jù)資源配置不同將 Data Nodes 進(jìn)行分類形成分層或分組架構(gòu)。

一部分支持新數(shù)據(jù)的讀寫,另一部分僅支持歷史數(shù)據(jù)的存儲(chǔ),存放一些查詢發(fā)生機(jī)率較低的數(shù)據(jù)。

即 Hot-Warm 架構(gòu),對(duì) CPU,磁盤、內(nèi)存等硬件資源合理的規(guī)劃和利用,達(dá)到性能和效率的大化。

我們可以通過(guò) ES 的 Shard Allocation Filtering 來(lái)實(shí)現(xiàn) Hot-Warm 的架構(gòu)。

實(shí)現(xiàn)思路如下:

將 Data Node 根據(jù)不同的資源配比打上標(biāo)簽,如:Host、Warm。

定義 2 個(gè)時(shí)序索引的 Index Template,包括 Hot Template 和 Warm Template,Hot Template 可以多分配一些 Shard 和擁有更好資源的 Hot Node。

用 Hot Template 創(chuàng)建一個(gè) Active Index 名為 active-logs-1,別名 active-logs,支持索引切割。

插入一定數(shù)據(jù)后,通過(guò) roller over api 將 active-logs 切割,并將切割前的 Index 移動(dòng)到 Warm Nodes 上,如 active-logs-1,并阻止寫入。

通過(guò) Shrinking API 收縮索引 active-logs-1 為 inactive-logs-1,原 Shard 為 5,適當(dāng)收縮到 2 或 3,可以在 Warm Template 中指定,減少檢索的 Shard,使查詢更快。

通過(guò) force-merging api 合并 inactive-logs-1 索引每個(gè) Shard 的 Segment,節(jié)省存儲(chǔ)空間。

刪除 active-logs-1。

1、Hot,Warm Nodes

Hot Nodes

擁有最好資源的 Data Nodes,如更高性能的 CPU、SSD 磁盤、內(nèi)存等資源,這些特殊的 Nodes 支持索引所有的讀、寫操作。

如果你計(jì)劃以 100 億為單位來(lái)切割 Index,那至少需要三個(gè)這樣的 Data Nodes,Index 的 Shard 數(shù)為 5,每個(gè) Shard 支持 20 億 Documents 數(shù)據(jù)的存儲(chǔ)。

為這類 Data Nodes 打上標(biāo)簽,以便我們?cè)?Template 中識(shí)別和指定,啟動(dòng)參數(shù)如下:

./bin/elasticsearch -Enode.attr.box_type=hot

或者配置文件:

node.attr.box_type: hot

Warm Nodes

存儲(chǔ)只讀數(shù)據(jù),并且查詢量較少,但用于存儲(chǔ)長(zhǎng)多時(shí)間歷史數(shù)據(jù)的 Data Nodes,這類 Nodes 相對(duì) Hot Nodes 較差的硬件配置,根據(jù)需求配置稍差的 CPU、機(jī)械磁盤和其他硬件資源,至于數(shù)量根據(jù)需要保留多長(zhǎng)時(shí)間的數(shù)據(jù)來(lái)配比,同樣需要打上標(biāo)簽,方法跟 Hot Nodes 一樣,指定為 Warm,box_type: warm。

2、Hot,Warm Template

Hot Template

我們可以通過(guò)指定參數(shù)"routing.allocation.include.box_type": "hot",讓所有符合命名規(guī)則索引的 Shard 都將被分配到 Hot Nodes 上:

PUT _template/active-logs

{

"template": "active-logs-*",

"settings": {

"number_of_shards": 5,

"number_of_replicas": 1,

"routing.allocation.include.box_type": "hot",

"routing.allocation.total_shards_per_node": 2

},

"aliases": {

"active-logs": {}

}

}
Warm Template

同樣符合命名規(guī)則索引的 Shard 會(huì)被分配到 Warm Nodes 上,我們指定了更少的 Shards 數(shù)量和復(fù)本數(shù)。

注意,這里的復(fù)本數(shù)為 0,和 best_compression 級(jí)別的壓縮,方便做遷移等操作,以及進(jìn)行一些數(shù)據(jù)的壓縮:

PUT _template/inactive-logs

{

"template": "inactive-logs-*",

"settings": {

"number_of_shards": 1,

"number_of_replicas": 0,

"routing.allocation.include.box_type": "warm",

"codec": "best_compression"

}

}

假如我們已經(jīng)創(chuàng)建了索引 active-logs-1 ,當(dāng)然你可以通過(guò) _bulk API 快速寫入測(cè)試的數(shù)據(jù),然后參考上文中介紹的 Rollover API 進(jìn)行切割。

3、Shrink Index
Rollover API 切割以后,active-logs-1 將變成一個(gè)冷索引,我們將它移動(dòng)到 Warm Nodes 上。

先將索引置為只讀狀態(tài),拒絕任何寫入操作,然后修改 index.routing.allocation.include.box_type 屬性,ES 會(huì)自動(dòng)移動(dòng)所有 Shards 到目標(biāo) Data Nodes 上:

PUT active-logs-1/_settings

{

"index.blocks.write": true,

"index.routing.allocation.include.box_type": "warm"

}

Cluster Health API 可以查看遷移狀態(tài),完成后進(jìn)行收縮操作,其實(shí)相當(dāng)于復(fù)制出來(lái)一個(gè)新的索引,舊的索引還存在。

POST active-logs-1/_shrink/inactive-logs-1

我們可以通過(guò) Head 插件查看整個(gè)集群索引的變化情況。

Forcemerge

到目前為止我們已經(jīng)實(shí)現(xiàn)了索引的冷熱分離,和索引的收縮,我們知道每個(gè) Shard 下面由多個(gè) Segment 組成,那 inactive-logs-1 的 Shard 數(shù)是 1,但 Segment 還是多個(gè)。

這類索引不會(huì)在接受寫入操作,為了節(jié)約空間和改善查詢性能,通過(guò) Forcemerge API 將 Segment 適量合并:

PUT inactive-logs-1/_settings

{ "number_of_replicas": 1 }

ES 的 Forcemerge 過(guò)程是先創(chuàng)建新的 Segment 刪除舊的,所以舊 Segment 的壓縮方式 best_compression 不會(huì)在新的 Segment 中生效,新的 Segment 還是默認(rèn)的壓縮方式。

現(xiàn)在 inactive-logs-1 的復(fù)本還是 0,如果有需要的話,可以分配新的復(fù)本數(shù):

PUT inactive-logs-1/_settings

{ "number_of_replicas": 1 }

最后刪除 active-logs-1,因?yàn)槲覀円呀?jīng)為它做了一個(gè)查詢復(fù)本 inactive-logs-1。

DELETE active-logs-1

走到這里,我們就已經(jīng)實(shí)現(xiàn)了 Index 的 Hot-Warm 架構(gòu),根據(jù)業(yè)務(wù)特點(diǎn)將一段時(shí)間的數(shù)據(jù)放在 Hot Nodes,更多的歷史數(shù)據(jù)存儲(chǔ)于 Warm Nodes。

五、其他優(yōu)化方案

這一部分我們會(huì)展示更多的優(yōu)化方案。

1、索引隔離

百億級(jí)實(shí)時(shí)查詢優(yōu)化實(shí)戰(zhàn),讓你的Elasticsearch飛起來(lái)!

在多條業(yè)務(wù)線的索引共用一個(gè) ES 集群時(shí)會(huì)發(fā)生流量被獨(dú)吃獨(dú)占的情況,因?yàn)榇蠹叶脊灿孟嗤募嘿Y源,流量大的索引會(huì)占用大部分計(jì)算資源而流量小的也會(huì)被拖慢,得不到即時(shí)響應(yīng),或者說(shuō)業(yè)務(wù)流量大的索引可以按天拆分,幾個(gè)流量小的索引可以按周或月拆分。

這種情況下我們可以將規(guī)模大的索引和其他相對(duì)小規(guī)模的索引獨(dú)立存儲(chǔ),分開(kāi)查詢或合并查詢。

除了 Master Nodes 以外,Data Nodes 和 Coordinating Nodes 都可以獨(dú)立使用(其實(shí)如果每個(gè)索引的量都特別大也應(yīng)該采用這種架構(gòu)),還有一個(gè)好處是對(duì)方的某個(gè) Node 掛掉,自己不受影響。

同樣利用 ES 支持 Shard Allocation Filtering 功能來(lái)實(shí)現(xiàn)索引的資源獨(dú)立分配,先將 Nodes 進(jìn)行打標(biāo)簽,劃分區(qū)域,類似于 Hot-Warm 架構(gòu):

node.attr.zone=zone_a、node.attr.zone=zone_b

或者:

node.attr.zone =zone_hot_a、node.attr.zone=zone_hot_b

等打標(biāo)簽的方式來(lái)區(qū)別對(duì)應(yīng)不同的索引,然后在各自的 Index Template 中指定不同的 node.attr.zone 即可。

如"index.routing.allocation.include.zone" : "zone_a,zone_hot_a",或者排除法"index.routing.allocation.exclude.size": "zone_hot_b"分配到 zone_hot_b 以外的所有 Data Nodes 上。

更多用法可以參考 Hot-Warm 架構(gòu),或 shard-allocation-filtering:

2、跨數(shù)據(jù)中心

百億級(jí)實(shí)時(shí)查詢優(yōu)化實(shí)戰(zhàn),讓你的Elasticsearch飛起來(lái)!

如果你的業(yè)務(wù)遍布全國(guó)各地,四海八荒,如果你數(shù)據(jù)要存儲(chǔ)到多個(gè)機(jī)房,如果你的 Index 有幾萬(wàn)個(gè)甚至更多( Index 特別多,集群龐大會(huì)導(dǎo)致 Cluster State 信息量特別大,因?yàn)?Cluster State 包含了所有 Shard、Index、Node 等所有相關(guān)信息,它存儲(chǔ)在每個(gè) Node 上,這些數(shù)據(jù)發(fā)生變化都會(huì)實(shí)時(shí)同步到所有 Node 上,當(dāng)這個(gè)數(shù)據(jù)很大的時(shí)候會(huì)對(duì)集群的性能造成影響)。

這些情況下我們會(huì)考慮部署多個(gè) ES Cluster,那我們將如何解決跨集群查詢的問(wèn)題呢?

目前 ES 針對(duì)跨集群操作提供了兩種方案 Tribe Node 和 Cross Cluster Search。

Tribe Node

百億級(jí)實(shí)時(shí)查詢優(yōu)化實(shí)戰(zhàn),讓你的Elasticsearch飛起來(lái)!

需要一個(gè)獨(dú)立的 Node 節(jié)點(diǎn),加入其他 ES Cluster,用法有點(diǎn)類似于 Coordinating Only Node。

所不同的是 Tribe 是針對(duì)多個(gè) ES 集群之間的所有節(jié)點(diǎn),Tribe Node 收到請(qǐng)求廣播到相關(guān)集群中所有節(jié)點(diǎn),將結(jié)果合并處理后返回。

表面上看起來(lái) Tribe Node 將多個(gè)集群串連成了一個(gè)整體,遇到同名 Index 發(fā)生沖突,會(huì)選擇其中一個(gè) Index,也可以指定:

tribe:

on_conflict: prefer_t1

t1:

cluster.name: us-cluster

discovery.zen.ping.multicast.enabled: false

discovery.zen.ping.unicast.hosts: ['usm1','usm2','usm3']

t2:

cluster.name: eu-cluster

discovery.zen.ping.multicast.enabled: false

discovery.zen.ping.unicast.hosts: ['eum1','eum2','eum3']
Cross Cluster Search

百億級(jí)實(shí)時(shí)查詢優(yōu)化實(shí)戰(zhàn),讓你的Elasticsearch飛起來(lái)!

Cross Cluster Search 可以讓集群中的任意一個(gè)節(jié)點(diǎn)聯(lián)合查詢其他集群中的數(shù)據(jù), 通過(guò)配置 elasticsearch.yml 或者 API 來(lái)啟用這個(gè)功能,API 示例:

PUT _cluster/settings

{

"persistent": {

"search": {

"remote": {

"cluster_one": {

"seeds": [

"127.0.0.1:9300"

]

...

}

}

}

}

}

提交以后整個(gè)集群所有節(jié)點(diǎn)都會(huì)生效,都可以做為代理去做跨集群聯(lián)合查詢,不過(guò)我們最好還是通過(guò) Coordinating Only Nodes 去發(fā)起請(qǐng)求。

POST /cluster_one:decision,decision/_search

{

"match_all": {}

}

對(duì)集群 cluster_one 和本集群中名為 Decision 的索引聯(lián)合查詢。

目前這個(gè)功能還在測(cè)試階段,但未來(lái)可能會(huì)取代 Tribe Node,之間的大的差異是 Tribe Node 需要設(shè)置獨(dú)立的節(jié)點(diǎn),而 Cross Cluster Search 不需要,集群中的任意一個(gè)節(jié)點(diǎn)都可以兼任。

比如可以用我們的 Coordinating Only Nodes 做為聯(lián)合查詢節(jié)點(diǎn),另一個(gè)優(yōu)點(diǎn)是配置是動(dòng)態(tài)的,不需要重啟節(jié)點(diǎn)。

實(shí)際上可以理解為是一個(gè) ES 集群之間特定的動(dòng)態(tài)代理工具,支持所有操作,包括 Index 的創(chuàng)建和修改,并且通過(guò) Namespace 對(duì) Index 進(jìn)行隔離,也解決了 Tribe Node 之 Index 名稱沖突的問(wèn)題。

六、總結(jié)

我們?cè)谖闹薪榻B了幾種方案用來(lái)解決時(shí)序索引的海量數(shù)據(jù)存儲(chǔ)和查詢的問(wèn)題,根據(jù)業(yè)務(wù)特點(diǎn)和使用場(chǎng)景來(lái)單獨(dú)或組合使用能夠發(fā)揮出意想不到的效果。

特別是 Nodes 之間的讀寫分離、索引拆分、Hot-Warm 等方案的組合應(yīng)用對(duì)索引的查詢和存儲(chǔ)性能有顯著的提升。

另外 Routing 在新版本中增加了 routing_partition_size,解決了 Shard 難以均衡的問(wèn)題。

如果你的索引 Mapping 中沒(méi)有 parent-child 關(guān)聯(lián)關(guān)系可以考慮使用,對(duì)查詢的性能提升非常有效。

創(chuàng)新互聯(lián)www.cdcxhl.cn,專業(yè)提供香港、美國(guó)云服務(wù)器,動(dòng)態(tài)BGP最優(yōu)骨干路由自動(dòng)選擇,持續(xù)穩(wěn)定高效的網(wǎng)絡(luò)助力業(yè)務(wù)部署。公司持有工信部辦法的idc、isp許可證, 機(jī)房獨(dú)有T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確進(jìn)行流量調(diào)度,確保服務(wù)器高可用性。佳節(jié)活動(dòng)現(xiàn)已開(kāi)啟,新人活動(dòng)云服務(wù)器買多久送多久。

網(wǎng)頁(yè)名稱:百億級(jí)實(shí)時(shí)查詢優(yōu)化實(shí)戰(zhàn),讓你的Elasticsearch飛起來(lái)!-創(chuàng)新互聯(lián)
本文來(lái)源:http://muchs.cn/article4/dpjeie.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)頁(yè)設(shè)計(jì)公司、網(wǎng)站改版、網(wǎng)站維護(hù)網(wǎng)站收錄、微信小程序定制開(kāi)發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

網(wǎng)站托管運(yùn)營(yíng)