- Elastic Stack應(yīng)用寶典
- 田雪松編著
- 3499字
- 2020-07-22 17:21:27
3.3 容量控制與緩存機制
索引容量由分片數(shù)量和分片容量決定,分片數(shù)量可以通過_split接口擴容,也可以通過_shrink接口縮容。需要注意的是,這種擴容、縮容的方式依然是將原索引擴容、縮容到新索引上,并不是在原索引上做擴展;而且使用_split接口擴容時,分片擴容依然存在上限,如果增加分片的數(shù)量超過了容量上限,就只能通過_reindex接口對索引做重新索引。
除了這三個可以直接或間接控制索引容量的接口以外,Elasticsearch為了提升性能還默認開啟了緩存機制。由于容量與緩存實際上都與索引性能相關(guān),本節(jié)最后還會介紹一組可以查看索引及分片運行狀態(tài)的接口,它們經(jīng)常會在性能調(diào)優(yōu)時使用。
3.3.1 _split接口
_split接口可以在新索引中將每個主分片分裂為兩個或更多分片,所以使用_split擴容時分片總量都是成倍增加而不能逐個增加。使用_split接口分裂分片雖然會創(chuàng)建新的索引,但新索引中的數(shù)據(jù)只是通過文件系統(tǒng)硬連接到新索引中,所以并不存在數(shù)據(jù)復制過程。而擴容的分片又是在本地分裂,所以不存在不同節(jié)點間網(wǎng)絡(luò)傳輸數(shù)據(jù)的開銷,所以_split擴容效率相對其他方案來說還是比較高的。
_split接口做動態(tài)擴容需要預先設(shè)置索引的number_of_routing_shards參數(shù),Elasticsearch向分片散列文檔采用一致性哈希算法,這個參數(shù)實際上設(shè)置了索引分片散列空間。所以分裂后分片數(shù)量必須是number_of_routing_shards的因數(shù),同時是number_of_shards的倍數(shù)。例如,設(shè)置number_of_routing_shards為12,number_of_shards為2,則分片再分裂存在2→4→12、2→6→12和2→12三種可能的擴容路徑。分裂后分片數(shù)量可通過_split接口的index.number_of_shards參數(shù)設(shè)置,數(shù)量必須滿足前述整數(shù)倍的要求。需要注意的是,這個參數(shù)的“index.”前綴是不能省略的,因為這是在_split接口中而不是在創(chuàng)建索引接口中。上面講解的這些規(guī)則比較抽象,下面通過創(chuàng)建一個具體示例來看一下如何通過_split接口擴容索引。
首先創(chuàng)建一個索引employee,將它的主分片數(shù)量number_of_shards設(shè)置為2,散列空間number_of_routing_shards設(shè)置為12。然后,通過將索引的blocks.write參數(shù)設(shè)置為true,將索引設(shè)置為只讀,這是因為使用_split接口要求索引必須為只讀。最后調(diào)用_split接口將employee索引的分片分裂到新索引splited_employee中,index.number_of_shards參數(shù)設(shè)置為4,即分裂為4個分片。如示例3-20所示:

示例3-20 _split分裂分片
在執(zhí)行成功后,可調(diào)用“GET _cat/shards”查看分片。在返回結(jié)果中可以看到employee索引共有4個分片,即2個主分片和2個副本分片;新索引splited_employee會有8個分片,即4個主分片和4個副本分片。_split接口在創(chuàng)建新索引的同時,會將原索引的配置也一同設(shè)置到新索引中。所以index.blocks.write參數(shù)也會一同被復制過來,但這可能并不是我們想要的。所幸在分裂分片的同時支持通過aliases和settings設(shè)置新索引的別名和配置,所以可以在分裂分片的同時將index.blocks.write參數(shù)覆蓋。在示例3-20中就將這個參數(shù)覆蓋了,同時還添加了新的別名stu。另外,還可以在地址中添加copy_settings=false參數(shù)禁止從源索引中復制配置,但這個參數(shù)在版本8中有可能被廢止,所以添加這個參數(shù)會收到警告。
需要注意的是,使用_split接口成功分裂分片后,原索引并不會被自動刪除。通過原索引和新索引都可以查看到相同的文檔數(shù)據(jù),原索引是否刪除應(yīng)根據(jù)業(yè)務(wù)需要具體判斷。
3.3.2 _shrink接口
與_split接口相反,_shrink接口用于縮減索引分片。盡管它們在邏輯上正好相反,但它們在應(yīng)用時的規(guī)則基本上是一致的。比如,_shrink接口在縮減索引分片數(shù)量時也要求原始分片數(shù)量必須是縮減后分片數(shù)量的整數(shù)倍。例如原始分片數(shù)量為12,則可以按12→6→3→1的路徑縮減,也可以按12→4→2→1的路徑縮減。在調(diào)用_shrink接口前要滿足兩個條件,第一個條件與_split接口類似,就是要求索引在縮容期間必須只讀;第二個條件有些特殊,就是要求索引所有分片(包括副本分片)都要復制一份存儲在同一節(jié)點,并且要求健康狀態(tài)為green,這可以通過routing.allocation.require._name指定節(jié)點名稱實現(xiàn)。如果想要查看節(jié)點名稱,可調(diào)用“GET _nodes”接口相看所有集群節(jié)點。
與_split接口類似,索引在縮減后的具體分片數(shù)量可通過_shrink接口的index.number_of_shards參數(shù)設(shè)置。但它的值必須與原始分片數(shù)量保持整數(shù)比例關(guān)系,如果不設(shè)置該參數(shù)將直接縮減為1個分片。如示例3-21所示,縮減后索引分片數(shù)量為2,同時還清除了兩項配置:

