中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁(yè) > news >正文

陜西整站關(guān)鍵詞自然排名優(yōu)化湖南網(wǎng)絡(luò)推廣機(jī)構(gòu)

陜西整站關(guān)鍵詞自然排名優(yōu)化,湖南網(wǎng)絡(luò)推廣機(jī)構(gòu),sae wordpress 主題,支付網(wǎng)站開(kāi)發(fā)費(fèi)可以做無(wú)形資產(chǎn)配置內(nèi)存 #1.內(nèi)存架構(gòu) #1.1.概述 Ignite內(nèi)存架構(gòu)通過(guò)可以同時(shí)在內(nèi)存和磁盤(pán)上存儲(chǔ)和處理數(shù)據(jù)及索引,得到了支持磁盤(pán)持久化的內(nèi)存級(jí)性能。 多層存儲(chǔ)的運(yùn)行方式類(lèi)似于操作系統(tǒng)(例如Linux)的虛擬內(nèi)存。但是這兩種類(lèi)型架構(gòu)之間的主要區(qū)別是&…

配置內(nèi)存

#1.內(nèi)存架構(gòu)

#1.1.概述

Ignite內(nèi)存架構(gòu)通過(guò)可以同時(shí)在內(nèi)存和磁盤(pán)上存儲(chǔ)和處理數(shù)據(jù)及索引,得到了支持磁盤(pán)持久化的內(nèi)存級(jí)性能。

多層存儲(chǔ)的運(yùn)行方式類(lèi)似于操作系統(tǒng)(例如Linux)的虛擬內(nèi)存。但是這兩種類(lèi)型架構(gòu)之間的主要區(qū)別是,多層存儲(chǔ)始終將磁盤(pán)視為數(shù)據(jù)的超集(如果啟用了持久化),在故障或者重啟后仍然可以保留數(shù)據(jù),而傳統(tǒng)的虛擬內(nèi)存僅將磁盤(pán)作為交換擴(kuò)展,一旦進(jìn)程停止,數(shù)據(jù)就會(huì)被清除。

#1.2.內(nèi)存架構(gòu)

多層架構(gòu)是一種基于固定大小頁(yè)面的內(nèi)存架構(gòu),這些頁(yè)面存儲(chǔ)在內(nèi)存(Java堆外)的托管非堆區(qū)中,并按磁盤(pán)上的特定層次結(jié)構(gòu)進(jìn)行組織。

Ignite在內(nèi)存和磁盤(pán)上都維護(hù)相同的二進(jìn)制數(shù)據(jù)表示形式,這樣在內(nèi)存和磁盤(pán)之間移動(dòng)數(shù)據(jù)時(shí)就不需要進(jìn)行昂貴的序列化。

下圖說(shuō)明了多層存儲(chǔ)架構(gòu):

#1.2.1.內(nèi)存段

每個(gè)數(shù)據(jù)區(qū)均以初始大小開(kāi)始,并具有可以增長(zhǎng)到的最大大小。該區(qū)域通過(guò)分配連續(xù)的內(nèi)存段擴(kuò)展到其最大大小。

內(nèi)存段是從操作系統(tǒng)分配的物理內(nèi)存的連續(xù)字節(jié)數(shù)組,該數(shù)組被拆分為固定大小的頁(yè)面。該段中可以存在幾種類(lèi)型的頁(yè)面,如下圖所示。

#1.2.2.數(shù)據(jù)頁(yè)面

數(shù)據(jù)頁(yè)面存儲(chǔ)從應(yīng)用端寫(xiě)入緩存的條目。

通常每個(gè)數(shù)據(jù)頁(yè)面持有多個(gè)鍵值條目,以便盡可能高效地使用內(nèi)存并避免內(nèi)存碎片。將新條目添加到緩存后,Ignite會(huì)尋找一個(gè)適合整個(gè)鍵-值條目的最佳頁(yè)面。

但是如果一個(gè)條目的總大小超過(guò)了DataStorageConfiguration.setPageSize(..)屬性配置的頁(yè)面大小,則該條目將占用多個(gè)數(shù)據(jù)頁(yè)面。

提示

如果有許多緩存條目無(wú)法容納在單個(gè)頁(yè)面中,那么增加頁(yè)面大小配置參數(shù)是有必要的。

如果在更新期間條目大小擴(kuò)大并超過(guò)了其數(shù)據(jù)頁(yè)面的剩余可用空間,則Ignite會(huì)搜索新的空間足夠的數(shù)據(jù)頁(yè)面,并將其移到那里。

#1.2.3.內(nèi)存碎片整理

Ignite自動(dòng)執(zhí)行內(nèi)存碎片整理,不需要用戶(hù)干預(yù)。

隨著時(shí)間的推移,每個(gè)數(shù)據(jù)頁(yè)面可能會(huì)通過(guò)不同的CRUD操作多次更新,這會(huì)導(dǎo)致頁(yè)面和整體內(nèi)存碎片化。為了最大程度地減少內(nèi)存碎片,只要頁(yè)面碎片過(guò)多,Ignite都會(huì)使用頁(yè)面壓縮。

壓縮的數(shù)據(jù)頁(yè)面如下圖所示:

頁(yè)面具有一個(gè)頭部,其存儲(chǔ)內(nèi)部使用所需的元信息。所有鍵-值條目總是從右到左添加。在上圖中,頁(yè)面中存儲(chǔ)了三個(gè)條目(分別為1、2和3)。這些條目可能具有不同的大小。

頁(yè)面內(nèi)條目位置的偏移量(或引用)從左到右存儲(chǔ),并且始終為固定大小。偏移量用于在頁(yè)面中查找鍵-值條目的指針。

中間的空間是可用空間,每當(dāng)將更多數(shù)據(jù)推入集群時(shí),該空間就會(huì)被填充。

接下來(lái),假設(shè)隨著時(shí)間的推移,條目2被刪除,這導(dǎo)致頁(yè)面中的非連續(xù)可用空間:

這就是碎片化頁(yè)面的樣子。

但是,當(dāng)需要頁(yè)面的整個(gè)可用空間或達(dá)到某個(gè)碎片閾值時(shí),壓縮過(guò)程會(huì)對(duì)頁(yè)面進(jìn)行碎片整理,使其變?yōu)樯厦娴谝粡垐D片中所示的狀態(tài),其中該連續(xù)空間是連續(xù)的。此過(guò)程是自動(dòng)的,不需要用戶(hù)干預(yù)。

#1.3.持久化

Ignite提供了許多功能,可以將數(shù)據(jù)持久化磁盤(pán)上,同時(shí)還保持一致性??梢栽诓粊G失數(shù)據(jù)的前提下重啟集群,可以應(yīng)對(duì)故障,并在內(nèi)存不足時(shí)為數(shù)據(jù)提供存儲(chǔ)。啟用原生持久化后,Ignite會(huì)將所有數(shù)據(jù)保存在磁盤(pán)上,并將盡可能多的數(shù)據(jù)加載到內(nèi)存中進(jìn)行處理。更多信息請(qǐng)參考Ignite持久化章節(jié)的內(nèi)容。

#2.配置數(shù)據(jù)區(qū)

#2.1.概述

Ignite使用數(shù)據(jù)區(qū)的概念來(lái)控制可用于緩存的內(nèi)存數(shù)量,數(shù)據(jù)區(qū)是緩存數(shù)據(jù)存儲(chǔ)在內(nèi)存中的邏輯可擴(kuò)展區(qū)域??梢钥刂茢?shù)據(jù)區(qū)的初始值及其可以占用的最大值,除了大小之外,數(shù)據(jù)區(qū)還控制緩存的持久化配置。

Ignite有一個(gè)默認(rèn)的數(shù)據(jù)區(qū)最多可占用該節(jié)點(diǎn)20%的內(nèi)存,并且創(chuàng)建的所有緩存均位于該數(shù)據(jù)區(qū)中,但是也可以添加任意多個(gè)數(shù)據(jù)區(qū),創(chuàng)建多個(gè)數(shù)據(jù)區(qū)的原因有:

  • 可以通過(guò)不同數(shù)據(jù)區(qū)分別配置緩存對(duì)應(yīng)的可用內(nèi)存量;
  • 持久化參數(shù)是按數(shù)據(jù)區(qū)配置的。如果要同時(shí)具有純內(nèi)存緩存和持久化緩存,則需要配置兩個(gè)(或多個(gè))具有不同持久化參數(shù)的數(shù)據(jù)區(qū):一個(gè)用于純內(nèi)存緩存,一個(gè)用于持久化緩存;
  • 部分內(nèi)存參數(shù),比如退出策略,是按照數(shù)據(jù)區(qū)進(jìn)行配置的。

下面的章節(jié)會(huì)演示如何更改默認(rèn)數(shù)據(jù)區(qū)的參數(shù)或配置多個(gè)數(shù)據(jù)區(qū)。

#2.2.配置默認(rèn)數(shù)據(jù)區(qū)

新的緩存默認(rèn)會(huì)添加到默認(rèn)的數(shù)據(jù)區(qū)中,可以在數(shù)據(jù)區(qū)配置中更改默認(rèn)數(shù)據(jù)區(qū)的屬性:

  • XML
  • Java
  • C#/.NET
DataStorageConfiguration storageCfg = new DataStorageConfiguration();DataRegionConfiguration defaultRegion = new DataRegionConfiguration();
defaultRegion.setName("Default_Region");
defaultRegion.setInitialSize(100 * 1024 * 1024);storageCfg.setDefaultDataRegionConfiguration(defaultRegion);IgniteConfiguration cfg = new IgniteConfiguration();cfg.setDataStorageConfiguration(storageCfg);// Start the node.
Ignite ignite = Ignition.start(cfg);

#2.3.添加自定義數(shù)據(jù)區(qū)

除了默認(rèn)的數(shù)據(jù)區(qū),還可以使用自定義配置定義更多個(gè)數(shù)據(jù)區(qū),在下面的示例中,配置了一個(gè)數(shù)據(jù)區(qū)占用40MB空間然后使用了Random-2-LRU退出策略,注意在進(jìn)一步的緩存配置中,在該數(shù)據(jù)區(qū)中創(chuàng)建了一個(gè)緩存。

  • XML
  • Java
  • C#/.NET
DataStorageConfiguration storageCfg = new DataStorageConfiguration();DataRegionConfiguration defaultRegion = new DataRegionConfiguration();
defaultRegion.setName("Default_Region");
defaultRegion.setInitialSize(100 * 1024 * 1024);storageCfg.setDefaultDataRegionConfiguration(defaultRegion);
// 40MB memory region with eviction enabled.
DataRegionConfiguration regionWithEviction = new DataRegionConfiguration();
regionWithEviction.setName("40MB_Region_Eviction");
regionWithEviction.setInitialSize(20 * 1024 * 1024);
regionWithEviction.setMaxSize(40 * 1024 * 1024);
regionWithEviction.setPageEvictionMode(DataPageEvictionMode.RANDOM_2_LRU);storageCfg.setDataRegionConfigurations(regionWithEviction);IgniteConfiguration cfg = new IgniteConfiguration();cfg.setDataStorageConfiguration(storageCfg);CacheConfiguration cache1 = new CacheConfiguration("SampleCache");
//this cache will be hosted in the "40MB_Region_Eviction" data region
cache1.setDataRegionName("40MB_Region_Eviction");cfg.setCacheConfiguration(cache1);// Start the node.
Ignite ignite = Ignition.start(cfg);

#2.4.緩存預(yù)熱策略

集群?jiǎn)?dòng)組網(wǎng)成功之后,Ignite本身并不需要對(duì)內(nèi)存進(jìn)行預(yù)熱,應(yīng)用就可以在其上執(zhí)行計(jì)算和查詢(xún)。但是對(duì)于需要低延遲的系統(tǒng),還是希望在查詢(xún)數(shù)據(jù)之前先將數(shù)據(jù)加載到內(nèi)存中的。

當(dāng)前,Ignite的預(yù)熱策略是從索引開(kāi)始,將數(shù)據(jù)加載到所有或者指定的數(shù)據(jù)區(qū),直到用完可用空間為止??梢詾樗械臄?shù)據(jù)區(qū)進(jìn)行配置(默認(rèn)),也可以單獨(dú)為某個(gè)數(shù)據(jù)區(qū)進(jìn)行配置。

要預(yù)熱所有數(shù)據(jù)區(qū),需將配置參數(shù)LoadAllWarmUpStrategy傳遞給DataStorageConfiguration#setDefaultWarmUpConfiguration,如下所示:

  • XML
  • Java
IgniteConfiguration cfg = new IgniteConfiguration();DataStorageConfiguration storageCfg = new DataStorageConfiguration();//Changing the default warm-up strategy for all data regions
storageCfg.setDefaultWarmUpConfiguration(new LoadAllWarmUpConfiguration());cfg.setDataStorageConfiguration(storageCfg);

要預(yù)熱某個(gè)數(shù)據(jù)區(qū),需將配置參數(shù)LoadAllWarmUpStrategy傳遞給DataStorageConfiguration#setWarmUpConfiguration,如下所示:

  • XML
  • Java
IgniteConfiguration cfg = new IgniteConfiguration();DataStorageConfiguration storageCfg = new DataStorageConfiguration();//Setting another warm-up strategy for a custom data region
DataRegionConfiguration myNewDataRegion = new DataRegionConfiguration();myNewDataRegion.setName("NewDataRegion");//You can tweak the initial size as well as other settings
myNewDataRegion.setInitialSize(100 * 1024 * 1024);//Performing data loading from disk in DRAM on restarts.
myNewDataRegion.setWarmUpConfiguration(new LoadAllWarmUpConfiguration());//Enabling Ignite persistence. Ignite reads data from disk when queried for tables/caches from this region.
myNewDataRegion.setPersistenceEnabled(true);//Applying the configuration.
storageCfg.setDataRegionConfigurations(myNewDataRegion);cfg.setDataStorageConfiguration(storageCfg);

要停止預(yù)熱所有數(shù)據(jù)區(qū),請(qǐng)將配置參數(shù)NoOpWarmUpStrategy傳遞給DataStorageConfiguration#setDefaultWarmUpConfiguration,如下所示:

  • XML
  • Java
IgniteConfiguration cfg = new IgniteConfiguration();DataStorageConfiguration storageCfg = new DataStorageConfiguration();storageCfg.setDefaultWarmUpConfiguration(new NoOpWarmUpConfiguration());cfg.setDataStorageConfiguration(storageCfg);

要停止預(yù)熱某個(gè)數(shù)據(jù)區(qū),請(qǐng)將配置參數(shù)NoOpWarmUpStrategy傳遞給DataStorageConfiguration#setWarmUpConfiguration,如下所示:

  • XML
  • Java
IgniteConfiguration cfg = new IgniteConfiguration();DataStorageConfiguration storageCfg = new DataStorageConfiguration();//Setting another warm-up strategy for a custom data region
DataRegionConfiguration myNewDataRegion = new DataRegionConfiguration();myNewDataRegion.setName("NewDataRegion");//You can tweak the initial size as well as other settings
myNewDataRegion.setInitialSize(100 * 1024 * 1024);//Skip data loading from disk in DRAM on restarts.
myNewDataRegion.setWarmUpConfiguration(new NoOpWarmUpConfiguration());//Enabling Ignite persistence. Ignite reads data from disk when queried for tables/caches from this region.
myNewDataRegion.setPersistenceEnabled(true);//Applying the configuration.
storageCfg.setDataRegionConfigurations(myNewDataRegion);cfg.setDataStorageConfiguration(storageCfg);

還可以使用control.sh和JMX停止緩存預(yù)熱過(guò)程。

要使用control.sh停止預(yù)熱:

  • Linux
  • Windows
control.sh --warm-up --stop --yes

要使用JMX停止預(yù)熱,可使用下面的方法:

org.apache.ignite.mxbean.WarmUpMXBean#stopWarmUp

#3.退出策略

如果關(guān)閉了Ignite原生持久化,Ignite會(huì)在堆外內(nèi)存中存儲(chǔ)所有的緩存條目,當(dāng)有新的數(shù)據(jù)注入,會(huì)進(jìn)行頁(yè)面的分配。如果達(dá)到了內(nèi)存的限制,Ignite無(wú)法分配頁(yè)面時(shí),部分?jǐn)?shù)據(jù)就必須從內(nèi)存中刪除以避免內(nèi)存溢出,這個(gè)過(guò)程叫做退出,退出保證系統(tǒng)不會(huì)內(nèi)存溢出,但是代價(jià)是內(nèi)存數(shù)據(jù)丟失以及如果需要數(shù)據(jù)還需要重新加載。

退出策略用于下面的場(chǎng)景:

  • 關(guān)閉原生持久化之后的堆外內(nèi)存;
  • 整合外部存儲(chǔ)后的堆外內(nèi)存;
  • 堆內(nèi)緩存;
  • 近緩存(如果啟用)。

