apache ignite系列(四):持久化
ignite持久化與固化內(nèi)存
1.持久化的機(jī)制
ignite持久化的關(guān)鍵點(diǎn)如下:
ignite持久化可防止內(nèi)存溢出導(dǎo)致數(shù)據(jù)丟失的情況;
持久化可以定制化配置,按需持久化;
持久化能解決在大量緩存數(shù)據(jù)情況下ignite節(jié)點(diǎn)啟動(dòng)緩慢的問題;
使用持久化后,ignite能存儲(chǔ)海量的數(shù)據(jù);
使用持久化之后需要手工啟動(dòng)集群;
持久化涉及到的一個(gè)關(guān)鍵點(diǎn)就是WAL,所謂WAL就是預(yù)寫日志,目的是為了保證在持久化機(jī)制下數(shù)據(jù)寫入的性能,其原理圖如下所示:
? 在ignite中,對(duì)內(nèi)存中數(shù)據(jù)的操作并不會(huì)立即同步到持久化文件(Partition File)中,而是先記錄在預(yù)寫日志(Write-Ahead Log)中,檢查點(diǎn)線程(Checkpointing)將內(nèi)存中的臟數(shù)據(jù)(dirty page)同步到持久化文件中,并且會(huì)將預(yù)寫日志中的過期數(shù)據(jù)刪除。
? dirty page:在wal文件中但是還沒寫入partition files中,當(dāng)dirty page 比例占到內(nèi)存數(shù)據(jù)的2/3的時(shí)候會(huì)觸發(fā)checkpoint機(jī)制。
? checkpoint : 將內(nèi)存中的數(shù)據(jù)同步到partition files中,當(dāng)checkpoint結(jié)束之后,wal會(huì)歸檔,開啟一個(gè)新的wal文件。
? wal可以防止在極端情況下,比如斷電,程序崩潰的情況下數(shù)據(jù)丟失,但是如果wal中的數(shù)據(jù)過多,那么在ignite啟動(dòng)的時(shí)候從wal讀取數(shù)據(jù)勢(shì)必會(huì)導(dǎo)致啟動(dòng)速度緩慢,因?yàn)閺膚al中讀取數(shù)據(jù)的速度遠(yuǎn)比從partition files中讀取數(shù)據(jù)的速度慢。緩存配置項(xiàng)中有個(gè)'writeThrottlingEnabled' 配置項(xiàng)可以改善這個(gè)情況,除此之外,還可以調(diào)整檢查點(diǎn)的線程數(shù)以及同步頻率來提升預(yù)寫日志的效率,相關(guān)配置如下所示:
<property name="dataStorageConfiguration">
<bean class="org.apache.ignite.configuration.DataStorageConfiguration">
......
<!-- Threads that generate dirty pages too fast during ongoing checkpoint will be throttled -->
<property name="writeThrottlingEnabled" value="true"/>
<!--Checkpointing frequency which is a minimal interval when the dirty pages will be written to the Persistent Store.-->
<!-- 檢查點(diǎn)頻率 -->
<property name="checkpointFrequency" value="180000"/>
<!-- Number of threads for checkpointing.-->
<!-- 檢查點(diǎn)線程數(shù) -->
<property name="checkpointThreads" value="4"/>
<!-- 在檢查點(diǎn)同步完成后預(yù)寫日志歷史保留數(shù)量
<!-- Number of checkpoints to be kept in WAL after checkpoint is finished.-->
<property name="walHistorySize" value="20"/>
......
</bean>
</property>
?
? WAL有幾種模式可以選擇,可以關(guān)閉WAL或者強(qiáng)同步模式,保證數(shù)據(jù)在苛刻條件下也不會(huì)丟失,設(shè)置方式如下:
<!-- 設(shè)置持久化預(yù)寫日志模式. -->
<property name="walMode">
<util:constant static-field="org.apache.ignite.configuration.WALMode.DEFAULT"/>
</property>
2. 通過配置開啟持久化:
ignite中對(duì)于存儲(chǔ)有個(gè)內(nèi)存區(qū)的概念,每個(gè)cache默認(rèn)使用的是Default_Region,可以自定義內(nèi)存區(qū),然后在定義緩存的時(shí)候指定緩存區(qū),這樣可以做到個(gè)性化持久化,比如有些緩存的數(shù)據(jù)量比較小,那么就沒有持久化的必要,而有些表數(shù)據(jù)量比較大,而且還在持續(xù)增長(zhǎng),需要開啟持久化防止內(nèi)存溢出,這時(shí)可以通過自定義內(nèi)存區(qū)將兩者緩存區(qū)分開來,實(shí)現(xiàn)定制化持久化。
xml配置:
<!-- Consistent globally unique node identifier which survives node restarts. -->
<!-- 設(shè)置節(jié)點(diǎn)固定的一致性id,使得節(jié)點(diǎn)使用專用目錄和數(shù)據(jù)分區(qū) -->
<property name="consistentId" value="ABC"/>
<!-- 節(jié)點(diǎn)自定義存儲(chǔ)配置 -->
<property name="dataStorageConfiguration">
<bean class="org.apache.ignite.configuration.DataStorageConfiguration">
<!-- Redefining the default region's settings -->
<property name="defaultDataRegionConfiguration">
<bean class="org.apache.ignite.configuration.DataRegionConfiguration">
<property name="name" value="Default_Region"/>
<!-- 設(shè)置默認(rèn)內(nèi)存區(qū)最大內(nèi)存為 1GB. -->
<property name="maxSize" value="#{1L * 1024 * 1024 * 1024}"/>
<!-- 默認(rèn)內(nèi)存區(qū)開啟持久化. -->
<property name="persistenceEnabled" value="true"/>
</bean>
</property>
<property name="dataRegionConfigurations">
<list>
<!-- 自定義內(nèi)存區(qū)并開啟持久化-->
<bean class="org.apache.ignite.configuration.DataRegionConfiguration">
<!-- 內(nèi)存區(qū)名. -->
<property name="name" value="500MB_Region"/>
<!-- 100 MB initial size. -->
<property name="initialSize" value="#{100L * 1024 * 1024}"/>
<!-- 500 MB maximum size. -->
<property name="maxSize" value="#{500L * 1024 * 1024}"/>
<!-- 開啟持久化. -->
<property name="persistenceEnabled" value="true"/>
</bean>
</list>
</property>
<!-- 設(shè)置持久化預(yù)寫日志模式. -->
<property name="walMode">
<util:constant static-field="org.apache.ignite.configuration.WALMode.DEFAULT"/>
</property>
<!-- 持久化文件存儲(chǔ)路徑. -->
<!-- <property name="storagePath" value="D:\Test\db" /> -->
<property name="storagePath" value="/data/local/db" />
<!-- 預(yù)寫日志存儲(chǔ)路徑. -->
<!-- <property name="walPath" value="D:\Test\db\wal" /> -->
<property name="walPath" value="/data/local/db/wal" />
<!-- 預(yù)寫日志解壓路徑. -->
<!-- <property name="walArchivePath" value="D:\Test\db\wal\archive" /> -->
<property name="walArchivePath" value="/data/local/db/wal/archive" />
</bean>
</property>
java配置:
private static final String usrDir = System.getProperty("user.dir");
private static final String separator = File.separator;
private static final String DB = "db";
private static final String WAL = "wal";
private static final String ARCHIVE = "archive";
/**設(shè)置一致性Id*/
igniteCfg.setConsistentId("ABC");
/**ignite持久化配置*/
DataStorageConfiguration dcfg = igniteCfg.getDataStorageConfiguration();
dcfg.getDefaultDataRegionConfiguration()
.setMaxSize(4L * 1024 * 1024 * 1024) //設(shè)置默認(rèn)區(qū)域的最大可用內(nèi)存
.setPersistenceEnabled(true); //默認(rèn)區(qū)域開啟持久化
//設(shè)置持久化路徑
dcfg.setStoragePath(String.format("%s%s%s", usrDir, separator, DB));
dcfg.setWalPath(String.format("%s%s%s%s%s", usrDir, separator, DB, separator, WAL));
dcfg.setWalArchivePath(String.format("%s%s%s%s%s%s%s", usrDir, separator, DB, separator, WAL, separator, ARCHIVE));
相關(guān)說明:
1.1 設(shè)置consistentId的原因:
?默認(rèn)狀態(tài)下,如果節(jié)點(diǎn)重啟,那么ignite會(huì)隨機(jī)生成一個(gè)全局唯一的consistentId, 而持久化的磁盤路徑是用consistentId 區(qū)分的,如果重啟之后那么無法再讀取原來區(qū)間的持久化文件,但是指定consistentId就可以使用固定空間,使用之前的持久化文件。
如果一臺(tái)主機(jī)啟動(dòng)了若干個(gè)節(jié)點(diǎn),那么每個(gè)節(jié)點(diǎn)進(jìn)程都會(huì)在一個(gè)預(yù)定義的唯一子目錄中,比如
${IGNITE_HOME}/work/db/node{IDX}-{UUID},有自己的持久化文件,這里IDX和UUID參數(shù)都是Ignite在節(jié)點(diǎn)啟動(dòng)時(shí)自動(dòng)計(jì)算的(這里有詳細(xì)描述)。如果在持久化層次結(jié)構(gòu)中已經(jīng)有了若干node{IDX}-{UUID}子目錄,那么他們是按照節(jié)點(diǎn)先入先出的順序進(jìn)行賦值的。如果希望某節(jié)點(diǎn)即使重啟也有專用目錄和專用的數(shù)據(jù)分區(qū),需要在集群范圍配置唯一的IgniteConfiguration.setConsistentId,這個(gè)唯一ID會(huì)在node{IDX}-{UUID}字符串中映、射setStoragePath(...)到、setWalArchivePath(...)ffUUID`。
1.2 自定義存儲(chǔ)區(qū)域的使用方式:
? 默認(rèn)配置下,緩存使用的是默認(rèn)內(nèi)存區(qū)(defaultDataRegionConfiguration),也可以自定義內(nèi)存區(qū),如上面配置文件中定義的"500MB_Region"。這樣可以將需要持久化的數(shù)據(jù)和不需要持久化的數(shù)據(jù)分離出來,但是使用自定義的內(nèi)存區(qū)的時(shí)候需要設(shè)置額外的屬性:
<property name="cacheConfiguration">
<list>
<bean class="org.apache.ignite.configuration.CacheConfiguration">
...
<property name="dataRegionName" value="500MB_Region"/>
...
</bean>
</list>
</property>
// Creating a cache configuration.
CacheConfiguration cacheCfg = new CacheConfiguration();
// Binding the cache to the earlier defined region.
cacheCfg.setDataRegionName("500MB_Region");
1.3 啟用持久化之后需要手工激活集群:
集群激活
注意如果開啟了Ignite持久化,集群默認(rèn)是未激活的,無法進(jìn)行任何的CRUD操作。用戶需要手工激活集群,后面會(huì)介紹如何進(jìn)行操作。
集群激活方式:
a. 代碼激活:
// Activating the cluster once all the cluster nodes are up and running.
if(!ignite.active()) {
ignite.active(true); //如果集群未啟動(dòng)則啟動(dòng)集群
}
b. web控制臺(tái):
c. 命令激活:
在命令行中,使用$IGNITE_HOME/bin文件夾中的control.sh|bat腳本,比如
.sh:
control.sh|bat
./control.sh --activate
.bat:
./control.bat --activate
1.4 ignite的destroyCache()方法同樣會(huì)清除持久化文件.
destroyCache同樣會(huì)清除持久化文件,但是持久化的緩存配置不會(huì)清除, 所以重啟之后會(huì)出現(xiàn)容量為空的cache。如果要?jiǎng)討B(tài)修改cache配置,必須先destroyCache,再做調(diào)整;
3. 持久化相關(guān)測(cè)試:
持久化占用的磁盤空間大小,以及持久化對(duì)于節(jié)點(diǎn)啟動(dòng)速度的提升:
| 數(shù)據(jù)量 | 磁盤占用 | 未持久化啟動(dòng) | 持久化后啟動(dòng) |
|---|---|---|---|
| 350w(生產(chǎn)數(shù)據(jù)) | 分區(qū)文件5.6g, 預(yù)寫日志7.0g | 2分鐘 | 39s |
| 2400w(本地?cái)?shù)據(jù)) | 分區(qū)文件6.76g,預(yù)寫日志12.1g | .......(內(nèi)存溢出) | 12s |
?
總結(jié)
以上是生活随笔為你收集整理的apache ignite系列(四):持久化的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Power | PTPX功耗分析实战,
- 下一篇: Nginx重要概念之keepalive