示例3-21 _shrink接口
同樣地,使用_shrink接口縮容后會創(chuàng)建新索引shrinked_employee,原索引和新索引都可以查詢到相同的文檔數(shù)據(jù)。
3.3.3 _reindex接口
盡管_split接口和_shrink接口可以對索引分片數(shù)量做擴容和縮容,但在分片數(shù)量上有倍數(shù)要求,并且分片總量受散列空間(即number_of_routing_shards參數(shù))的限制。如果索引容量超出了散列空間或者有其他特殊要求,則可以按新需求創(chuàng)建新的索引。Elasticsearch提供的_reindex接口支持將文檔從一個索引重新索引到到另一個索引中。但顯然重新索引在性能上的開銷要比_split和_shrink大,所以盡量不要使用這種辦法。_reindex接口需要兩個參數(shù)source和dest,前者指明文檔來源索引而后者則指明了文檔添加的新索引。例如在示例3-22中是將users索引中的文檔添加到users_copy索引中:

示例3-22 _reindex接口
需要注意的是,在重新索引時,不會將原索引的配置信息復制到新索引中。如果事先沒有指定索引配置,重新索引時將根據(jù)默認配置創(chuàng)建索引及映射。另外,使用_reindex接口必須將索引的_source字段開啟。
在實際應(yīng)用中,_reindex接口并不是應(yīng)用于擴容和縮容,而是主要應(yīng)用于索引數(shù)據(jù)的合并。所以在_reindex接口中還提供了一些其他參數(shù),用于處理在合并過程中出現(xiàn)的問題。例如:


示例3-23 合并索引
在示例3-23中,source參數(shù)除了指定源索引以外,還添加了term查詢用于過濾文檔,而dest參數(shù)則使用op_type參數(shù)設(shè)置了合并時只添加不存在的文檔。
3.3.4 緩存機制
為了提升數(shù)據(jù)檢索時的性能,Elasticsearch為索引提供了三種緩存。第一種緩存稱為節(jié)點查詢緩存(Node Query Cache),負責存儲節(jié)點查詢結(jié)果。節(jié)點查詢緩存是節(jié)點級別的,一個節(jié)點只有一個緩存,同一節(jié)點上的分片共享同一緩存。在默認情況下,節(jié)點查詢緩存是開啟的,可通過索引index.queries.cache.enabled參數(shù)關(guān)閉。節(jié)點查詢緩存默認使用節(jié)點內(nèi)存的10%作為緩存容量上限,可通過indices.queries.cache_size更改,這個參數(shù)是節(jié)點的配置而非索引配置。
第二種緩存被稱為分片請求緩存(Shard Request Cache),負責存儲分片接收到的查詢結(jié)果。分片請求緩存不會緩存查詢結(jié)果的hits字段,也就是具體的文檔內(nèi)容,它一般只緩存聚集查詢的相關(guān)結(jié)果。在默認情況下,分片請求緩存也是開啟的,通過索引index.requests.cache.enable參數(shù)關(guān)閉。另一種關(guān)閉該緩存的辦法,是在調(diào)用_search接口時添加request_cache=false參數(shù)。分片請求緩存使用的鍵是作為查詢條件JSON字符串,所以如果查詢條件JSON串完全相同,文檔的查詢幾乎可以達到實時。但由于JSON屬性之間并沒有次序要求,這意味著即使JSON描述的是同一個對象,只要它們屬性的次序不同就不能在緩存中命中數(shù)據(jù)。這一點在使用時需要格外注意。
最后一種緩存就是text類型字段在開啟fielddata機制后使用的緩存,它會將text類型字段提取的所有詞項全部加載到內(nèi)存中,以提高使用該字段做排序和聚集運算的效率。由于fielddata是text類型對文檔值機制的代替,所以天然就是開啟的且不能關(guān)閉。但可通過indices.fielddata.cache.size設(shè)置這個緩存的容量,默認情況下該緩存沒有容量上限。
緩存的引入使得文檔檢索性能得到了提升,但緩存一般會帶來兩個主要問題:一是如何保證緩存數(shù)據(jù)與實際數(shù)據(jù)的一致;另一個問題是當緩存容量超出時如何清理緩存。數(shù)據(jù)一致性問題,Elasticsearch是通過讓緩存與索引刷新頻率保持一致實現(xiàn)的。還記得索引是準實時的嗎?索引默認情況下會以每秒一次的頻率將文檔編入索引,Elasticsearch會在索引更新的同時讓緩存也失效,這就保證了索引數(shù)據(jù)與緩存數(shù)據(jù)的一致性。緩存數(shù)據(jù)容量問題則是通過LRU的方式,將最近最少使用的緩存條目清除。同時,Elasticsearch還提供了一個_cache接口用于主動清理緩存。之所以要提供這個接口,是因為Elasticsearch為索引提供了一個主動刷新的接口_refresh,所以最好在主動刷新索引后再主動清理緩存。
1._refresh接口
_refresh接口用于主動刷新一個或多個索引,將已經(jīng)添加的文檔編入索引以使它們在檢索時可見。在調(diào)用該接口時,可以直接調(diào)用或與一個或多個索引一起使用,還可以使用_all刷新所有索引,所以以下調(diào)用都是正確的:

示例3-24 _refresh接口
事實上,除了使用_refresh接口主動刷新索引外,也可以在操作文檔時通過refresh參數(shù)刷新索引,具體請參考3.4節(jié)的講解。
2._cache接口
_cache接口用于主動清理緩存,在調(diào)用該接口時需要在_cache后附加關(guān)鍵字clear。_cache接口可以清理所有緩存,也可以清理某一索引甚至某一字段的緩存,還可以只清理某一種類型的緩存。例如:

示例3-25 _cache接口
在示例3-25中,query、request、fielddata參數(shù)分別對應(yīng)于不同的緩存類型,而fields參數(shù)則用于定義清理哪一個字段的緩存。
3.3.5 查看運行狀態(tài)
除此上述接口以外,Elasticsearch還提供了一組用于查看索引及分片運行情況的接口,包括_stat、_shard_stores和_segments等。由于它們往往在性能分析時使用,所以本小節(jié)將它們放在一起講解。
1._stat接口
_stats接口用于查看索引上不同操作的統(tǒng)計數(shù)據(jù),可以直接請求也可以與索引名稱一起使用。_stats接口返回的統(tǒng)計數(shù)據(jù)非常多,如果只對其中某一組統(tǒng)計數(shù)據(jù)感興趣,可以在_stats接口后附加統(tǒng)計名稱。例如以下對_stats接口的調(diào)用都是正確的:

示例3-26 _stats接口
在_stats接口中可以使用的統(tǒng)計名稱及它們的含義見表3-4,它們在返回結(jié)果中的含義與此相同。
表3-4 _stats接口統(tǒng)計名稱

2._shard_stores和_segments接口
_shard_stores接口用于查詢索引分片存儲情況,而_segments接口則用于查看底層Lucene的分段情況。這兩個接口都只能通過GET方法請求,同時都可以針對一個或多個索引,例如:

示例3-27 _shard_stores和_segments接口
- C++ Primer習題集(第5版)
- MySQL數(shù)據(jù)庫管理實戰(zhàn)
- JavaScript百煉成仙
- R語言數(shù)據(jù)分析從入門到精通
- Azure IoT Development Cookbook
- ASP.NET Core 5.0開發(fā)入門與實戰(zhàn)
- 機器人Python青少年編程開發(fā)實例
- aelf區(qū)塊鏈應(yīng)用架構(gòu)指南
- Nginx實戰(zhàn):基于Lua語言的配置、開發(fā)與架構(gòu)詳解
- Python深度學習原理、算法與案例
- ASP.NET Core and Angular 2
- 青少年P(guān)ython趣味編程
- INSTANT PLC Programming with RSLogix 5000
- Learning Alfresco Web Scripts
- 接口自動化測試持續(xù)集成:Postman+Newman+Git+Jenkins+釘釘