如果開(kāi)啟了原生持久化,當(dāng)Ignite無(wú)法分配新的頁(yè)面時(shí),會(huì)有一個(gè)叫做頁(yè)面替換的簡(jiǎn)單過(guò)程來(lái)進(jìn)行堆外內(nèi)存的釋放,不同點(diǎn)在于數(shù)據(jù)并沒(méi)有丟失(因?yàn)槠浯鎯?chǔ)于持久化存儲(chǔ)),因此不用擔(dān)心數(shù)據(jù)丟失,而要關(guān)注效率。頁(yè)面替換由Ignite自動(dòng)處理,用戶(hù)無(wú)法進(jìn)行配置。

#3.1.堆外內(nèi)存退出

堆外內(nèi)存退出的實(shí)現(xiàn)方式如下:

當(dāng)內(nèi)存使用超過(guò)預(yù)設(shè)限制時(shí),Ignite使用預(yù)配置的算法之一來(lái)選擇最適合退出的內(nèi)存頁(yè)面。然后將頁(yè)面中的每個(gè)緩存條目從頁(yè)面中刪除,但是會(huì)保留被事務(wù)鎖定的條目。因此,整個(gè)頁(yè)面或大塊頁(yè)面都是空的,可以再次使用。

堆外內(nèi)存的退出默認(rèn)是關(guān)閉的,這意味著內(nèi)存使用量會(huì)一直增長(zhǎng)直到達(dá)到限值。如果要開(kāi)啟退出,需要在數(shù)據(jù)區(qū)配置中指定頁(yè)面退出模式。注意堆外內(nèi)存退出是數(shù)據(jù)區(qū)級(jí)的,如果沒(méi)使用數(shù)據(jù)區(qū),那么需要給默認(rèn)的數(shù)據(jù)區(qū)顯式地增加參數(shù)來(lái)配置退出。

默認(rèn)情況下,當(dāng)某個(gè)數(shù)據(jù)區(qū)的內(nèi)存消耗量達(dá)到90%時(shí),退出就開(kāi)始了,如果希望更早或者更晚地發(fā)起退出,可以配置DataRegionConfiguration.setEvictionThreshold(...)參數(shù)。

Ignite支持兩種頁(yè)面選擇算法:

  • Random-LRU
  • Random-2-LRU

兩者的不同下面會(huì)說(shuō)明。

#3.1.1.Random-LRU

要啟用Random-LRU退出算法,配置方式如下所示;

  • XML
  • Java
  • C#/.NET
// Node configuration.
IgniteConfiguration cfg = new IgniteConfiguration();// Memory configuration.
DataStorageConfiguration storageCfg = new DataStorageConfiguration();// Creating a new data region.
DataRegionConfiguration regionCfg = new DataRegionConfiguration();// Region name.
regionCfg.setName("20GB_Region");// 500 MB initial size (RAM).
regionCfg.setInitialSize(500L * 1024 * 1024);// 20 GB max size (RAM).
regionCfg.setMaxSize(20L * 1024 * 1024 * 1024);// Enabling RANDOM_LRU eviction for this region.
regionCfg.setPageEvictionMode(DataPageEvictionMode.RANDOM_LRU);// Setting the data region configuration.
storageCfg.setDataRegionConfigurations(regionCfg);// Applying the new configuration.
cfg.setDataStorageConfiguration(storageCfg);

Random-LRU算法工作方式如下:

  • 當(dāng)一個(gè)數(shù)據(jù)區(qū)配置了內(nèi)存策略時(shí),就會(huì)分配一個(gè)堆外數(shù)組,它會(huì)跟蹤每個(gè)數(shù)據(jù)頁(yè)面的最后使用時(shí)間戳;
  • 當(dāng)數(shù)據(jù)頁(yè)面被訪問(wèn)時(shí),跟蹤數(shù)組的時(shí)間戳就會(huì)被更新;
  • 當(dāng)?shù)搅送顺鲰?yè)面時(shí)間時(shí),算法會(huì)從跟蹤數(shù)組中隨機(jī)地選擇5個(gè)索引,然后退出最近的時(shí)間戳對(duì)應(yīng)的頁(yè)面,如果部分索引指向非數(shù)據(jù)頁(yè)面(索引或者系統(tǒng)頁(yè)面),算法會(huì)選擇其它的頁(yè)面。
#3.1.2.Random-2-LRU

Random-2-LRU退出算法是Random-LRU算法的抗掃描版,配置方式如下所示:

  • XML
  • Java
  • C#/.NET
// Ignite configuration.
IgniteConfiguration cfg = new IgniteConfiguration();// Memory configuration.
DataStorageConfiguration storageCfg = new DataStorageConfiguration();// Creating a new data region.
DataRegionConfiguration regionCfg = new DataRegionConfiguration();// Region name.
regionCfg.setName("20GB_Region");// 500 MB initial size (RAM).
regionCfg.setInitialSize(500L * 1024 * 1024);// 20 GB max size (RAM).
regionCfg.setMaxSize(20L * 1024 * 1024 * 1024);// Enabling RANDOM_2_LRU eviction for this region.
regionCfg.setPageEvictionMode(DataPageEvictionMode.RANDOM_2_LRU);// Setting the data region configuration.
storageCfg.setDataRegionConfigurations(regionCfg);// Applying the new configuration.
cfg.setDataStorageConfiguration(storageCfg);

在Random-2-LRU算法中,每個(gè)數(shù)據(jù)頁(yè)面會(huì)存儲(chǔ)兩個(gè)最近訪問(wèn)時(shí)間戳,退出時(shí),算法會(huì)隨機(jī)地從跟蹤數(shù)組中選擇5個(gè)索引值,然后兩個(gè)最近時(shí)間戳中的最小值會(huì)被用來(lái)和另外4個(gè)候選頁(yè)面中的最小值進(jìn)行比較。

Random-2-LRU比Random-LRU要好,因?yàn)樗鉀Q了曇花一現(xiàn)的問(wèn)題,即一個(gè)頁(yè)面很少被訪問(wèn),但是偶然地被訪問(wèn)了一次,然后就會(huì)被退出策略保護(hù)很長(zhǎng)時(shí)間。

#3.2.堆內(nèi)緩存退出

關(guān)于如何為堆內(nèi)緩存配置退出策略的介紹,請(qǐng)參見(jiàn)堆內(nèi)緩存配置退出策略章節(jié)的內(nèi)容。

配置持久化

#1.Ignite持久化

#1.1.概述

Ignite持久化,或者說(shuō)原生持久化,是旨在提供持久化存儲(chǔ)的一組功能。啟用后,Ignite會(huì)將所有數(shù)據(jù)存儲(chǔ)在磁盤(pán)上,并將盡可能多的數(shù)據(jù)加載到內(nèi)存中進(jìn)行處理。例如,如果有100個(gè)條目,而內(nèi)存僅能存儲(chǔ)20個(gè),則所有100個(gè)都存儲(chǔ)在磁盤(pán)上,而內(nèi)存中僅緩存20個(gè),以獲得更好的性能。

如果關(guān)閉原生持久化并且不使用任何外部存儲(chǔ)時(shí),Ignite就是一個(gè)純內(nèi)存存儲(chǔ)。

啟用持久化后,每個(gè)服務(wù)端節(jié)點(diǎn)只會(huì)存儲(chǔ)整個(gè)數(shù)據(jù)的一個(gè)子集,即只包含分配給該節(jié)點(diǎn)的分區(qū)(如果啟用了備份,也包括備份分區(qū))。

原生持久化基于以下特性:

  • 在磁盤(pán)上存儲(chǔ)數(shù)據(jù)分區(qū);
  • 預(yù)寫(xiě)日志;
  • 檢查點(diǎn);
  • 操作系統(tǒng)交換的使用。

啟用持久化后,Ignite會(huì)將每個(gè)分區(qū)存儲(chǔ)在磁盤(pán)上的單獨(dú)文件中,分區(qū)文件的數(shù)據(jù)格式與保存在內(nèi)存中的數(shù)據(jù)格式相同。如果啟用了分區(qū)備份,則也會(huì)保存在磁盤(pán)上,除了數(shù)據(jù)分區(qū),Ignite還存儲(chǔ)索引和元數(shù)據(jù)。

可以在配置中修改數(shù)據(jù)文件的默認(rèn)位置。

#1.2.啟用持久化存儲(chǔ)

原生持久化是配置在數(shù)據(jù)區(qū)上的。要啟用持久化存儲(chǔ),需要在數(shù)據(jù)區(qū)配置中將persistenceEnabled屬性設(shè)置為true,可以同時(shí)有純內(nèi)存數(shù)據(jù)區(qū)和持久化數(shù)據(jù)區(qū)。

以下是如何為默認(rèn)數(shù)據(jù)區(qū)啟用持久化存儲(chǔ)的示例:

  • XML
  • Java
  • C#/.NET
IgniteConfiguration cfg = new IgniteConfiguration();//data storage configuration
DataStorageConfiguration storageCfg = new DataStorageConfiguration();storageCfg.getDefaultDataRegionConfiguration().setPersistenceEnabled(true);cfg.setDataStorageConfiguration(storageCfg);Ignite ignite = Ignition.start(cfg);

#1.3.配置持久化存儲(chǔ)目錄

啟用持久化之后,節(jié)點(diǎn)就會(huì)在{IGNITE_WORK_DIR}/db目錄中存儲(chǔ)用戶(hù)的數(shù)據(jù)、索引和WAL文件,該目錄稱(chēng)為存儲(chǔ)目錄。通過(guò)配置DataStorageConfigurationstoragePath屬性可以修改存儲(chǔ)目錄。

每個(gè)節(jié)點(diǎn)都會(huì)在存儲(chǔ)目錄下維護(hù)一個(gè)子目錄樹(shù),來(lái)存儲(chǔ)緩存數(shù)據(jù)、WAL文件和WAL存檔文件。

子目錄名描述
{WORK_DIR}/db/{nodeId}該目錄中包括了緩存的數(shù)據(jù)和索引
{WORK_DIR}/db/wal/{nodeId}該目錄中包括了WAL文件
{WORK_DIR}/db/wal/archive/{nodeId}該目錄中包括了WAL存檔文件

這里的nodeId要么是節(jié)點(diǎn)的一致性ID(如果在節(jié)點(diǎn)配置中定義)要么是自動(dòng)生成的節(jié)點(diǎn)ID,它用于確保節(jié)點(diǎn)目錄的唯一性。如果多個(gè)節(jié)點(diǎn)共享同一工作目錄,則它們將使用不同的子目錄。

如果工作目錄包含多個(gè)節(jié)點(diǎn)的持久化文件(存在多個(gè)具有不同nodeId{nodeId}子目錄),則該節(jié)點(diǎn)將選擇第一個(gè)未使用的子目錄。為了確保節(jié)點(diǎn)即使重啟也始終使用固定的子目錄,即指定數(shù)據(jù)分區(qū),需要在節(jié)點(diǎn)配置中將IgniteConfiguration.setConsistentId設(shè)置為集群范圍內(nèi)的唯一值。

修改存儲(chǔ)目錄的代碼如下所示:

  • XML
  • Java
  • C#/.NET
IgniteConfiguration cfg = new IgniteConfiguration();//data storage configuration
DataStorageConfiguration storageCfg = new DataStorageConfiguration();storageCfg.getDefaultDataRegionConfiguration().setPersistenceEnabled(true);storageCfg.setStoragePath("/opt/storage");cfg.setDataStorageConfiguration(storageCfg);Ignite ignite = Ignition.start(cfg);

還可以將WAL和WAL存檔路徑指向存儲(chǔ)目錄之外的目錄。詳細(xì)信息后面章節(jié)會(huì)介紹。

#1.4.預(yù)寫(xiě)日志

預(yù)寫(xiě)日志是節(jié)點(diǎn)上發(fā)生的所有數(shù)據(jù)修改操作(包括刪除)的日志。在內(nèi)存中更新頁(yè)面時(shí),更新不會(huì)直接寫(xiě)入分區(qū)文件,而是會(huì)附加到WAL的末尾。

預(yù)寫(xiě)日志的目的是為單個(gè)節(jié)點(diǎn)或整個(gè)集群的故障提供一個(gè)恢復(fù)機(jī)制。如果發(fā)生故障或重啟,則可以依靠WAL的內(nèi)容將集群恢復(fù)到最近成功提交的事務(wù)。

WAL由幾個(gè)文件(稱(chēng)為活動(dòng)段)和一個(gè)存檔組成?;顒?dòng)段按順序填充,然后循環(huán)覆蓋。第一個(gè)段寫(xiě)滿后,其內(nèi)容將復(fù)制到WAL存檔中(請(qǐng)參見(jiàn)下面的WAL存檔章節(jié))。在復(fù)制第一段時(shí),第二段會(huì)被視為激活的WAL文件,并接受來(lái)自應(yīng)用端的所有更新,活動(dòng)段默認(rèn)有10個(gè)。

#1.4.1.WAL模式

WAL模式有幾種,每種模式對(duì)性能的影響方式不同,并提供不同的一致性保證:

WAL模式描述一致性保證
FSYNC保證每個(gè)原子寫(xiě)或者事務(wù)性提交都會(huì)持久化到磁盤(pán)。數(shù)據(jù)更新不會(huì)丟失,不管是任何的操作系統(tǒng)或者進(jìn)程故障,甚至是電源故障。
LOG_ONLY默認(rèn)模式,對(duì)于每個(gè)原子寫(xiě)或者事務(wù)性提交,保證會(huì)刷新到操作系統(tǒng)的緩沖區(qū)緩存或者內(nèi)存映射文件。默認(rèn)會(huì)使用內(nèi)存映射文件方式,并且可以通過(guò)將IGNITE_WAL_MMAP系統(tǒng)屬性配置為false將其關(guān)閉。如果僅僅是進(jìn)程崩潰數(shù)據(jù)更新會(huì)保留。
BACKGROUND如果打開(kāi)了IGNITE_WAL_MMAP屬性(默認(rèn)),該模式的行為類(lèi)似于LOG_ONLY模式,如果關(guān)閉了內(nèi)存映射文件方式,變更會(huì)保持在節(jié)點(diǎn)的內(nèi)部緩沖區(qū),緩沖區(qū)刷新到磁盤(pán)的頻率由walFlushFrequency參數(shù)定義。如果打開(kāi)了IGNITE_WAL_MMAP屬性(默認(rèn)),該模式提供了與LOG_ONLY模式一樣的保證,否則如果進(jìn)程故障或者其它的故障發(fā)生時(shí),最近的數(shù)據(jù)更新可能丟失。
NONEWAL被禁用,只有在節(jié)點(diǎn)優(yōu)雅地關(guān)閉時(shí),變更才會(huì)正常持久化,使用Ignite#active(false)可以?xún)鼋Y(jié)集群然后停止節(jié)點(diǎn)。可能出現(xiàn)數(shù)據(jù)丟失,如果節(jié)點(diǎn)在更新操作期間突然終止,則磁盤(pán)上存儲(chǔ)的數(shù)據(jù)很可能出現(xiàn)不同步或損壞。
#1.4.2.WAL存檔

WAL存檔用于保存故障后恢復(fù)節(jié)點(diǎn)所需的WAL段。存檔中保存的段的數(shù)量應(yīng)確保所有段的總大小不超過(guò)WAL存檔的既定大小。

WAL存檔的最大大小(在磁盤(pán)上占用的總空間)定義為檢查點(diǎn)緩沖區(qū)大小的4倍,可以在配置中更改該值。

警告

將WAL存檔大小配置為小于默認(rèn)值可能影響性能,用于生產(chǎn)之前需要進(jìn)行測(cè)試。

#1.4.3.修改WAL段大小

在高負(fù)載情況下,默認(rèn)的WAL段大小(64MB)可能效率不高,因?yàn)樗鼤?huì)導(dǎo)致WAL過(guò)于頻繁地在段之間切換,并且切換/輪轉(zhuǎn)是一項(xiàng)昂貴的操作。更大的WAL段大小有助于提高高負(fù)載下的性能,但代價(jià)是增加WAL文件和WAL存檔文件的總大小。

可以在數(shù)據(jù)存儲(chǔ)配置中更改WAL段文件的大小,該值必須介于512KB和2GB之間。

  • XML
  • Java
IgniteConfiguration cfg = new IgniteConfiguration();
DataStorageConfiguration storageCfg = new DataStorageConfiguration();
storageCfg.getDefaultDataRegionConfiguration().setPersistenceEnabled(true);storageCfg.setWalSegmentSize(128 * 1024 * 1024);cfg.setDataStorageConfiguration(storageCfg);Ignite ignite = Ignition.start(cfg);
#1.4.4.禁用WAL

警告

禁用或啟用WAL只能在穩(wěn)定的拓?fù)渖线M(jìn)行:即所有基線節(jié)點(diǎn)都應(yīng)該在線,在此操作期間不應(yīng)該有節(jié)點(diǎn)加入或離開(kāi)集群。否則,緩存可能會(huì)陷入不一致?tīng)顟B(tài)。如果發(fā)生這種情況,建議銷(xiāo)毀受影響的緩存。

在某些情況下,禁用WAL以獲得更好的性能是合理的做法。例如,在初始數(shù)據(jù)加載期間禁用WAL并在預(yù)加載完成后啟用WAL就是個(gè)好的做法。

  • Java
  • C#/.NET
  • SQL
IgniteConfiguration cfg = new IgniteConfiguration();
DataStorageConfiguration storageCfg = new DataStorageConfiguration();
storageCfg.getDefaultDataRegionConfiguration().setPersistenceEnabled(true);cfg.setDataStorageConfiguration(storageCfg);Ignite ignite = Ignition.start(cfg);ignite.cluster().state(ClusterState.ACTIVE);String cacheName = "myCache";ignite.getOrCreateCache(cacheName);ignite.cluster().disableWal(cacheName);//load data
ignite.cluster().enableWal(cacheName);

警告

如果禁用WAL并重啟節(jié)點(diǎn),則將從該節(jié)點(diǎn)上的持久化存儲(chǔ)中刪除所有數(shù)據(jù)。之所以這樣實(shí)現(xiàn),是因?yàn)槿绻麤](méi)有WAL,則無(wú)法保證節(jié)點(diǎn)故障或重啟時(shí)的數(shù)據(jù)一致性。

#1.4.5.WAL存檔壓縮

可以啟用WAL存檔壓縮以減少WAL存檔占用的空間。WAL存檔默認(rèn)包含最后20個(gè)檢查點(diǎn)的段(此數(shù)字是可配置的)。啟用壓縮后,則將所有1個(gè)檢查點(diǎn)之前的已存檔段壓縮為ZIP格式,如果需要這些段(例如在節(jié)點(diǎn)之間再平衡數(shù)據(jù)),則會(huì)將其解壓縮為原始格式。

關(guān)于如何啟用WAL存檔壓縮,請(qǐng)參見(jiàn)下面的配置屬性章節(jié)。

#1.4.6.WAL記錄壓縮

如設(shè)計(jì)文檔中所述,在確認(rèn)用戶(hù)操作之前,代表數(shù)據(jù)更新的物理和邏輯記錄已寫(xiě)入WAL文件,Ignite可以先將WAL記錄壓縮到內(nèi)存中,然后再寫(xiě)入磁盤(pán)以節(jié)省空間。

WAL記錄壓縮要求引入ignite-compress模塊,具體請(qǐng)參見(jiàn)啟用模塊。

WAL記錄壓縮默認(rèn)是禁用的,如果要啟用,需要在數(shù)據(jù)存儲(chǔ)配置中設(shè)置壓縮算法和壓縮級(jí)別:

IgniteConfiguration cfg = new IgniteConfiguration();DataStorageConfiguration dsCfg = new DataStorageConfiguration();
dsCfg.getDefaultDataRegionConfiguration().setPersistenceEnabled(true);//WAL page compression parameters
dsCfg.setWalPageCompression(DiskPageCompression.LZ4);
dsCfg.setWalPageCompressionLevel(8);cfg.setDataStorageConfiguration(dsCfg);
Ignite ignite = Ignition.start(cfg);

DiskPageCompression中列出了支持的壓縮算法。

#1.4.7.禁用WAL存檔

有時(shí)可能想要禁用WAL存檔,比如減少與將WAL段復(fù)制到存檔文件有關(guān)的開(kāi)銷(xiāo),當(dāng)Ignite將數(shù)據(jù)寫(xiě)入WAL段的速度快于將段復(fù)制到存檔文件的速度時(shí),這樣做就有用,因?yàn)檫@樣會(huì)導(dǎo)致I/O瓶頸,從而凍結(jié)節(jié)點(diǎn)的操作,如果遇到了這樣的問(wèn)題,就可以嘗試關(guān)閉WAL存檔。

通過(guò)將WAL路徑和WAL存檔路徑配置為同一個(gè)值,可以關(guān)閉存檔。這時(shí)Ignite就不會(huì)將段復(fù)制到存檔文件,而是只是在WAL文件夾中創(chuàng)建新的段。根據(jù)WAL存檔大小設(shè)置,舊段將隨著WAL的增長(zhǎng)而刪除。

#1.5.檢查點(diǎn)

檢查點(diǎn)是一個(gè)將臟頁(yè)面從內(nèi)存復(fù)制到磁盤(pán)上的分區(qū)文件的過(guò)程,臟頁(yè)面是指頁(yè)面已經(jīng)在內(nèi)存中進(jìn)行了更新但是還沒(méi)有寫(xiě)入對(duì)應(yīng)的分區(qū)文件(只是添加到了WAL中)。

創(chuàng)建檢查點(diǎn)后,所有更改都將保存到磁盤(pán),并且在節(jié)點(diǎn)故障并重啟后將生效。

檢查點(diǎn)和預(yù)寫(xiě)日志旨在確保數(shù)據(jù)的持久化和節(jié)點(diǎn)故障時(shí)的恢復(fù)能力。

這個(gè)過(guò)程通過(guò)在磁盤(pán)上保持頁(yè)面的最新?tīng)顟B(tài)而節(jié)省更多的磁盤(pán)空間,檢查點(diǎn)完成后,就可以在WAL存檔中刪除檢查點(diǎn)執(zhí)行前創(chuàng)建的WAL段。

具體請(qǐng)參見(jiàn)相關(guān)的文檔:

  • 檢查點(diǎn)操作監(jiān)控;
  • 調(diào)整檢查點(diǎn)緩沖區(qū)大小。

#1.6.配置屬性

下表列出了DataStorageConfiguration的主要參數(shù):

屬性名描述默認(rèn)值
persistenceEnabled將該屬性配置為true可以開(kāi)啟原生持久化。false
storagePath數(shù)據(jù)存儲(chǔ)路徑。${IGNITE_HOME}/work/db/node{IDX}-{UUID}
walPathWAL活動(dòng)段存儲(chǔ)路徑。${IGNITE_HOME}/work/db/wal/
walArchivePathWAL存檔路徑。${IGNITE_HOME}/work/db/wal/archive/
walCompactionEnabled將該屬性配置為true可以開(kāi)啟WAL存檔壓縮。false
walSegmentSizeWAL段文件大小(字節(jié))。64MB
walMode預(yù)寫(xiě)日志模式。LOG_ONLY
walCompactionLevelWAL壓縮級(jí)別,1表示速度最快,9表示最高的壓縮率。1
maxWalArchiveSizeWAL存檔占用空間最大值(字節(jié))。檢查點(diǎn)緩沖區(qū)大小的4倍

#2.外部存儲(chǔ)

#2.1.概述

Ignite可以做為已有數(shù)據(jù)庫(kù)之上的一個(gè)緩存層,包括RDBMS或者NoSQL數(shù)據(jù)庫(kù),比如Apache Cassandra或者M(jìn)ongoDB等,該場(chǎng)景通過(guò)內(nèi)存計(jì)算來(lái)對(duì)底層數(shù)據(jù)庫(kù)進(jìn)行加速。

Ignite可以與Apache Cassandra直接集成,但是暫時(shí)還不支持其他NoSQL數(shù)據(jù)庫(kù),但是開(kāi)發(fā)自己的CacheStore接口實(shí)現(xiàn)。

使用外部存儲(chǔ)的兩個(gè)主要場(chǎng)景是:

  • 作為已有數(shù)據(jù)庫(kù)的緩存層,這時(shí)可以通過(guò)將數(shù)據(jù)加載到內(nèi)存來(lái)優(yōu)化處理速度,還可以為不支持SQL的數(shù)據(jù)庫(kù)帶來(lái)SQL支持能力(數(shù)據(jù)全部加載到內(nèi)存);
  • 希望將數(shù)據(jù)持久化到外部數(shù)據(jù)庫(kù)(而不是單一的原生持久化)。

CacheStore接口同時(shí)擴(kuò)展了javax.cache.integration.CacheLoaderjavax.cache.integration.CacheWriter,相對(duì)應(yīng)的分別用于通讀通寫(xiě)。也可以單獨(dú)實(shí)現(xiàn)每個(gè)接口,然后在緩存配置中單獨(dú)配置。

提示

除了鍵-值操作,Ignite的通寫(xiě)也支持SQL的INSERT、UPDATE和MERGE,但是SELECT查詢(xún)語(yǔ)句不會(huì)從外部數(shù)據(jù)庫(kù)通讀數(shù)據(jù)。

#2.1.1.通讀和通寫(xiě)

通讀是指如果緩存中不存在,則從底層持久化存儲(chǔ)中讀取數(shù)據(jù)。注意這僅適用于通過(guò)鍵-值A(chǔ)PI進(jìn)行的get操作,SELECT查詢(xún)不會(huì)從外部數(shù)據(jù)庫(kù)查詢(xún)數(shù)據(jù)。要執(zhí)行SELECT查詢(xún),必須通過(guò)調(diào)用loadCache()方法將數(shù)據(jù)從數(shù)據(jù)庫(kù)預(yù)加載到緩存中。

通寫(xiě)是指數(shù)據(jù)在緩存中更新后會(huì)自動(dòng)持久化。所有的通讀和通寫(xiě)操作都參與緩存事務(wù),然后作為整體提交或回滾。

#2.1.2.后寫(xiě)緩存

在一個(gè)簡(jiǎn)單的通寫(xiě)模式中每個(gè)緩存的putremove操作都會(huì)涉及一個(gè)持久化存儲(chǔ)的請(qǐng)求,因此整個(gè)緩存更新的持續(xù)時(shí)間可能是相對(duì)比較長(zhǎng)的。另外,密集的緩存更新頻率也會(huì)導(dǎo)致非常高的存儲(chǔ)負(fù)載。

對(duì)于這種情況,可以啟用后寫(xiě)模式,它會(huì)以異步的方式執(zhí)行更新操作。這個(gè)方式的主要概念是累積更新操作然后作為一個(gè)批量異步刷入持久化存儲(chǔ)。數(shù)據(jù)的刷新可以基于時(shí)間的事件(數(shù)據(jù)條目駐留在隊(duì)列中的時(shí)間是有限的)來(lái)觸發(fā),也可以基于隊(duì)列大小的事件(如果隊(duì)列大小達(dá)到限值,會(huì)被刷新)觸發(fā),或者兩者(先發(fā)生者優(yōu)先)。

性能和一致性

啟用后寫(xiě)緩存可以通過(guò)異步更新來(lái)提高性能,但這可能會(huì)導(dǎo)致一致性下降,因?yàn)槟承└驴赡苡捎诠?jié)點(diǎn)故障或崩潰而丟失。

對(duì)于后寫(xiě)的方式只有數(shù)據(jù)的最后一次更新會(huì)被寫(xiě)入底層存儲(chǔ)。如果鍵為key1的緩存數(shù)據(jù)分別被依次更新為值value1、value2value3,那么只有(key1,value3)對(duì)這一個(gè)存儲(chǔ)請(qǐng)求會(huì)被傳播到持久化存儲(chǔ)。

更新性能

批量的存儲(chǔ)操作通常比按順序的單一操作更有效率,因此可以通過(guò)開(kāi)啟后寫(xiě)模式的批量操作來(lái)利用這個(gè)特性。簡(jiǎn)單類(lèi)型(putremove)的簡(jiǎn)單順序更新操作可以被組合成一個(gè)批量操作。比如,連續(xù)地往緩存中寫(xiě)入(key1,value1)、(key2,value2)、(key3,value3)可以通過(guò)一個(gè)單一的CacheStore.putAll(...)操作批量處理。

#2.2.RDBMS集成

要將RDBMS作為底層存儲(chǔ),可以使用下面的CacheStore實(shí)現(xiàn)之一:

  • CacheJdbcPojoStore:使用反射將對(duì)象存儲(chǔ)為一組字段,如果在現(xiàn)有數(shù)據(jù)庫(kù)之上添加Ignite并希望使用底層表中的部分字段或所有字段,請(qǐng)使用此實(shí)現(xiàn);
  • CacheJdbcBlobStore:將對(duì)象以Blob格式存儲(chǔ)在底層數(shù)據(jù)庫(kù)中,當(dāng)將外部數(shù)據(jù)庫(kù)作為持久化存儲(chǔ)并希望以簡(jiǎn)單格式存儲(chǔ)數(shù)據(jù)時(shí),可以用此實(shí)現(xiàn)。

下面是CacheStore兩種實(shí)現(xiàn)的配置示例:

#2.2.1.CacheJdbcPojoStore

使用CacheJdbcPojoStore,可以將對(duì)象存儲(chǔ)為一組字段,并可以配置表列和對(duì)象字段之間的映射。

  1. CacheConfiguration.cacheStoreFactory屬性設(shè)置為org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreFactory并提供以下屬性:

    • dataSourceBean:數(shù)據(jù)庫(kù)連接憑據(jù):URL、用戶(hù)、密碼;
    • dialect:實(shí)現(xiàn)與數(shù)據(jù)庫(kù)兼容的SQL方言的類(lèi)。Ignite為MySQL、Oracle、H2、SQLServer和DB2數(shù)據(jù)庫(kù)提供了現(xiàn)成的實(shí)現(xiàn)。這些方言位于org.apache.ignite.cache.store.jdbc.dialect包中;
    • types:此屬性用于定義數(shù)據(jù)庫(kù)表和相應(yīng)的POJO之間的映射(請(qǐng)參見(jiàn)下面的POJO配置示例)。
  2. (可選)如果要在緩存上執(zhí)行SQL查詢(xún),請(qǐng)配置查詢(xún)實(shí)體。

以下示例演示了如何在MySQL表之上配置Ignite緩存。該映射到Person類(lèi)對(duì)象的表有2列:id(INTEGER)name(VARCHAR)。

可以通過(guò)XML或Java代碼配置CacheJdbcPojoStore

  • XML
  • Java
IgniteConfiguration igniteCfg = new IgniteConfiguration();CacheConfiguration<Integer, Person> personCacheCfg = new CacheConfiguration<>();personCacheCfg.setName("PersonCache");
personCacheCfg.setCacheMode(CacheMode.PARTITIONED);
personCacheCfg.setAtomicityMode(CacheAtomicityMode.ATOMIC);personCacheCfg.setReadThrough(true);
personCacheCfg.setWriteThrough(true);CacheJdbcPojoStoreFactory<Integer, Person> factory = new CacheJdbcPojoStoreFactory<>();
factory.setDialect(new MySQLDialect());
factory.setDataSourceFactory((Factory<DataSource>)() -> {MysqlDataSource mysqlDataSrc = new MysqlDataSource();mysqlDataSrc.setURL("jdbc:mysql://[host]:[port]/[database]");mysqlDataSrc.setUser("YOUR_USER_NAME");mysqlDataSrc.setPassword("YOUR_PASSWORD");return mysqlDataSrc;
});JdbcType personType = new JdbcType();
personType.setCacheName("PersonCache");
personType.setKeyType(Integer.class);
personType.setValueType(Person.class);
// Specify the schema if applicable
// personType.setDatabaseSchema("MY_DB_SCHEMA");
personType.setDatabaseTable("PERSON");personType.setKeyFields(new JdbcTypeField(java.sql.Types.INTEGER, "id", Integer.class, "id"));personType.setValueFields(new JdbcTypeField(java.sql.Types.INTEGER, "id", Integer.class, "id")),new JdbcTypeField(java.sql.Types.VARCHAR, "name", String.class, "name"));factory.setTypes(personType);personCacheCfg.setCacheStoreFactory(factory);QueryEntity qryEntity = new QueryEntity();qryEntity.setKeyType(Integer.class.getName());
qryEntity.setValueType(Person.class.getName());
qryEntity.setKeyFieldName("id");Set<String> keyFields = new HashSet<>();
keyFields.add("id");
qryEntity.setKeyFields(keyFields);LinkedHashMap<String, String> fields = new LinkedHashMap<>();
fields.put("id", "java.lang.Integer");
fields.put("name", "java.lang.String");qryEntity.setFields(fields);personCacheCfg.setQueryEntities(Collections.singletonList(qryEntity));igniteCfg.setCacheConfiguration(personCacheCfg);

Person類(lèi):

class Person implements Serializable {private static final long serialVersionUID = 0L;private int id;private String name;public Person() {}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getId() {return id;}public void setId(int id) {this.id = id;}
}
#2.2.2.CacheJdbcBlobStore

CacheJdbcBlobStore將對(duì)象以Blob格式存儲(chǔ)于底層數(shù)據(jù)庫(kù)中,它會(huì)創(chuàng)建一張表名為ENTRIES,有名為keyval的列(類(lèi)型都為binary)。

可以通過(guò)提供自定義的建表語(yǔ)句和DML語(yǔ)句,分別用于加載、更新、刪除數(shù)據(jù)來(lái)修改默認(rèn)的定義,具體請(qǐng)參見(jiàn)CacheJdbcBlobStore的javadoc。

在下面的示例中,Person類(lèi)的對(duì)象存儲(chǔ)于單一列的字節(jié)數(shù)組中。

  • XML
  • Java
IgniteConfiguration igniteCfg = new IgniteConfiguration();CacheConfiguration<Integer, Person> personCacheCfg = new CacheConfiguration<>();
personCacheCfg.setName("PersonCache");CacheJdbcBlobStoreFactory<Integer, Person> cacheStoreFactory = new CacheJdbcBlobStoreFactory<>();cacheStoreFactory.setUser("USER_NAME");MysqlDataSource mysqlDataSrc = new MysqlDataSource();
mysqlDataSrc.setURL("jdbc:mysql://[host]:[port]/[database]");
mysqlDataSrc.setUser("USER_NAME");
mysqlDataSrc.setPassword("PASSWORD");cacheStoreFactory.setDataSource(mysqlDataSrc);personCacheCfg.setCacheStoreFactory(cacheStoreFactory);personCacheCfg.setWriteThrough(true);
personCacheCfg.setReadThrough(true);igniteCfg.setCacheConfiguration(personCacheCfg);

#2.3.加載數(shù)據(jù)

緩存存儲(chǔ)配置完成并啟動(dòng)集群后,就可以使用下面的代碼從數(shù)據(jù)庫(kù)加載數(shù)據(jù)了:

// Load data from person table into PersonCache.
IgniteCache<Integer, Person> personCache = ignite.cache("PersonCache");personCache.loadCache(null);

#2.4.NoSQL數(shù)據(jù)庫(kù)集成

通過(guò)實(shí)現(xiàn)CacheStore接口,可以將Ignite與任何NoSQL數(shù)據(jù)庫(kù)集成。

警告

雖然Ignite支持分布式事務(wù),但是并不會(huì)使NoSQL數(shù)據(jù)庫(kù)具有事務(wù)性,除非數(shù)據(jù)庫(kù)本身直接支持事務(wù)。

#2.4.1.Cassandra集成

Ignite通過(guò)CacheStore實(shí)現(xiàn),直接支持將Apache Cassandra用作持久化存儲(chǔ)。其利用Cassandra的異步查詢(xún)來(lái)提供loadAll()、writeAll()deleteAll()等高性能批處理操作,并自動(dòng)在Cassandra中創(chuàng)建所有必要的表和命名空間。

具體請(qǐng)參見(jiàn)Cassandra集成章節(jié)的介紹。

#3.交換空間

#3.1.概述

如果使用純內(nèi)存存儲(chǔ),隨著數(shù)據(jù)量的大小逐步達(dá)到物理內(nèi)存大小,可能導(dǎo)致內(nèi)存溢出。如果不想使用原生持久化或者外部存儲(chǔ),還可以開(kāi)啟交換,這時(shí)Ignite會(huì)將內(nèi)存中的數(shù)據(jù)移動(dòng)到磁盤(pán)上的交換空間,注意Ignite不會(huì)提供自己的交換空間實(shí)現(xiàn),而是利用了操作系統(tǒng)(OS)提供的交換功能。

打開(kāi)交換空間之后,Ignite會(huì)將數(shù)據(jù)存儲(chǔ)在內(nèi)存映射文件(MMF)中,操作系統(tǒng)會(huì)根據(jù)內(nèi)存使用情況,將其內(nèi)容交換到磁盤(pán),但是這時(shí)數(shù)據(jù)訪問(wèn)的性能會(huì)下降。另外,還沒(méi)有數(shù)據(jù)持久性保證,這意味著交換空間中的數(shù)據(jù)只在節(jié)點(diǎn)在線期間才可用。一旦存在交換空間的節(jié)點(diǎn)停止,所有數(shù)據(jù)都會(huì)丟失。因此,應(yīng)該將交換空間作為內(nèi)存的擴(kuò)展,以留出足夠的時(shí)間向集群中添加更多的節(jié)點(diǎn)讓數(shù)據(jù)重新分布,并避免集群未及時(shí)擴(kuò)容導(dǎo)致內(nèi)存溢出的錯(cuò)誤(OOM)發(fā)生。

注意

雖然交換空間位于磁盤(pán)上,但是其不能替代原生持久化。交換空間中的數(shù)據(jù)只有在節(jié)點(diǎn)在線時(shí)才有效,一旦節(jié)點(diǎn)關(guān)閉,數(shù)據(jù)將丟失。為了確保數(shù)據(jù)一直可用,應(yīng)該啟用原生持久化或使用外部存儲(chǔ)。

#3.2.啟用交換

數(shù)據(jù)區(qū)的maxSize定義了區(qū)域的整體最大值,如果數(shù)據(jù)量達(dá)到了maxSize,然后既沒(méi)有使用原生持久化,也沒(méi)有使用外部存儲(chǔ),那么就會(huì)拋出內(nèi)存溢出異常。使用交換可以避免這種情況的發(fā)生,做法是:

  • 配置maxSize的值大于內(nèi)存大小,這時(shí)操作系統(tǒng)就會(huì)使用交換;
  • 啟用數(shù)據(jù)區(qū)的交換,如下所示。
  • XML
  • Java
  • C#/.NET
// Node configuration.
IgniteConfiguration cfg = new IgniteConfiguration();// Durable Memory configuration.
DataStorageConfiguration storageCfg = new DataStorageConfiguration();// Creating a new data region.
DataRegionConfiguration regionCfg = new DataRegionConfiguration();// Region name.
regionCfg.setName("500MB_Region");// Setting initial RAM size.
regionCfg.setInitialSize(100L * 1024 * 1024);// Setting region max size equal to physical RAM size(5 GB)
regionCfg.setMaxSize(5L * 1024 * 1024 * 1024);// Enable swap space.
regionCfg.setSwapPath("/path/to/some/directory");// Setting the data region configuration.
storageCfg.setDataRegionConfigurations(regionCfg);// Applying the new configuration.
cfg.setDataStorageConfiguration(storageCfg);

#4.實(shí)現(xiàn)自定義CacheStore

可以實(shí)現(xiàn)自己的自定義CacheStore并將其作為緩存的底層數(shù)據(jù)存儲(chǔ),IgniteCache中讀寫(xiě)數(shù)據(jù)的方法將會(huì)調(diào)用CacheStore實(shí)現(xiàn)中相應(yīng)的方法。

下表描述了CacheStore接口中的方法:

方法描述
loadCache()調(diào)用IgniteCache.loadCache(…?)時(shí),就會(huì)調(diào)用該方法,通常用于從數(shù)據(jù)庫(kù)預(yù)加載數(shù)據(jù)。此方法在駐有緩存的所有節(jié)點(diǎn)上執(zhí)行,要加載單個(gè)節(jié)點(diǎn)的數(shù)據(jù),需要在該節(jié)點(diǎn)上調(diào)用IgniteCache.localLoadCache()方法。
load()、write()、delete()當(dāng)調(diào)用IgniteCache接口的get()、put()、remove()方法時(shí),會(huì)分別調(diào)用這3個(gè)方法,這些方法用于單條數(shù)據(jù)的通讀通寫(xiě)。
loadAll()、writeAll()、deleteAll()當(dāng)調(diào)用IgniteCache接口的getAll()putAll()、removeAll()方法時(shí),會(huì)分別調(diào)用這3個(gè)方法,這些方法用于處理多條數(shù)據(jù)的通讀通寫(xiě),通常以批量的形式實(shí)現(xiàn)以提高性能。

#4.1.CacheStoreAdapter

CacheStoreAdapterCacheStore的擴(kuò)展,提供了批量操作的默認(rèn)實(shí)現(xiàn),如loadAll(Iterable)、writeAll(Collection)deleteAll(Collection),其會(huì)迭代所有條目并在每個(gè)條目上調(diào)用對(duì)應(yīng)的load()write()delete()方法。

#4.2.CacheStoreSession

CacheStoreSession用于持有多個(gè)操作之間的上下文,主要用于提供事務(wù)支持。一個(gè)事務(wù)中的多個(gè)操作是在同一個(gè)數(shù)據(jù)庫(kù)連接中執(zhí)行的,并在事務(wù)提交時(shí)提交該連接。通過(guò)@GridCacheStoreSessionResource注解可以將其注入CacheStore實(shí)現(xiàn)中。

關(guān)于如何實(shí)現(xiàn)事務(wù)化的CacheStore,可以參見(jiàn)GitHub上的示例。

#4.3.示例

下面是一個(gè)CacheStore的非事務(wù)化實(shí)現(xiàn)的示例:

public class CacheJdbcPersonStore extends CacheStoreAdapter<Long, Person> {// This method is called whenever the "get(...)" methods are called on IgniteCache.@Overridepublic Person load(Long key) {try (Connection conn = connection()) {try (PreparedStatement st = conn.prepareStatement("select * from PERSON where id=?")) {st.setLong(1, key);ResultSet rs = st.executeQuery();return rs.next() ? new Person(rs.getInt(1), rs.getString(2)) : null;}} catch (SQLException e) {throw new CacheLoaderException("Failed to load: " + key, e);}}@Overridepublic void write(Entry<? extends Long, ? extends Person> entry) throws CacheWriterException {try (Connection conn = connection()) {// Syntax of MERGE statement is database specific and should be adopted for your database.// If your database does not support MERGE statement then use sequentially// update, insert statements.try (PreparedStatement st = conn.prepareStatement("merge into PERSON (id, name) key (id) VALUES (?, ?)")) {Person val = entry.getValue();st.setLong(1, entry.getKey());st.setString(2, val.getName());st.executeUpdate();}} catch (SQLException e) {throw new CacheWriterException("Failed to write entry (" + entry + ")", e);}}// This method is called whenever the "remove(...)" method are called on IgniteCache.@Overridepublic void delete(Object key) {try (Connection conn = connection()) {try (PreparedStatement st = conn.prepareStatement("delete from PERSON where id=?")) {st.setLong(1, (Long) key);st.executeUpdate();}} catch (SQLException e) {throw new CacheWriterException("Failed to delete: " + key, e);}}// This method is called whenever the "loadCache()" and "localLoadCache()"// methods are called on IgniteCache. It is used for bulk-loading the cache.// If you don't need to bulk-load the cache, skip this method.@Overridepublic void loadCache(IgniteBiInClosure<Long, Person> clo, Object... args) {if (args == null || args.length == 0 || args[0] == null)throw new CacheLoaderException("Expected entry count parameter is not provided.");final int entryCnt = (Integer) args[0];try (Connection conn = connection()) {try (PreparedStatement st = conn.prepareStatement("select * from PERSON")) {try (ResultSet rs = st.executeQuery()) {int cnt = 0;while (cnt < entryCnt && rs.next()) {Person person = new Person(rs.getInt(1), rs.getString(2));clo.apply(person.getId(), person);cnt++;}}}} catch (SQLException e) {throw new CacheLoaderException("Failed to load values from cache store.", e);}}// Open JDBC connection.private Connection connection() throws SQLException {// Open connection to your RDBMS systems (Oracle, MySQL, Postgres, DB2, Microsoft SQL, etc.)Connection conn = DriverManager.getConnection("jdbc:mysql://[host]:[port]/[database]", "YOUR_USER_NAME", "YOUR_PASSWORD");conn.setAutoCommit(true);return conn;}
}

#5.集群快照

#5.1.概述

對(duì)于開(kāi)啟了原生持久化的集群,Ignite提供了創(chuàng)建集群完整快照的功能。一個(gè)Ignite快照包括了整個(gè)集群中所有存盤(pán)數(shù)據(jù)的完整一致副本,以及用于恢復(fù)過(guò)程必需的其他一些文件。

快照的結(jié)構(gòu)除了一些例外,類(lèi)似于Ignite原生持久化存儲(chǔ)目錄的布局,以下面的快照為例,看一下結(jié)構(gòu):

work
└── snapshots└── backup23012020└── db├── binary_meta│         ├── node1│         ├── node2│         └── node3├── marshaller│         ├── node1│         ├── node2│         └── node3├── node1│    └── my-sample-cache│        ├── cache_data.dat│        ├── part-3.bin│        ├── part-4.bin│        └── part-6.bin├── node2│    └── my-sample-cache│        ├── cache_data.dat│        ├── part-1.bin│        ├── part-5.bin│        └── part-7.bin└── node3└── my-sample-cache├── cache_data.dat├── part-0.bin└── part-2.bin
  • 快照位于work\snapshots目錄下,名為backup23012020,這里work是Ignite的工作目錄;
  • 創(chuàng)建快照的集群有3個(gè)節(jié)點(diǎn),所有節(jié)點(diǎn)都在同一臺(tái)主機(jī)上運(yùn)行。在此示例中,節(jié)點(diǎn)分別名為node1、node2node3,而實(shí)際上,它們的名字是節(jié)點(diǎn)的一致性ID;
  • 快照保留了my-sample-cache緩存的副本;
  • db文件夾在part-N.bincache_data.dat文件中保留數(shù)據(jù)記錄的副本。預(yù)寫(xiě)日志和檢查點(diǎn)不在快照中,因?yàn)檫@些在當(dāng)前的恢復(fù)過(guò)程中并不需要;
  • binary_metamarshaller目錄存儲(chǔ)了和元數(shù)據(jù)和編組器有關(guān)的信息。

通??煺辗植加谡麄€(gè)集群

上面的示例顯示為同一個(gè)集群創(chuàng)建的快照運(yùn)行于同一臺(tái)物理機(jī),因此整個(gè)快照位于一個(gè)位置上。實(shí)際上,集群中不同主機(jī)的所有節(jié)點(diǎn)上都會(huì)有快照數(shù)據(jù)。每個(gè)節(jié)點(diǎn)都持有快照的一段,即歸屬于該節(jié)點(diǎn)的數(shù)據(jù)快照,恢復(fù)過(guò)程會(huì)說(shuō)明恢復(fù)時(shí)如何將所有段合并在一起。

#5.2.配置快照目錄

快照默認(rèn)存儲(chǔ)在相應(yīng)Ignite節(jié)點(diǎn)的工作目錄中,并和Ignite持久化保存數(shù)據(jù)、索引、WAL和其他文件使用相同的存儲(chǔ)介質(zhì)。因?yàn)榭煺障牧撕统志没喈?dāng)?shù)目臻g,然后和Ignite持久化進(jìn)程共享磁盤(pán)IO,從而會(huì)影響應(yīng)用的性能,因此建議將快照和持久化文件存儲(chǔ)在不同的存儲(chǔ)介質(zhì)上。

可以通過(guò)更改持久化文件的存儲(chǔ)目錄或覆蓋快照的默認(rèn)位置來(lái)避免Ignite原生持久化和快照之間的這種干擾,如下所示:

  • XML
  • Java
IgniteConfiguration cfg = new IgniteConfiguration();File exSnpDir = U.resolveWorkDirectory(U.defaultWorkDirectory(), "ex_snapshots", true);cfg.setSnapshotPath(exSnpDir.getAbsolutePath());

#5.3.創(chuàng)建快照

Ignite提供了幾個(gè)API來(lái)進(jìn)行快照的創(chuàng)建,下面看下所有的選項(xiàng):

#5.3.1.使用控制腳本

Ignite自帶的控制腳本支持和快照有關(guān)的操作,如下所示:

#Create a cluster snapshot:
control.(sh|bat) --snapshot create snapshot_name#Cancel a running snapshot:
control.(sh|bat) --snapshot cancel snapshot_name#Kill a running snapshot:
control.(sh|bat) --kill SNAPSHOT snapshot_name
#5.3.2.使用JMX

使用SnapshotMXBean接口,可以通過(guò)JMX執(zhí)行和快照有關(guān)的過(guò)程:

方法描述
createSnapshot(String snpName)創(chuàng)建快照
createSnapshot(String snpName)在創(chuàng)建快照的發(fā)起節(jié)點(diǎn)取消快照
#5.3.3.使用Java API

也可以通過(guò)Java API通過(guò)編程式創(chuàng)建快照:

CacheConfiguration<Long, String> ccfg = new CacheConfiguration<Long, String>("snapshot-cache");try (IgniteCache<Long, String> cache = ignite.getOrCreateCache(ccfg)) {cache.put(1, "Maxim");// Start snapshot operation.ignite.snapshot().createSnapshot("snapshot_02092020").get();
}
finally {ignite.destroyCache(ccfg);
}

#5.4.從快照恢復(fù)

當(dāng)前,數(shù)據(jù)恢復(fù)過(guò)程必須手動(dòng)執(zhí)行。簡(jiǎn)而言之,需要停止集群,用快照中的數(shù)據(jù)替換持久化數(shù)據(jù)和其他文件,然后重啟節(jié)點(diǎn)。

詳細(xì)過(guò)程如下:

  1. 停止要恢復(fù)的集群;
  2. 從檢查點(diǎn)目錄$IGNITE_HOME/work/cp中刪除所有文件;
  3. 在每個(gè)節(jié)點(diǎn)上執(zhí)行以下操作,單獨(dú)清理db/{node_id}目錄,如果他不在Ignite的work目錄下:
    • $IGNITE_HOME/work/db/binary_meta目錄中刪除和{nodeId}有關(guān)的文件;
    • $IGNITE_HOME/work/db/marshaller目錄中刪除和{nodeId}有關(guān)的文件;
    • $IGNITE_HOME/work/db目錄中刪除和{nodeId}有關(guān)的文件和子目錄;
    • 將快照中屬于{node_id}節(jié)點(diǎn)的文件復(fù)制到$IGNITE_HOME/work/目錄中。如果db/{node_id}目錄不在Ignite的工作目錄下,則應(yīng)在對(duì)應(yīng)目錄復(fù)制數(shù)據(jù)文件。
  4. 重啟集群。

在不同拓?fù)涞募荷匣謴?fù)

有時(shí)可能在N個(gè)節(jié)點(diǎn)的集群上創(chuàng)建快照,但是需要在有M個(gè)節(jié)點(diǎn)的集群上進(jìn)行恢復(fù),下表說(shuō)明了支持的選項(xiàng):

條件描述
N==M建議方案,在拓?fù)湟恢碌募荷蟿?chuàng)建和使用快照。
N<M在M個(gè)節(jié)點(diǎn)的集群上首先啟動(dòng)N個(gè)節(jié)點(diǎn),應(yīng)用快照,然后將剩余的M-N個(gè)集群節(jié)點(diǎn)加入拓?fù)?#xff0c;然后等待數(shù)據(jù)再平衡和索引重建。
N>M不支持。

#5.5.一致性保證

在Ignite的持久化文件、索引、模式、二進(jìn)制元數(shù)據(jù)、編組器以及節(jié)點(diǎn)的其他文件上的并發(fā)操作以及正在進(jìn)行的修改,所有的快照都是完全一致的。

集群范圍的快照一致性是通過(guò)觸發(fā)分區(qū)映射交換過(guò)程實(shí)現(xiàn)的,通過(guò)這樣做,集群最終達(dá)到的狀態(tài)是所有之前發(fā)起的事務(wù)全部完成,新的事務(wù)全部暫停,這個(gè)過(guò)程結(jié)束之后,集群就會(huì)發(fā)起快照創(chuàng)建過(guò)程,PME過(guò)程會(huì)確??煺找砸恢碌臓顟B(tài)包括了主快照和備份快照。

Ignite持久化文件與其快照副本之間的一致性是通過(guò)將原始文件復(fù)制到目標(biāo)快照目錄并跟蹤所有正在進(jìn)行的更改來(lái)實(shí)現(xiàn)的,跟蹤更改可能需要額外的空間。

#5.6.當(dāng)前的限制

快照過(guò)程有若干限制,如果要用于生產(chǎn)環(huán)境需要事先了解:

  • 不支持某個(gè)表/緩存的快照,只能創(chuàng)建整個(gè)集群的快照;
  • 未開(kāi)啟原生持久化的表/緩存,不支持快照;
  • 加密的緩存不包括在快照中;
  • 同時(shí)只能執(zhí)行一個(gè)快照操作;
  • 如果一個(gè)服務(wù)端節(jié)點(diǎn)離開(kāi)集群,快照過(guò)程會(huì)被中斷;
  • 快照只能在具有相同節(jié)點(diǎn)ID的同一集群拓?fù)渲谢謴?fù);
  • 目前還不支持自動(dòng)化的恢復(fù)過(guò)程,只能手工執(zhí)行。

#6.磁盤(pán)壓縮

磁盤(pán)壓縮是指將數(shù)據(jù)頁(yè)面寫(xiě)入磁盤(pán)時(shí)對(duì)其進(jìn)行壓縮的過(guò)程,以減小磁盤(pán)空間占用。這些頁(yè)面在內(nèi)存中是不壓縮的,但是當(dāng)將數(shù)據(jù)刷新到磁盤(pán)時(shí),將使用配置的算法對(duì)其進(jìn)行壓縮。這僅適用于開(kāi)啟原生持久化的數(shù)據(jù)頁(yè)面并且不會(huì)壓縮索引或WAL記錄的數(shù)據(jù)頁(yè),WAL記錄壓縮是可以單獨(dú)啟用的。

磁盤(pán)頁(yè)面壓縮是在每個(gè)緩存的配置中設(shè)定的,緩存必須在持久化的數(shù)據(jù)區(qū)中。目前沒(méi)有選項(xiàng)可全局啟用磁盤(pán)頁(yè)面壓縮,此外,還必須必須滿足以下的條件:

  • 將持久化配置中的pageSize屬性設(shè)置為文件系統(tǒng)頁(yè)面大小的至少2倍,這意味著頁(yè)面大小必須為8K或16K;
  • 啟用ignite-compress模塊。

要為某個(gè)緩存啟用磁盤(pán)頁(yè)面壓縮,需要在緩存配置中提供一種可用的壓縮算法,如下所示:

  • XML
  • Java
DataStorageConfiguration dsCfg = new DataStorageConfiguration();//set the page size to 2 types of the disk page size
dsCfg.setPageSize(4096 * 2);//enable persistence for the default data region
dsCfg.setDefaultDataRegionConfiguration(new DataRegionConfiguration().setPersistenceEnabled(true));IgniteConfiguration cfg = new IgniteConfiguration();
cfg.setDataStorageConfiguration(dsCfg);CacheConfiguration cacheCfg = new CacheConfiguration("myCache");
//enable disk page compression for this cache
cacheCfg.setDiskPageCompression(DiskPageCompression.LZ4);
//optionally set the compression level
cacheCfg.setDiskPageCompressionLevel(10);cfg.setCacheConfiguration(cacheCfg);Ignite ignite = Ignition.start(cfg);

#6.1.支持的算法

支持的壓縮算法包括:

  • ZSTD:支持從-131072到22的壓縮級(jí)別(默認(rèn)值:3);
  • LZ4:支持從0到17的壓縮級(jí)別(默認(rèn)值:0);
  • SNAPPY
  • SKIP_GARBAGE:該算法僅從半填充頁(yè)面中提取有用的數(shù)據(jù),而不壓縮數(shù)據(jù)。

#7.持久化調(diào)優(yōu)

本章節(jié)總結(jié)了Ignite原生持久化調(diào)優(yōu)的最佳實(shí)踐。

#7.1.調(diào)整頁(yè)面大小

Ignite的頁(yè)面大小(DataStorageConfiguration.pageSize)不要小于存儲(chǔ)設(shè)備(SSD、閃存、HDD等)的頁(yè)面大小以及操作系統(tǒng)緩存頁(yè)面的大小,默認(rèn)值為4KB。

操作系統(tǒng)的緩存頁(yè)面大小很容易就可以通過(guò)系統(tǒng)工具和參數(shù)獲取到。

存儲(chǔ)設(shè)備比如SSD的頁(yè)面大小可以在設(shè)備的說(shuō)明上找到,如果廠商未提供這些信息,可以運(yùn)行SSD的基準(zhǔn)測(cè)試來(lái)算出這個(gè)數(shù)值,如果還是難以拿到這個(gè)數(shù)值,可以使用4KB作為Ignite的頁(yè)面大小。很多廠商為了適應(yīng)4KB的隨機(jī)寫(xiě)工作負(fù)載不得不調(diào)整驅(qū)動(dòng),因?yàn)楹芏鄻?biāo)準(zhǔn)基準(zhǔn)測(cè)試都是默認(rèn)使用4KB,來(lái)自英特爾的白皮書(shū)也確認(rèn)4KB足夠了。

選定最優(yōu)值之后,可以將其用于集群的配置:

  • XML
  • Java
  • C#/.NET
IgniteConfiguration cfg = new IgniteConfiguration();// Durable memory configuration.
DataStorageConfiguration storageCfg = new DataStorageConfiguration();// Changing the page size to 8 KB.
storageCfg.setPageSize(8192);cfg.setDataStorageConfiguration(storageCfg);

#7.2.單獨(dú)保存WAL

考慮為數(shù)據(jù)文件以及預(yù)寫(xiě)日志(WAL)使用單獨(dú)的磁盤(pán)設(shè)備。Ignite會(huì)主動(dòng)地寫(xiě)入數(shù)據(jù)文件以及WAL文件,下面的示例會(huì)顯示如何為數(shù)據(jù)存儲(chǔ)、WAL以及WAL存檔配置單獨(dú)的路徑:

  • XML
  • Java
  • C#/.NET
IgniteConfiguration cfg = new IgniteConfiguration();// Configuring Native Persistence.
DataStorageConfiguration storeCfg = new DataStorageConfiguration();// Sets a path to the root directory where data and indexes are to be persisted.
// It's assumed the directory is on a separated SSD.
storeCfg.setStoragePath("/ssd/storage");// Sets a path to the directory where WAL is stored.
// It's assumed the directory is on a separated HDD.
storeCfg.setWalPath("/wal");// Sets a path to the directory where WAL archive is stored.
// The directory is on the same HDD as the WAL.
storeCfg.setWalArchivePath("/wal/archive");cfg.setDataStorageConfiguration(storeCfg);// Starting the node.
Ignite ignite = Ignition.start(cfg);

#7.3.增加WAL段大小

WAL段的默認(rèn)大小(64MB)在高負(fù)載情況下可能是低效的,因?yàn)樗鼘?dǎo)致WAL在段之間頻繁切換,并且切換/輪轉(zhuǎn)是昂貴的操作。將段大小設(shè)置為較大的值(最多2GB)可能有助于減少切換操作的次數(shù),不過(guò)這將增加預(yù)寫(xiě)日志的占用空間。

具體請(qǐng)參見(jiàn)修改WAL段大小。

#7.4.調(diào)整WAL模式

考慮其它WAL模式替代默認(rèn)模式。每種模式在節(jié)點(diǎn)故障時(shí)提供不同程度的可靠性,并且可靠性與速度成反比,即,WAL模式越可靠,則速度越慢。因此,如果具體業(yè)務(wù)不需要高可靠性,那么可以切換到可靠性較低的模式。

具體可以看WAL模式的相關(guān)內(nèi)容。

#7.5.禁用WAL

有時(shí)禁用WAL也會(huì)改進(jìn)性能。

#7.6.頁(yè)面寫(xiě)入限流

Ignite會(huì)定期地啟動(dòng)檢查點(diǎn)進(jìn)程,以在內(nèi)存和磁盤(pán)間同步臟頁(yè)面。臟頁(yè)面是已在內(nèi)存中更新但是還未寫(xiě)入對(duì)應(yīng)的分區(qū)文件的頁(yè)面(更新只是添加到了WAL)。這個(gè)進(jìn)程在后臺(tái)進(jìn)行,對(duì)應(yīng)用沒(méi)有影響。

但是,如果計(jì)劃進(jìn)行檢查點(diǎn)的臟頁(yè)面在寫(xiě)入磁盤(pán)前被更新,它之前的狀態(tài)會(huì)被復(fù)制進(jìn)某個(gè)區(qū)域,叫做檢查點(diǎn)緩沖區(qū)。如果這個(gè)緩沖區(qū)溢出,那么在檢查點(diǎn)處理過(guò)程中,Ignite會(huì)停止所有的更新。因此,寫(xiě)入性能可能降為0,直至檢查點(diǎn)過(guò)程完成,如下圖所示:

當(dāng)檢查點(diǎn)處理正在進(jìn)行中時(shí),如果臟頁(yè)面數(shù)達(dá)到閾值,同樣的情況也會(huì)發(fā)生,這會(huì)使Ignite強(qiáng)制安排一個(gè)新的檢查點(diǎn)執(zhí)行,并停止所有的更新操作直到第一個(gè)檢查點(diǎn)執(zhí)行完成。

當(dāng)磁盤(pán)較慢或者更新過(guò)于頻繁時(shí),這兩種情況都會(huì)發(fā)生,要減少或者防止這樣的性能下降,可以考慮啟用頁(yè)面寫(xiě)入限流算法。這個(gè)算法會(huì)在檢查點(diǎn)緩沖區(qū)填充過(guò)快或者臟頁(yè)面占比過(guò)高時(shí),將更新操作的性能降低到磁盤(pán)的速度。

頁(yè)面寫(xiě)入限流剖析

要了解更多的信息,可以看相關(guān)的Wiki頁(yè)面。

下面的示例顯示了如何開(kāi)啟頁(yè)面寫(xiě)入限流:

  • XML
  • Java
  • C#/.NET
IgniteConfiguration cfg = new IgniteConfiguration();// Configuring Native Persistence.
DataStorageConfiguration storeCfg = new DataStorageConfiguration();// Enabling the writes throttling.
storeCfg.setWriteThrottlingEnabled(true);cfg.setDataStorageConfiguration(storeCfg);
// Starting the node.
Ignite ignite = Ignition.start(cfg);

#7.7.調(diào)整檢查點(diǎn)緩沖區(qū)大小

前述章節(jié)中描述的檢查點(diǎn)緩沖區(qū)大小,是檢查點(diǎn)處理的觸發(fā)器之一。

緩沖區(qū)的默認(rèn)大小是根據(jù)數(shù)據(jù)區(qū)大小計(jì)算的。

數(shù)據(jù)區(qū)大小默認(rèn)檢查點(diǎn)緩沖區(qū)大小
< 1GBMIN (256 MB, 數(shù)據(jù)區(qū)大小)
1GB ~ 8GB數(shù)據(jù)區(qū)大小/4
> 8GB2GB

默認(rèn)的緩沖區(qū)大小并沒(méi)有為寫(xiě)密集型應(yīng)用進(jìn)行優(yōu)化,因?yàn)樵诖笮〗咏鼧?biāo)稱(chēng)值時(shí),頁(yè)面寫(xiě)入限流算法會(huì)降低寫(xiě)入的性能,因此在正在進(jìn)行檢查點(diǎn)處理時(shí)還希望保持寫(xiě)入性能,可以考慮增加DataRegionConfiguration.checkpointPageBufferSize,并且開(kāi)啟寫(xiě)入限流來(lái)阻止性能的下降:

  • XML
  • Java
  • C#/.NET
IgniteConfiguration cfg = new IgniteConfiguration();// Configuring Native Persistence.
DataStorageConfiguration storeCfg = new DataStorageConfiguration();// Enabling the writes throttling.
storeCfg.setWriteThrottlingEnabled(true);// Increasing the buffer size to 1 GB.
storeCfg.getDefaultDataRegionConfiguration().setCheckpointPageBufferSize(1024L * 1024 * 1024);cfg.setDataStorageConfiguration(storeCfg);// Starting the node.
Ignite ignite = Ignition.start(cfg);

在上例中,默認(rèn)數(shù)據(jù)區(qū)的檢查點(diǎn)緩沖區(qū)大小配置為1GB。

#7.8.啟用直接I/O

通常當(dāng)應(yīng)用訪問(wèn)磁盤(pán)上的數(shù)據(jù)時(shí),操作系統(tǒng)拿到數(shù)據(jù)后會(huì)將其寫(xiě)入一個(gè)文件緩沖區(qū)緩存,寫(xiě)操作也是同樣,操作系統(tǒng)首先將數(shù)據(jù)寫(xiě)入緩存,然后才會(huì)傳輸?shù)酱疟P(pán),要消除這個(gè)過(guò)程,可以打開(kāi)直接IO,這時(shí)數(shù)據(jù)會(huì)忽略文件緩沖區(qū)緩存,直接從磁盤(pán)進(jìn)行讀寫(xiě)。

Ignite中的直接I/O插件用于加速檢查點(diǎn)進(jìn)程,它的作用是將內(nèi)存中的臟頁(yè)面寫(xiě)入磁盤(pán),建議將直接IO插件用于寫(xiě)密集型負(fù)載環(huán)境中。

注意

注意,無(wú)法專(zhuān)門(mén)為WAL文件開(kāi)啟直接I/O,但是開(kāi)啟直接I/O可以為WAL文件帶來(lái)一點(diǎn)好處,就是WAL數(shù)據(jù)不會(huì)在操作系統(tǒng)的緩沖區(qū)緩存中存儲(chǔ)過(guò)長(zhǎng)時(shí)間,它會(huì)在下一次頁(yè)面緩存掃描中被刷新(依賴(lài)于WAL模式),然后從頁(yè)面緩存中刪除。

要啟用直接I/O插件,需要在二進(jìn)制包中將{IGNITE_HOME}/libs/optional/ignite-direct-io文件夾上移一層至libs/optional/ignite-direct-io文件夾,或者也可以作為一個(gè)Maven構(gòu)件引入,具體請(qǐng)參見(jiàn)這里的介紹。

通過(guò)IGNITE_DIRECT_IO_ENABLED系統(tǒng)屬性,也可以在運(yùn)行時(shí)啟用/禁用該插件。

相關(guān)的Wiki頁(yè)面有更多的細(xì)節(jié)。

#7.9.購(gòu)買(mǎi)產(chǎn)品級(jí)SSD

限于SSD的操作特性,在經(jīng)歷幾個(gè)小時(shí)的高強(qiáng)度寫(xiě)入負(fù)載之后,Ignite原生持久化的性能可能會(huì)下降,因此需要考慮購(gòu)買(mǎi)快速的產(chǎn)品級(jí)SSD來(lái)保證高性能,或者切換到非易失性?xún)?nèi)存設(shè)備比如Intel Optane持久化內(nèi)存。

#7.10.SSD預(yù)留空間

由于SSD預(yù)留空間的原因,50%使用率的磁盤(pán)的隨機(jī)寫(xiě)性能要好于90%使用率的磁盤(pán),因此需要考慮購(gòu)買(mǎi)高預(yù)留空間比率的SSD,然后還要確保廠商能提供工具來(lái)進(jìn)行相關(guān)的調(diào)整。

Intel 3D XPoint

考慮使用3D XPoint驅(qū)動(dòng)器代替常規(guī)SSD,以避免由SSD級(jí)別上的低預(yù)留空間設(shè)置和恒定垃圾收集造成的瓶頸。具體可以看這里。

配置緩存

#1.緩存配置

本章節(jié)介紹如何設(shè)定緩存的配置參數(shù),緩存創(chuàng)建之后,這些參數(shù)將無(wú)法修改。

Ignite中的緩存和表

緩存驅(qū)動(dòng)的配置方式是配置選項(xiàng)之一,還可以使用CREATE TABLE這樣的標(biāo)準(zhǔn)SQL命令來(lái)配置緩存/表,具體請(qǐng)參見(jiàn)鍵-值緩存與SQL表章節(jié)的內(nèi)容以了解Ignite中緩存和表的關(guān)系。

#1.1.配置示例

下面是緩存配置的示例:

  • XML
  • Java
  • C#/.NET
  • SQL
CacheConfiguration cacheCfg = new CacheConfiguration("myCache");cacheCfg.setCacheMode(CacheMode.PARTITIONED);
cacheCfg.setBackups(2);
cacheCfg.setRebalanceMode(CacheRebalanceMode.SYNC);
cacheCfg.setWriteSynchronizationMode(CacheWriteSynchronizationMode.FULL_SYNC);
cacheCfg.setPartitionLossPolicy(PartitionLossPolicy.READ_ONLY_SAFE);IgniteConfiguration cfg = new IgniteConfiguration();
cfg.setCacheConfiguration(cacheCfg);// Start a node.
Ignition.start(cfg);

完整的參數(shù)列表,請(qǐng)參見(jiàn)CacheConfiguration的javadoc。

參數(shù)描述默認(rèn)值
name緩存名
cacheMode該參數(shù)定義了數(shù)據(jù)在集群中的分布方式。在默認(rèn)的PARTITIONED模式中,整體數(shù)據(jù)集被拆分為分區(qū),然后所有的分區(qū)再以平衡的方式分布于相關(guān)的節(jié)點(diǎn)上。而在REPLICATED模式中,所有的數(shù)據(jù)在所有的節(jié)點(diǎn)上都復(fù)制一份,具體請(qǐng)參見(jiàn)分區(qū)/復(fù)制模式章節(jié)的介紹。PARTITIONED
writeSynchronizationMode寫(xiě)同步模式,具體請(qǐng)參見(jiàn)配置分區(qū)備份章節(jié)的內(nèi)容。PRIMARY_SYNC
rebalanceMode該參數(shù)控制再平衡過(guò)程的執(zhí)行方式??蛇x值包括:SYNC:所有緩存操作都會(huì)被阻塞直到再平衡結(jié)束;ASYNC:再平衡在后臺(tái)執(zhí)行;NONE:再平衡不會(huì)被觸發(fā)。ASYNC
backups緩存的備份分區(qū)數(shù)量。0
partitionLossPolicy分區(qū)丟失策略IGNORE
readFromBackup如果本地的備份分區(qū)可用,則從備份分區(qū)讀取數(shù)據(jù),而不是向主分區(qū)請(qǐng)求數(shù)據(jù)(可能位于遠(yuǎn)程節(jié)點(diǎn))。true
queryPrallelism單節(jié)點(diǎn)在緩存上執(zhí)行SQL查詢(xún)的線程數(shù),具體請(qǐng)參見(jiàn)性能優(yōu)化的查詢(xún)并行度相關(guān)章節(jié)的內(nèi)容。1

#1.2.緩存模板

緩存模板是在集群中注冊(cè)的CacheConfiguration實(shí)例,然后用作后續(xù)創(chuàng)建新緩存或SQL表的基礎(chǔ),一個(gè)從模板創(chuàng)建的緩存或表會(huì)繼承該模板的所有屬性。

當(dāng)使用CREATE TABLE命令建表時(shí),模板非常有用,因?yàn)樵撁畈⒉恢С炙械木彺鎱?shù)。

提示

當(dāng)前,CREATE TABLE和REST命令支持模板。

創(chuàng)建模板時(shí),需要定義一個(gè)緩存配置然后將其加入Ignite實(shí)例中,如下所示。如果希望在XML配置文件中定義緩存模板,需要在模板名后面加一個(gè)*號(hào),這個(gè)是用于標(biāo)示該配置是一個(gè)模板而不是實(shí)際的緩存。

  • XML
  • Java
  • C#/.NET
IgniteConfiguration igniteCfg = new IgniteConfiguration();try (Ignite ignite = Ignition.start(igniteCfg)) {CacheConfiguration cacheCfg = new CacheConfiguration("myCacheTemplate");cacheCfg.setBackups(2);cacheCfg.setCacheMode(CacheMode.PARTITIONED);// Register the cache templateignite.addCacheConfiguration(cacheCfg);
}

緩存模板在集群中注冊(cè)之后,就可以用相同的配置創(chuàng)建其他緩存了。

#2.配置分區(qū)備份

Ignite默認(rèn)為每個(gè)分區(qū)持有一個(gè)副本(整個(gè)數(shù)據(jù)集的一個(gè)副本),這時(shí)如果一個(gè)或者多個(gè)節(jié)點(diǎn)故障,存儲(chǔ)于這些節(jié)點(diǎn)上的分區(qū)就會(huì)丟失,為了避免這種情況,可以配置Ignite維護(hù)分區(qū)的備份副本。

提示

備份默認(rèn)是禁用的。

備份副本是緩存(表)級(jí)的配置,如果配置了2個(gè)備份副本,集群會(huì)為每個(gè)分區(qū)維護(hù)3個(gè)副本。其中一個(gè)分區(qū)稱(chēng)為主分區(qū),其他2個(gè)稱(chēng)為備份分區(qū)。擴(kuò)展來(lái)說(shuō),具有主分區(qū)的節(jié)點(diǎn)稱(chēng)為該分區(qū)中存儲(chǔ)的數(shù)據(jù)的主節(jié)點(diǎn),備份分區(qū)對(duì)應(yīng)的節(jié)點(diǎn)稱(chēng)為備份節(jié)點(diǎn)。

當(dāng)某些數(shù)據(jù)對(duì)應(yīng)的主分區(qū)所在的節(jié)點(diǎn)離開(kāi)集群,Ignite會(huì)觸發(fā)分區(qū)映射交換(PME)過(guò)程,PME會(huì)標(biāo)記這些數(shù)據(jù)對(duì)應(yīng)的某個(gè)已配置的備份分區(qū)為主分區(qū)。

備份分區(qū)增加了數(shù)據(jù)的可用性和某些場(chǎng)景的數(shù)據(jù)讀取速度,因?yàn)槿绻镜毓?jié)點(diǎn)的備份分區(qū)可用,Ignite會(huì)從備份分區(qū)讀取數(shù)據(jù)(這是默認(rèn)的行為,但是可以禁用)。但是增加了內(nèi)存的消耗或者持久化存儲(chǔ)的大小(如果開(kāi)啟)。

#2.1.配置備份

在緩存配置中配置backups屬性,可以配置備份副本的數(shù)量。

  • XML
  • Java
  • C#/.NET
CacheConfiguration cacheCfg = new CacheConfiguration();cacheCfg.setName("cacheName");
cacheCfg.setCacheMode(CacheMode.PARTITIONED);
cacheCfg.setBackups(1);IgniteConfiguration cfg = new IgniteConfiguration();cfg.setCacheConfiguration(cacheCfg);// Start the node.
Ignite ignite = Ignition.start(cfg);

#2.2.同步和異步備份

通過(guò)指定寫(xiě)同步模式,可以配置更新在主備副本之間是同步模式還是異步模式,如下所示:

  • XML
  • Java
  • C#/.NET
CacheConfiguration cacheCfg = new CacheConfiguration();cacheCfg.setName("cacheName");
cacheCfg.setBackups(1);
cacheCfg.setWriteSynchronizationMode(CacheWriteSynchronizationMode.FULL_SYNC);
IgniteConfiguration cfg = new IgniteConfiguration();cfg.setCacheConfiguration(cacheCfg);// Start the node.
Ignition.start(cfg);

寫(xiě)同步模式有如下的可選值:

描述
FULL_SYNC客戶(hù)端節(jié)點(diǎn)會(huì)等待所有相關(guān)的遠(yuǎn)程節(jié)點(diǎn)(主和備)寫(xiě)入或者提交完成。
FULL_ASYNC客戶(hù)端節(jié)點(diǎn)不會(huì)等待來(lái)自相關(guān)節(jié)點(diǎn)的響應(yīng),這時(shí)遠(yuǎn)程節(jié)點(diǎn)會(huì)在緩存寫(xiě)入或者事務(wù)提交方法完成之后稍晚些收到狀態(tài)更新。
PRIMARY_SYNC默認(rèn)模式,客戶(hù)端節(jié)點(diǎn)會(huì)等待主節(jié)點(diǎn)的寫(xiě)入或者提交完成,但是不會(huì)等待備份的更新。

#3.分區(qū)丟失策略

在整個(gè)集群的生命周期中,由于分區(qū)的主節(jié)點(diǎn)和備份節(jié)點(diǎn)的故障可能出現(xiàn)分區(qū)丟失的情況,這會(huì)導(dǎo)致部分?jǐn)?shù)據(jù)丟失,需要根據(jù)場(chǎng)景進(jìn)行處理。

當(dāng)一個(gè)分區(qū)的主副本和所有備份副本均不在線,即該分區(qū)的主節(jié)點(diǎn)和備份節(jié)點(diǎn)全部故障時(shí),該分區(qū)將丟失。這意味著對(duì)于給定的緩存,能承受的節(jié)點(diǎn)故障數(shù)不能超過(guò)緩存?zhèn)浞輸?shù)。

當(dāng)集群拓?fù)浒l(fā)生變更時(shí),Ignite會(huì)檢查變更是否導(dǎo)致分區(qū)丟失,并根據(jù)配置的分區(qū)丟失策略和基線自動(dòng)調(diào)整設(shè)置,允許或禁止對(duì)緩存進(jìn)行操作,具體請(qǐng)參見(jiàn)下一章節(jié)的介紹。

對(duì)于純內(nèi)存緩存,當(dāng)分區(qū)丟失時(shí),除非數(shù)據(jù)重新加載,否則分區(qū)中的數(shù)據(jù)將無(wú)法恢復(fù)。對(duì)于持久化緩存,數(shù)據(jù)不會(huì)物理丟失,因?yàn)樗驯怀志没酱疟P(pán)上。當(dāng)發(fā)生故障或斷開(kāi)連接的節(jié)點(diǎn)回到集群時(shí)(重啟后),將從磁盤(pán)上加載數(shù)據(jù)。這時(shí)需要重置丟失的分區(qū)的狀態(tài)才能繼續(xù)使用數(shù)據(jù),具體請(qǐng)參見(jiàn)處理分區(qū)丟失章節(jié)的介紹。

#3.1.配置分區(qū)丟失策略

Ignite支持以下的分區(qū)丟失策略:

策略描述
IGNORE分區(qū)丟失將被忽略。集群將丟失的分區(qū)視為空分區(qū)。當(dāng)請(qǐng)求該分區(qū)的數(shù)據(jù)時(shí),將返回空值,就好像數(shù)據(jù)從不存在一樣。此策略只能在純內(nèi)存集群中使用且是默認(rèn)值,這個(gè)模式中啟用了基線自動(dòng)調(diào)整且超時(shí)為0。在所有其他配置(集群中只要有一個(gè)數(shù)據(jù)區(qū)開(kāi)啟了持久化)中,IGNORE策略都會(huì)被READ_WRITE_SAFE替代,即使在緩存配置中顯式指定也不行。
READ_WRITE_SAFE緩存丟失分區(qū)的讀寫(xiě)嘗試都會(huì)拋出異常,但是在線分區(qū)的讀寫(xiě)是正常的。
READ_ONLY_SAFE緩存處于只讀狀態(tài),緩存的寫(xiě)操作會(huì)拋出異常,丟失分區(qū)的讀操作也會(huì)拋出異常,具體請(qǐng)參見(jiàn)處理分區(qū)丟失章節(jié)的介紹。

分區(qū)丟失策略是緩存級(jí)的配置。

  • XML
  • Java
CacheConfiguration cacheCfg = new CacheConfiguration("myCache");cacheCfg.setPartitionLossPolicy(PartitionLossPolicy.READ_ONLY_SAFE);

#3.2.監(jiān)聽(tīng)分區(qū)丟失事件

當(dāng)發(fā)生分區(qū)丟失時(shí),可以監(jiān)聽(tīng)EVT_CACHE_REBALANCE_PART_DATA_LOST事件的通知。每個(gè)丟失的分區(qū)都會(huì)觸發(fā)該事件,其包含了丟失的分區(qū)號(hào)以及持有該分區(qū)的節(jié)點(diǎn)ID。只有使用READ_WRITE_SAFEREAD_ONLY_SAFE策略時(shí),才會(huì)觸發(fā)分區(qū)丟失事件。

首先需要在集群的配置中啟用事件,具體參見(jiàn)啟用事件的介紹。

Ignite ignite = Ignition.start();IgnitePredicate<Event> locLsnr = evt -> {CacheRebalancingEvent cacheEvt = (CacheRebalancingEvent) evt;int lostPart = cacheEvt.partition();ClusterNode node = cacheEvt.discoveryNode();System.out.println(lostPart);return true; // Continue listening.
};ignite.events().localListen(locLsnr, EventType.EVT_CACHE_REBALANCE_PART_DATA_LOST);

關(guān)于其他和分區(qū)再平衡有關(guān)的事件,可以參見(jiàn)分區(qū)再平衡事件章節(jié)的介紹。

#3.3.處理分區(qū)丟失

如果數(shù)據(jù)沒(méi)有物理丟失,可以將該節(jié)點(diǎn)恢復(fù)然后重置丟失分區(qū)的狀態(tài),這樣就可以繼續(xù)處理該數(shù)據(jù),通過(guò)控制腳本,或者在特定的緩存上調(diào)用Ignite.resetLostPartitions(cacheNames),可以重置分區(qū)的狀態(tài)。

ignite.resetLostPartitions(Arrays.asList("myCache"));

控制腳本命令為:

control.sh --cache reset_lost_partitions myCache

如果不重置丟失的分區(qū),根據(jù)緩存策略的配置,從丟失分區(qū)的讀寫(xiě)操作可能會(huì)拋出CacheException,通過(guò)分析上層的觸發(fā)原因,可以檢查該異常是否由分區(qū)狀態(tài)導(dǎo)致:

IgniteCache<Integer, Integer> cache = ignite.cache("myCache");try {Integer value = cache.get(3);System.out.println(value);
} catch (CacheException e) {if (e.getCause() instanceof CacheInvalidStateException) {System.out.println(e.getCause().getMessage());} else {e.printStackTrace();}
}

通過(guò)IgniteCache.lostPartitions(),可以拿到緩存丟失分區(qū)的列表:

IgniteCache<Integer, String> cache = ignite.cache("myCache");cache.lostPartitions();

#3.4.從丟失分區(qū)中恢復(fù)

下面的章節(jié)會(huì)介紹根據(jù)集群的不同配置,如何從分區(qū)丟失中恢復(fù)。

#3.4.1.IGNORE策略的純內(nèi)存集群

在此配置中,該IGNORE策略?xún)H適用于啟用基線自動(dòng)調(diào)整且超時(shí)為0的場(chǎng)景,這也是純內(nèi)存集群的默認(rèn)設(shè)置。這時(shí)將忽略分區(qū)丟失,緩存仍然可以操作,丟失的分區(qū)會(huì)被視為空分區(qū)。

當(dāng)禁用基線自動(dòng)調(diào)整或超時(shí)時(shí)間大于0時(shí),IGNORE策略會(huì)被替換為READ_WRITE_SAFE。

#3.4.2.READ_WRITE_SAFE或READ_ONLY_SAFE策略的純內(nèi)存集群

重置丟失的分區(qū)之前,對(duì)緩存的操作將被阻止。重置后,緩存可以繼續(xù)使用,但是數(shù)據(jù)將丟失。

禁用基線自動(dòng)調(diào)整或超時(shí)大于0時(shí),必須在重置丟失的分區(qū)之前將節(jié)點(diǎn)(每個(gè)分區(qū)至少一個(gè)分區(qū)所有者)恢復(fù)到基線拓?fù)?。否則,Ignite.resetLostPartitions(cacheNames)會(huì)拋出一個(gè)消息為Cannot reset lost partitions because no baseline nodes are online [cache=someCahe, partition=someLostPart]ClusterTopologyCheckedException,表明無(wú)法安全恢復(fù)。如果由于某種原因(例如硬件故障)而無(wú)法恢復(fù)節(jié)點(diǎn),需要在重置丟失的分區(qū)之前將它們從基線拓?fù)渲惺謩?dòng)刪除。

#3.4.3.開(kāi)啟持久化的集群

如果所有的數(shù)據(jù)區(qū)都開(kāi)啟了持久化(沒(méi)有純內(nèi)存數(shù)據(jù)區(qū)),那么有兩種從丟失分區(qū)中恢復(fù)的方式(只要數(shù)據(jù)沒(méi)有物理?yè)p壞):

  1. 讓所有的節(jié)點(diǎn)返回到基線;
  2. 重置丟失的分區(qū)(所有的緩存調(diào)用Ignite.resetLostPartitions(…?))。

或者:

  1. 停止所有的節(jié)點(diǎn);
  2. 啟動(dòng)包括故障節(jié)點(diǎn)在內(nèi)的所有節(jié)點(diǎn),然后激活集群。

如果某些節(jié)點(diǎn)無(wú)法返回,在嘗試重置丟失分區(qū)狀態(tài)前,需要將他們從基線拓?fù)渲袆h除。

#3.4.4.同時(shí)有純內(nèi)存和持久化緩存的集群

如果集群同時(shí)有純內(nèi)存的數(shù)據(jù)區(qū)和持久化的數(shù)據(jù)區(qū),那么純內(nèi)存的緩存會(huì)和配置為READ_WRITE_SAFE的純內(nèi)存集群的處理方式一致,而持久化的緩存會(huì)和持久化的集群的處理方式一致。

#4.原子化模式

緩存默認(rèn)僅支持原子操作,而批量操作(例如putAll()removeAll())則按順序單獨(dú)執(zhí)行寫(xiě)入和刪除。但是也可以啟用事務(wù)支持并將一個(gè)或多個(gè)緩存操作,可能對(duì)應(yīng)一個(gè)或者多個(gè)鍵,分組為單個(gè)原子事務(wù)。這些操作在沒(méi)有任何其他交叉操作的情況下執(zhí)行,或全部成功或全部失敗,沒(méi)有部分成功的狀態(tài)。

要啟用緩存的事務(wù)支持,需要將緩存配置中的atomicityMode參數(shù)設(shè)置為TRANSACTIONAL。

警告

如果在一個(gè)緩存組中配置了多個(gè)緩存,這些緩存的原子化模式應(yīng)全部相同,不能有的是TRANSACTIONAL,有的是ATOMIC。

Ignite支持3種原子化模式,如下表所示:

原子化模式描述
ATOMIC默認(rèn)模式,所有操作都會(huì)原子化地執(zhí)行,一次一個(gè),不支持事務(wù)。ATOMIC模式通過(guò)避免事務(wù)鎖,提供了最好的性能,同時(shí)為每個(gè)單個(gè)操作提供了數(shù)據(jù)原子性和一致性。比如putAll(…?)以及removeAll(…?)方法這樣的批量操作,并不以事務(wù)方式執(zhí)行,可能部分失敗,如果發(fā)生了這種情況,會(huì)拋出CachePartialUpdateException異常,其中包含了更新失敗的鍵列表。
TRANSACTIONAL在鍵-值A(chǔ)PI層面開(kāi)啟了符合ACID的事務(wù)支持,但是SQL不支持事務(wù)。該模式的事務(wù)支持不同的并發(fā)模型和隔離級(jí)別。如果確實(shí)需要符合ACID操作才建議開(kāi)啟這個(gè)模式,因?yàn)槭聞?wù)會(huì)導(dǎo)致性能下降。具體請(qǐng)參見(jiàn)執(zhí)行事務(wù)。
TRANSACTIONAL_SNAPSHOT多版本并發(fā)控制(MVCC)的試驗(yàn)性實(shí)現(xiàn)。其同時(shí)支持鍵-值事務(wù)和SQL事務(wù),更多的信息以及限制,請(qǐng)參見(jiàn)多版本并發(fā)控制。**注意:**MVCC實(shí)現(xiàn)目前還處于測(cè)試階段,不建議用于生產(chǎn)。

可以在緩存配置中為緩存開(kāi)啟事務(wù)支持:

  • XML
  • Java
  • C#/.NET
CacheConfiguration cacheCfg = new CacheConfiguration();cacheCfg.setName("cacheName");cacheCfg.setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL);IgniteConfiguration cfg = new IgniteConfiguration();cfg.setCacheConfiguration(cacheCfg);// Optional transaction configuration. Configure TM lookup here.
TransactionConfiguration txCfg = new TransactionConfiguration();cfg.setTransactionConfiguration(txCfg);// Start a node
Ignition.start(cfg);

#5.過(guò)期策略

#5.1.概述

過(guò)期策略指定了在緩存條目過(guò)期之前必須經(jīng)過(guò)的時(shí)間量,時(shí)間可以從創(chuàng)建、最后訪問(wèn)或者修改時(shí)間開(kāi)始計(jì)算。

根據(jù)內(nèi)存配置,過(guò)期策略將從內(nèi)存或磁盤(pán)上刪除條目:

  • 內(nèi)存模式:數(shù)據(jù)僅保存在內(nèi)存中,過(guò)期的條目會(huì)完全從內(nèi)存中清除;
  • 內(nèi)存+Ignite持久化:過(guò)期的條目會(huì)完全從內(nèi)存和磁盤(pán)上刪除,注意過(guò)期策略會(huì)從磁盤(pán)上的分區(qū)文件中刪除數(shù)據(jù),但是不會(huì)釋放空間,該空間會(huì)在后續(xù)的數(shù)據(jù)寫(xiě)入中重用;
  • 內(nèi)存+外部存儲(chǔ):過(guò)期的條目?jī)H僅從內(nèi)存(Ignite)中刪除,外部存儲(chǔ)(RDBMS、NoSQL以及其它數(shù)據(jù)庫(kù))中的數(shù)據(jù)會(huì)保持不變;
  • 內(nèi)存+交換空間:過(guò)期的條目會(huì)同時(shí)從內(nèi)存和交換空間中刪除。

過(guò)期策略可以通過(guò)任何標(biāo)準(zhǔn)的javax.cache.expiry.ExpiryPolicy實(shí)現(xiàn)或自定義實(shí)現(xiàn)進(jìn)行設(shè)置:

#5.2.配置

下面是過(guò)期策略的配置示例:

  • XML
  • Java
  • C#/.NET
CacheConfiguration<Integer, String> cfg = new CacheConfiguration<Integer, String>();
cfg.setName("myCache");
cfg.setExpiryPolicyFactory(CreatedExpiryPolicy.factoryOf(Duration.FIVE_MINUTES));

也可以為單獨(dú)的緩存操作配置或者修改過(guò)期策略,該策略會(huì)影響返回的緩存實(shí)例上調(diào)用的每個(gè)操作:

CacheConfiguration<Integer, String> cacheCfg = new CacheConfiguration<Integer, String>("myCache");ignite.createCache(cacheCfg);IgniteCache cache = ignite.cache("myCache").withExpiryPolicy(new CreatedExpiryPolicy(new Duration(TimeUnit.MINUTES, 5)));// if the cache does not contain key 1, the entry will expire after 5 minutes
cache.put(1, "first value");

#5.3.Eager TTL(熱生存時(shí)間)

過(guò)期的條目從緩存中刪除,既可以馬上刪除,也可以在緩存操作對(duì)其訪問(wèn)時(shí)再刪除。只要有一個(gè)緩存啟用了熱生存時(shí)間,Ignite就會(huì)創(chuàng)建一個(gè)線程在后臺(tái)清理過(guò)期的數(shù)據(jù)。

如果該屬性配置為false,過(guò)期的條目不會(huì)被馬上刪除,而是在執(zhí)行緩存操作時(shí)由執(zhí)行該操作的線程將其刪除。

熱生存時(shí)間可以通過(guò)CacheConfiguration.eagerTtl屬性啟用或者禁用(默認(rèn)值是true)。

  • XML
  • Java
  • C#/.NET
CacheConfiguration<Integer, String> cfg = new CacheConfiguration<Integer, String>();
cfg.setName("myCache");cfg.setEagerTtl(true);

#6.堆內(nèi)緩存

Ignite在Java堆外部使用堆外內(nèi)存來(lái)分配數(shù)據(jù)區(qū),但是可以通過(guò)配置CacheConfiguration.setOnheapCacheEnabled(true)來(lái)開(kāi)啟堆內(nèi)緩存。

對(duì)于在使用二進(jìn)制形式的緩存條目或調(diào)用緩存條目的反序列化的服務(wù)器節(jié)點(diǎn)上進(jìn)行大量緩存讀取的場(chǎng)景,堆內(nèi)緩存很有用。例如,當(dāng)分布式計(jì)算或部署的服務(wù)從緩存中獲取數(shù)據(jù)進(jìn)行進(jìn)一步處理時(shí),可能會(huì)發(fā)生這種情況。

  • XML
  • Java
  • C#/.NET
CacheConfiguration cfg = new CacheConfiguration();
cfg.setName("myCache");
cfg.setOnheapCacheEnabled(true);

#6.1.配置退出策略

啟用堆內(nèi)緩存后,可以使用堆內(nèi)緩存退出策略來(lái)管理不斷增長(zhǎng)的堆內(nèi)緩存。

退出策略控制緩存的堆內(nèi)存中可以存儲(chǔ)的最大數(shù)據(jù)量,當(dāng)?shù)竭_(dá)最大值后,條目會(huì)從Java堆中退出。

提示

堆內(nèi)退出策略只會(huì)從Java堆中刪除緩存條目,堆外數(shù)據(jù)區(qū)中存儲(chǔ)的數(shù)據(jù)不受影響。

退出策略支持基于批次的退出和基于內(nèi)存大小限制的退出。如果開(kāi)啟了基于批次的退出,那么當(dāng)緩存的數(shù)量比緩存最大值多出batchSize個(gè)條目時(shí),退出就開(kāi)始了,這時(shí)batchSize個(gè)條目就會(huì)被退出。如果開(kāi)啟了基于內(nèi)存大小限制的退出,那么當(dāng)緩存條目的大小(字節(jié)數(shù))大于最大值時(shí),退出就會(huì)被觸發(fā)。

注意

只有未配置最大內(nèi)存限制時(shí),才會(huì)支持基于批次的退出。

Ignite中退出策略是可插拔的,可以通過(guò)EvictionPolicy接口進(jìn)行控制,退出策略的實(shí)現(xiàn)定義了從堆內(nèi)緩存選擇待退出條目的算法,然后當(dāng)緩存發(fā)生改變時(shí)就會(huì)收到通知。

#6.1.1.最近最少使用(LRU)

LRU退出策略基于最近最少使用算法,它會(huì)確保最近最少使用的數(shù)據(jù)(即最久沒(méi)有被訪問(wèn)的數(shù)據(jù))會(huì)被首先退出。

注意

LRU退出策略適用于堆內(nèi)緩存的大多數(shù)使用場(chǎng)景,不確定時(shí)可以?xún)?yōu)先使用。

這個(gè)退出策略通過(guò)CacheConfiguration進(jìn)行配置,支持基于批次的退出以及基于內(nèi)存大小限制的退出,如下所示:

  • XML
  • Java
  • C#/.NET
CacheConfiguration cacheCfg = new CacheConfiguration();cacheCfg.setName("cacheName");// Enabling on-heap caching for this distributed cache.
cacheCfg.setOnheapCacheEnabled(true);// Set the maximum cache size to 1 million (default is 100,000).
cacheCfg.setEvictionPolicyFactory(() -> new LruEvictionPolicy(1000000));IgniteConfiguration cfg = new IgniteConfiguration();cfg.setCacheConfiguration(cacheCfg);
#6.1.2.先進(jìn)先出(FIFO)

FIFO退出策略基于先進(jìn)先出(FIFO)算法,它確保緩存中保存時(shí)間最久的數(shù)據(jù)會(huì)被首先退出,它與LruEvictionPolicy不同,因?yàn)樗雎粤藬?shù)據(jù)的訪問(wèn)順序。

這個(gè)策略通過(guò)CacheConfiguration進(jìn)行配置,支持基于批次的退出以及基于內(nèi)存大小限制的退出。

  • XML
  • Java
  • C#/.NET
CacheConfiguration cacheCfg = new CacheConfiguration();cacheCfg.setName("cacheName");// Enabling on-heap caching for this distributed cache.
cacheCfg.setOnheapCacheEnabled(true);// Set the maximum cache size to 1 million (default is 100,000).
cacheCfg.setEvictionPolicyFactory(() -> new FifoEvictionPolicy(1000000));IgniteConfiguration cfg = new IgniteConfiguration();cfg.setCacheConfiguration(cacheCfg);
#6.1.3.有序

有序退出策略和FIFO退出策略很像,不同點(diǎn)在于通過(guò)默認(rèn)或者用戶(hù)定義的比較器定義了數(shù)據(jù)的順序,然后確保最小的數(shù)據(jù)(即排序數(shù)值最小的數(shù)據(jù))會(huì)被退出。

默認(rèn)的比較器用緩存條目的鍵作為比較器,它要求鍵必須實(shí)現(xiàn)Comparable接口。也可以提供自定義的比較器實(shí)現(xiàn),可以通過(guò)鍵,值或者兩者都用來(lái)進(jìn)行條目的比較。

這個(gè)策略通過(guò)CacheConfiguration進(jìn)行配置,支持基于批次的退出以及基于內(nèi)存大小限制的退出。

  • XML
  • Java
CacheConfiguration cacheCfg = new CacheConfiguration();cacheCfg.setName("cacheName");// Enabling on-heap caching for this distributed cache.
cacheCfg.setOnheapCacheEnabled(true);// Set the maximum cache size to 1 million (default is 100,000).
cacheCfg.setEvictionPolicyFactory(() -> new SortedEvictionPolicy(1000000));IgniteConfiguration cfg = new IgniteConfiguration();cfg.setCacheConfiguration(cacheCfg);

#7.緩存組

對(duì)于集群中的緩存來(lái)說(shuō),總有一個(gè)開(kāi)銷(xiāo),即緩存被拆分為分區(qū)后其狀態(tài)必須在每個(gè)集群節(jié)點(diǎn)上進(jìn)行跟蹤以滿足系統(tǒng)的需要。

如果開(kāi)啟了Ignite的原生持久化,那么對(duì)于每個(gè)分區(qū)來(lái)說(shuō),都會(huì)在磁盤(pán)上打開(kāi)一個(gè)文件進(jìn)行讀寫(xiě),因此,如果有更多的緩存和分區(qū):

  • 分區(qū)映射就會(huì)占用更多的Java堆,每個(gè)緩存都有自己的分區(qū)映射;
  • 新節(jié)點(diǎn)加入集群就會(huì)花費(fèi)更多的時(shí)間;
  • 節(jié)點(diǎn)離開(kāi)集群也會(huì)因?yàn)樵倨胶饣ㄙM(fèi)更多的時(shí)間;
  • 打開(kāi)中的分區(qū)文件就會(huì)更多從而影響檢查點(diǎn)的性能。

通常,如果只有幾十甚至幾百個(gè)緩存時(shí),不用擔(dān)心這些問(wèn)題,但是如果增長(zhǎng)到上千時(shí),這類(lèi)問(wèn)題就會(huì)凸顯。

要避免這個(gè)影響,可以考慮使用緩存組,一個(gè)組內(nèi)的緩存會(huì)共享各種內(nèi)部數(shù)據(jù)結(jié)構(gòu)比如上面提到的分區(qū)映射,這樣,會(huì)提高拓?fù)涫录幚淼男室约敖档驼w的內(nèi)存使用量。注意,從API上來(lái)看,緩存是不是組的一部分并沒(méi)有什么區(qū)別。

通過(guò)配置CacheConfigurationgroupName屬性可以創(chuàng)建一個(gè)緩存組,示例如下:

  • XML
  • Java
  • C#/.NET
// Defining cluster configuration.
IgniteConfiguration cfg = new IgniteConfiguration();// Defining Person cache configuration.
CacheConfiguration<Integer, Person> personCfg = new CacheConfiguration<Integer, Person>("Person");personCfg.setBackups(1);// Group the cache belongs to.
personCfg.setGroupName("group1");// Defining Organization cache configuration.
CacheConfiguration orgCfg = new CacheConfiguration("Organization");orgCfg.setBackups(1);// Group the cache belongs to.
orgCfg.setGroupName("group1");cfg.setCacheConfiguration(personCfg, orgCfg);// Starting the node.
Ignition.start(cfg);

在上面的示例中,PersonOrganization緩存都屬于group1

如何區(qū)分鍵-值對(duì)

如果將緩存分配給一個(gè)緩存組,則其數(shù)據(jù)存儲(chǔ)在共享分區(qū)的內(nèi)部結(jié)構(gòu)中。寫(xiě)入緩存的每個(gè)鍵都會(huì)附加其所屬的緩存的唯一ID。該ID是從緩存名派生的。這些都是透明的,并允許將不同緩存的數(shù)據(jù)存儲(chǔ)在相同的分區(qū)和B+樹(shù)結(jié)構(gòu)中。

對(duì)緩存進(jìn)行分組的原因很簡(jiǎn)單,如果決定對(duì)1000個(gè)緩存進(jìn)行分組,則存儲(chǔ)分區(qū)數(shù)據(jù)、分區(qū)映射和打開(kāi)分區(qū)文件的結(jié)構(gòu)將減少為原來(lái)的千分之一。

緩存組是否應(yīng)一直使用?

雖然有這么多的好處,但是它可能影響讀操作和索引的性能,這是由于所有的數(shù)據(jù)和索引都混合在一個(gè)共享的數(shù)據(jù)結(jié)構(gòu)(分區(qū)映射、B+樹(shù))中,查詢(xún)的時(shí)間變長(zhǎng)導(dǎo)致的。 因此,如果集群有數(shù)十個(gè)和數(shù)百個(gè)節(jié)點(diǎn)和緩存,并且由于內(nèi)部結(jié)構(gòu)、檢查點(diǎn)性能下降和/或節(jié)點(diǎn)到集群的連接速度較慢而遇到Java堆使用增加的情況,可以考慮使用緩存組。

#8.近緩存

近緩存是一種本地緩存,用于在本地節(jié)點(diǎn)上存儲(chǔ)最近或最常訪問(wèn)的數(shù)據(jù)。假設(shè)應(yīng)用啟動(dòng)了一個(gè)客戶(hù)端節(jié)點(diǎn)并定期查詢(xún)數(shù)據(jù),例如國(guó)家/地區(qū)代碼。因?yàn)榭蛻?hù)端節(jié)點(diǎn)不存儲(chǔ)數(shù)據(jù),所以這些查詢(xún)總是從遠(yuǎn)程節(jié)點(diǎn)獲取數(shù)據(jù)。這時(shí)可以配置近緩存,以在應(yīng)用運(yùn)行時(shí)將國(guó)家/地區(qū)代碼保留在本地節(jié)點(diǎn)上,這樣可以提高性能。

近緩存為特定的常規(guī)緩存配置,并且僅保留該緩存的數(shù)據(jù)。

近緩存將數(shù)據(jù)存儲(chǔ)在堆內(nèi)存中,可以為近緩存條目配置緩存的最大值和退出策略。

提示

近緩存是完全事務(wù)性的,并且每當(dāng)服務(wù)端節(jié)點(diǎn)上的數(shù)據(jù)更改時(shí),它們都會(huì)自動(dòng)更新或失效。

#8.1.配置近緩存

可以在緩存配置中為某個(gè)緩存配置近緩存:

  • XML
  • Java
  • C#/.NET
// Create a near-cache configuration for "myCache".
NearCacheConfiguration<Integer, Integer> nearCfg = new NearCacheConfiguration<>();// Use LRU eviction policy to automatically evict entries
// from near-cache whenever it reaches 100_000 entries
nearCfg.setNearEvictionPolicyFactory(new LruEvictionPolicyFactory<>(100_000));CacheConfiguration<Integer, Integer> cacheCfg = new CacheConfiguration<Integer, Integer>("myCache");cacheCfg.setNearConfiguration(nearCfg);// Create a distributed cache on server nodes
IgniteCache<Integer, Integer> cache = ignite.getOrCreateCache(cacheCfg);

以這種方式配置后,就在從底層緩存請(qǐng)求數(shù)據(jù)的任何節(jié)點(diǎn)(包括服務(wù)端節(jié)點(diǎn)和客戶(hù)端節(jié)點(diǎn))上創(chuàng)建近緩存。如以下示例所示,當(dāng)拿到緩存的實(shí)例時(shí),數(shù)據(jù)將通過(guò)近緩存獲得:

IgniteCache<Integer, Integer> cache = ignite.cache("myCache");int value = cache.get(1);

CacheConfiguration中與近緩存有關(guān)的大部分參數(shù)都會(huì)繼承于底層緩存的配置,比如,如果底層緩存有一個(gè)ExpiryPolicy配置,近緩存中的條目也會(huì)基于同樣的策略。

下表中列出的參數(shù)是不會(huì)從底層配置中繼承的:

參數(shù)描述默認(rèn)值
nearEvictionPolicy近緩存退出策略無(wú)
nearStartSize近緩存初始大小(可持有的條目數(shù))375,000

#8.2.客戶(hù)端節(jié)點(diǎn)動(dòng)態(tài)創(chuàng)建近緩存

從客戶(hù)端節(jié)點(diǎn)向尚未配置近緩存的緩存發(fā)出請(qǐng)求時(shí),可以為該緩存動(dòng)態(tài)創(chuàng)建近緩存,通過(guò)在客戶(hù)端本地存儲(chǔ)“熱”數(shù)據(jù)來(lái)提高性能。此緩存僅在創(chuàng)建它的節(jié)點(diǎn)上生效。

為此,創(chuàng)建一個(gè)近緩存配置并將其作為參數(shù)傳遞給獲取緩存實(shí)例的方法:

  • Java
  • C#/.NET
// Create a near-cache configuration
NearCacheConfiguration<Integer, String> nearCfg = new NearCacheConfiguration<>();// Use LRU eviction policy to automatically evict entries
// from near-cache, whenever it reaches 100_000 in size.
nearCfg.setNearEvictionPolicyFactory(new LruEvictionPolicyFactory<>(100_000));// get the cache named "myCache" and create a near cache for it
IgniteCache<Integer, String> cache = ignite.getOrCreateNearCache("myCache", nearCfg);String value = cache.get(1);

數(shù)據(jù)再平衡

#1.數(shù)據(jù)再平衡

#1.1.概述

當(dāng)一個(gè)新節(jié)點(diǎn)加入集群時(shí),部分分區(qū)會(huì)被分配至新的節(jié)點(diǎn),以使整個(gè)集群的數(shù)據(jù)保持平均分布,這個(gè)過(guò)程稱(chēng)為數(shù)據(jù)再平衡。

如果現(xiàn)有節(jié)點(diǎn)永久離開(kāi)集群,并且未配置備份,則會(huì)丟失此節(jié)點(diǎn)上存儲(chǔ)的分區(qū)。配置備份后,丟失分區(qū)的備份副本之一將成為主分區(qū),并開(kāi)始再平衡過(guò)程。

警告

數(shù)據(jù)再平衡由基線拓?fù)涞淖兓|發(fā)。在純內(nèi)存集群中,默認(rèn)行為是在節(jié)點(diǎn)離開(kāi)或加入集群時(shí)(基線拓?fù)渥詣?dòng)更改)立即開(kāi)始再平衡。在開(kāi)啟持久化的集群中,默認(rèn)必須手動(dòng)更改基線拓?fù)?#xff0c;或者在啟用基線自動(dòng)調(diào)整后可以自動(dòng)更基線拓?fù)洹?/p>

再平衡是緩存級(jí)的配置。

#1.2.配置再平衡模式

Ignite支持同步和異步的再平衡,在同步模式中,再平衡結(jié)束前緩存的任何操作都會(huì)被阻塞。在異步模式中,再平衡過(guò)程以異步的模式執(zhí)行,也可以為某個(gè)緩存禁用再平衡。

如果要修改再平衡模式,可以在緩存配置中配置如下的值:

  • SYNC:同步再平衡模式,再平衡結(jié)束前緩存的任何操作都會(huì)被阻塞;
  • ASYNC:異步再平衡模式,緩存直接可用,然后在后臺(tái)會(huì)從其它節(jié)點(diǎn)加載所有必要的數(shù)據(jù);
  • NONE:該模式下不會(huì)發(fā)生再平衡,這意味著要么在訪問(wèn)數(shù)據(jù)時(shí)從持久化存儲(chǔ)載入,要么數(shù)據(jù)被顯式地填充。
  • XML
  • Java
  • C#/.NET
IgniteConfiguration cfg = new IgniteConfiguration();CacheConfiguration cacheCfg = new CacheConfiguration("mycache");cacheCfg.setRebalanceMode(CacheRebalanceMode.SYNC);cfg.setCacheConfiguration(cacheCfg);// Start a node.
Ignite ignite = Ignition.start(cfg);

#1.3.配置再平衡線程池

默認(rèn)一個(gè)節(jié)點(diǎn)只會(huì)有一個(gè)線程用于再平衡,這意味著在一個(gè)特定的時(shí)間點(diǎn)只有一個(gè)線程用于從一個(gè)節(jié)點(diǎn)到另一節(jié)點(diǎn)傳輸批量數(shù)據(jù),或者處理來(lái)自遠(yuǎn)端的批量數(shù)據(jù)。

可以從系統(tǒng)線程池中拿到更多的線程數(shù)用于再平衡。每當(dāng)節(jié)點(diǎn)需要將一批數(shù)據(jù)發(fā)送到遠(yuǎn)端節(jié)點(diǎn)或需要處理來(lái)自遠(yuǎn)端節(jié)點(diǎn)的一批數(shù)據(jù)時(shí),都會(huì)從池中獲取系統(tǒng)線程,批次處理完成后,該線程會(huì)被釋放。

  • XML
  • Java
IgniteConfiguration cfg = new IgniteConfiguration();cfg.setRebalanceThreadPoolSize(4);CacheConfiguration cacheCfg = new CacheConfiguration("mycache");
cfg.setCacheConfiguration(cacheCfg);// Start a node.
Ignite ignite = Ignition.start(cfg);

警告

在內(nèi)部,系統(tǒng)線程池廣泛用于和緩存有關(guān)的所有操作(put,get等),SQL引擎和其它模塊,因此將再平衡線程池設(shè)置為一個(gè)很大的值會(huì)顯著提高再平衡的性能,但是會(huì)影響應(yīng)用的吞吐量。

#1.4.再平衡消息限流

當(dāng)數(shù)據(jù)從一個(gè)節(jié)點(diǎn)傳輸?shù)搅硪粋€(gè)節(jié)點(diǎn)時(shí),整個(gè)數(shù)據(jù)集會(huì)被拆分為多個(gè)批次然后將每一個(gè)批次作為一個(gè)單獨(dú)的消息進(jìn)行發(fā)送,批次的大小和節(jié)點(diǎn)在消息之間的等待時(shí)間,都是可以配置的。

  • XML
  • Java
  • C#/.NET
IgniteConfiguration cfg = new IgniteConfiguration();CacheConfiguration cacheCfg = new CacheConfiguration("mycache");cfg.setRebalanceBatchSize(2 * 1024 * 1024);
cfg.setRebalanceThrottle(100);cfg.setCacheConfiguration(cacheCfg);// Start a node.
Ignite ignite = Ignition.start(cfg);

#1.5.其他配置

下表列出了CacheConfiguration中和再平衡有關(guān)的屬性:

屬性描述默認(rèn)值
rebalanceBatchSize單個(gè)再平衡消息的大小(字節(jié)),在每個(gè)節(jié)點(diǎn)再平衡算法會(huì)將數(shù)據(jù)拆分為多個(gè)批次,然后再將其發(fā)送給其他節(jié)點(diǎn)。512KB
rebalanceDelay當(dāng)節(jié)點(diǎn)加入或者離開(kāi)集群時(shí),再平衡過(guò)程啟動(dòng)的延遲時(shí)間(毫秒),如果打算在節(jié)點(diǎn)離開(kāi)拓?fù)浜笾貑⒐?jié)點(diǎn),或者打算在同時(shí)/一個(gè)個(gè)啟動(dòng)多個(gè)節(jié)點(diǎn)的過(guò)程中,所有節(jié)點(diǎn)都啟動(dòng)完成之前不進(jìn)行重新分區(qū)或者再平衡,也可以推遲。0,無(wú)延遲
rebalanceOrder完成再平衡的順序,只有SYNCASYNC再平衡模式的緩存才可以將再平衡順序設(shè)置為非0值,具有更小值的緩存再平衡會(huì)被首先完成,再平衡默認(rèn)是無(wú)序的。0
rebalanceThrottle請(qǐng)參見(jiàn)再平衡消息限流0(限流禁用)
rebalanceTimeout節(jié)點(diǎn)間交換再平衡消息的掛起超時(shí)。10秒

#1.6.再平衡過(guò)程監(jiān)控

通過(guò)JMX可以監(jiān)控緩存的再平衡過(guò)程。

http://www.risenshineclean.com/news/22077.html

相關(guān)文章:

  • 微信直接轉(zhuǎn)wordpress包頭整站優(yōu)化
  • 用python做網(wǎng)站不常見(jiàn)百度人工服務(wù)24小時(shí)
  • 東莞網(wǎng)站建設(shè)公司 網(wǎng)絡(luò)服務(wù)杭州推廣公司
  • 58同城鹽城網(wǎng)站建設(shè)東莞網(wǎng)站排名提升
  • 怎樣給網(wǎng)站做軟件測(cè)試營(yíng)銷(xiāo)型網(wǎng)站建設(shè)哪家好
  • 企業(yè)網(wǎng)站管理系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn)網(wǎng)絡(luò)營(yíng)銷(xiāo)與直播電商專(zhuān)業(yè)學(xué)什么
  • 蕪湖網(wǎng)站開(kāi)發(fā)小程序怎么引流推廣
  • 武漢眼前一亮科技內(nèi)蒙古seo
  • wordpress 全站不刷新百度識(shí)圖入口
  • 賣(mài)建材的網(wǎng)站找seo外包公司需要注意什么
  • 前端手機(jī)網(wǎng)站seo定義
  • 凡科網(wǎng)的網(wǎng)站建設(shè)怎么做百度百家自媒體平臺(tái)注冊(cè)
  • 新媒體seo培訓(xùn)seo研究中心南寧線下
  • 昆明快速做網(wǎng)站海南網(wǎng)站制作
  • 網(wǎng)站服務(wù)器租用價(jià)格表怎么從網(wǎng)上找國(guó)外客戶(hù)
  • 藍(lán)色網(wǎng)站素材搜索引擎推廣案例
  • 企業(yè)logo設(shè)計(jì)app搜狗seo怎么做
  • 做淘寶要用到哪些網(wǎng)站中國(guó)優(yōu)化網(wǎng)
  • asp網(wǎng)站圖片怎樣建立自己網(wǎng)站
  • 神州順利辦深一做網(wǎng)站百度搜索排行seo
  • 網(wǎng)絡(luò)營(yíng)銷(xiāo)資訊網(wǎng)站重慶網(wǎng)站推廣聯(lián)系方式
  • 網(wǎng)站怎么做白色字蘇州吳中區(qū)seo關(guān)鍵詞優(yōu)化排名
  • 網(wǎng)站怎樣做seo成功營(yíng)銷(xiāo)案例分享
  • 昆明網(wǎng)站做項(xiàng)目推廣平臺(tái)有哪些
  • 新手站長(zhǎng)如何購(gòu)買(mǎi)虛擬主機(jī)做網(wǎng)站seo對(duì)各類(lèi)網(wǎng)站的作用
  • 哪個(gè)網(wǎng)站可以懸賞做圖宣傳推廣的十種方式
  • 國(guó)內(nèi)環(huán)保行業(yè)網(wǎng)站開(kāi)發(fā)seo獨(dú)立站
  • 自己做的網(wǎng)站主頁(yè)打開(kāi)速度上海百度分公司電話
  • 裝飾裝修網(wǎng)站建設(shè)方案做網(wǎng)絡(luò)銷(xiāo)售如何找客戶(hù)
  • crm辦公系統(tǒng)武漢關(guān)鍵詞seo