如何配置Apache Ignite集群数据持久?
- By : Will
- Category : Big Data Framework
1 基础知识
1.1 数据持久化的概念
– Ignite持久化旨在提供持久化存储的一组功能
– Ignite持久化会将所有数据存储在磁盘上并将尽可能的数据加载到内存中。
– Ignite如果关闭持久化则是一个纯内存存储。
1.2 数据持久化的特点
– 启用持久化后Ignite会将每个分区存储到单独的磁盘文件夹
– 启用持久性后,数据在内存中缓存满后,多余的数据会被写到磁盘中
– 在内存缓存加本地持久化模式下,内存中新增记录都会添加到预读写日志(WAL)
– 预读写日志的目的是实现以最快速度更新到磁盘并提供完整的集群故障数据一致性恢复机制
– 预读写日志增长到一定程度会定期在主存储中设置检查点
– 检查点是实现将脏页(写有数据内存缓存页)中的数据写入磁盘的过程
– 操作系统SWAP的使用
1.3 启用数据持久化
– 数据区配置“persistenceEnabled”为“true”
– 启用后节点会在存储目录(“{IGNITE_WORK_DIR}/db”)存储用户数据、索引和WAL文件
– 通过配置“DataStorageConfiguration”和“storagePath”可修改存储目录
– 数据详细存储如下,
子目录名 | 描述 |
---|---|
{WORK_DIR}/db/{nodeId} |
该目录中包括了缓存的数据和索引 |
{WORK_DIR}/db/wal/{nodeId} |
该目录中包括了WAL文件 |
{WORK_DIR}/db/wal/archive/{nodeId} |
该目录中包括了WAL存档文件 |
注:
– nodeID支持节点配置中定义唯一的ID或自动生成
– nodeID用于确保节点目录的唯一性(如果多个节点共享一个目录则使用不同子目录存储)
默认的持久化范例,
<bean class="org.apache.ignite.configuration.IgniteConfiguration"> <property name="dataStorageConfiguration"> <bean class="org.apache.ignite.configuration.DataStorageConfiguration"> <property name="defaultDataRegionConfiguration"> <bean class="org.apache.ignite.configuration.DataRegionConfiguration"> <property name="persistenceEnabled" value="true"/> </bean> </property> </bean> </property> </bean>
指定存储目录的持久化范例,
<bean class="org.apache.ignite.configuration.IgniteConfiguration"> <property name="dataStorageConfiguration"> <bean class="org.apache.ignite.configuration.DataStorageConfiguration"> <property name="defaultDataRegionConfiguration"> <bean class="org.apache.ignite.configuration.DataRegionConfiguration"> <property name="persistenceEnabled" value="true"/> </bean> </property> <property name="storagePath" value="/opt/storage"/> </bean> </property> </bean>
1.4 预写日志
1.4.1 预读写日志的概念
– 预写日志是节点记录所有数据修改操作(包括删除)的日志
– 更新内存页面时,更新不会直接写入分区文件,而是会附加到WAL末尾
– 预写日志用于点节或集群故障恢复,故障或重启时靠WAL的内容恢复到最近的成功事务
– WAL由活动段(默认10个文件)和存档文件组成
– 活动段按顺序填充,然后循环覆盖,第一段写满后,其内容复制到WAL文档中
– 复制第一段时,第二段会被视为激活的WAL文件并接受来自应用端的所有更新
1.4.2 WAL的模式
WAL有几种模式,每种模式对性能影响不一样,
WAL模式 | 描述 | 一致性保证 |
---|---|---|
FSYNC |
保证每个原子写或者事务性提交都会持久化到磁盘。 | 数据更新不会丢失,不管是任何的操作系统或者进程故障,甚至是电源故障。 |
LOG_ONLY |
默认模式,对于每个原子写或者事务性提交,保证会刷新到操作系统的缓冲区缓存或者内存映射文件。默认会使用内存映射文件方式,并且可以通过将IGNITE_WAL_MMAP 系统属性配置为false 将其关闭。 |
如果仅仅是进程崩溃数据更新会保留。 |
BACKGROUND |
如果打开了IGNITE_WAL_MMAP 属性(默认),该模式的行为类似于LOG_ONLY 模式,如果关闭了内存映射文件方式,变更会保持在节点的内部缓冲区,缓冲区刷新到磁盘的频率由walFlushFrequency 参数定义。 |
如果打开了IGNITE_WAL_MMAP 属性(默认),该模式提供了与LOG_ONLY 模式一样的保证,否则如果进程故障或者其它的故障发生时,最近的数据更新可能丢失。 |
NONE |
WAL被禁用,只有在节点优雅地关闭时,变更才会正常持久化,使用Ignite#active(false) 可以冻结集群然后停止节点。 |
可能出现数据丢失,如果节点在更新操作期间突然终止,则磁盘上存储的数据很可能出现不同步或损坏。 |
1.4.3 WAL的存档
– WAL存档用于保存故障恢复点所需的WAL段,存档段所有段总大小确保不超过WAL存档的设定大小。
– WAL存档最大大小定义为检查点缓冲区大小的4倍(该值配置可修改)
1.4.4 WAL的修改
– 高负载情况下,默认WAL段大小(64M)可能效率不高
– 高负载情况下,会导致WAL过于频繁地在段之间切换(切换、轮转是一项昂贵的操作)
– 高负载情况下,加大WAL段大小有助于提高负载的性能(代价是增加WAL文件和WAL归档文件的总大小)
– WAL段大小必须介于512KB和2GB之间,配置范例如下,
<bean class="org.apache.ignite.configuration.IgniteConfiguration" id="ignite.cfg"> <property name="dataStorageConfiguration"> <bean class="org.apache.ignite.configuration.DataStorageConfiguration"> <!-- set the size of wal segments to 128MB --> <property name="walSegmentSize" value="#{128 * 1024 * 1024}"/> <property name="defaultDataRegionConfiguration"> <bean class="org.apache.ignite.configuration.DataRegionConfiguration"> <property name="persistenceEnabled" value="true"/> </bean> </property> </bean> </property> </bean>
1.4.5 WAL的禁用
– 禁用或启用WAL只能在稳定的拓扑上进行(即所有极限节点都在线,期间不允许增删集群节点)
– 非稳定的拓扑可能会导致缓存陷入不一致(不一致建议销毁受影响的缓存)
– 如数据初始化期间禁用WAL并预加载后启用WAL是建议的,禁用范例如下,
ALTER TABLE Person NOLOGGING //... ALTER TABLE Person LOGGING
注:如果禁用WAL并重启节点,则会从该节点上删除所有持久化数据(没有WAL则无法保证节点故障或重启的数据一致性)
1.4.6 WAL的存档压缩
– 启用WAL存档压缩可减少对空间的占用
– WAL存档默认包含最后20个检查点的端(数量可修改)
– 启用压缩后,仅保留1个检查点的存档段不压缩,其余均使用ZIP压缩。
– 如果需要使用压缩数据再平衡节点数据,则需要将压缩数据解压。
1.4.7 WAL的记录压缩
– WAL记录压缩支持内存中先压缩后存盘
– WAL记录压缩默认是禁用的
– 启用该功能需要启用ignite-compress模块且配置数据存储配置中设置压缩算法和压缩级别,范例如下,
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);
1.4.8 WAL的存档禁用
– 当Ignite将数据写入WAL段快于将数据复制到存档文件时候禁用WAL存档能减少WAL段复制到存档文件的开销
– 速度的差异会导致I/O瓶颈,从而导致节点操作被冻结,此时可以尝试关闭WAL存档
– 通过将WAL路径和WAL存档配置为同一个值则可关闭存档(此时只在WAL文件夹中创建新端而不会复制存档文件)
1.5 检查点
– 脏页面是指已更新到内存中但未写入磁盘分区的内存页(只是添加到WAL中)
– 检查点是将脏页从内存复制到磁盘分区文件的过程
– 创建检查点后,所有更改将存盘且在节点故障并重启后生效
– 检查点与预写日志旨在确保数据持久化和节点故障是能恢复
1.6 数据存储配置
属性名 | 描述 | 默认值 |
---|---|---|
persistenceEnabled |
将该属性配置为true 可以开启原生持久化。 |
false |
storagePath |
数据存储路径。 | ${IGNITE_HOME}/work/db/node{IDX}-{UUID} |
walPath |
WAL活动段存储路径。 | ${IGNITE_HOME}/work/db/wal/ |
walArchivePath |
WAL存档路径。 | ${IGNITE_HOME}/work/db/wal/archive/ |
walCompactionEnabled |
将该属性配置为true 可以开启WAL存档压缩。 |
false |
walSegmentSize |
WAL段文件大小(字节)。 | 64MB |
walMode |
预写日志模式。 | LOG_ONLY |
walCompactionLevel |
WAL压缩级别,1 表示速度最快,9 表示最高的压缩率。 |
1 |
maxWalArchiveSize |
WAL存档占用空间最大值(字节)。 | 检查点缓冲区大小的4倍 |
2 最佳实践
2.1 环境配置
配置Ignite集群环境,
2.2 配置存储持久化
停止其他集群节点
ssh ignite-node2 systemctl stop apache-ignite.service
ssh ignite-node3 systemctl stop apache-ignite.service
修改配置文件
vim /etc/apache-ignite/default-config.xml
配置修改如下,
<?xml version="1.0" encoding="UTF-8"?> <!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <!-- Ignite configuration with all defaults and enabled p2p deployment and enabled events. --> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> <bean abstract="true" id="ignite.cfg" class="org.apache.ignite.configuration.IgniteConfiguration"> <!-- Set to true to enable distributed class loading for examples, default is false. --> <property name="peerClassLoadingEnabled" value="true"/> <!-- Enable task execution events for examples. --> <property name="includeEventTypes"> <list> <!--Task execution events--> <util:constant static-field="org.apache.ignite.events.EventType.EVT_TASK_STARTED"/> <util:constant static-field="org.apache.ignite.events.EventType.EVT_TASK_FINISHED"/> <util:constant static-field="org.apache.ignite.events.EventType.EVT_TASK_FAILED"/> <util:constant static-field="org.apache.ignite.events.EventType.EVT_TASK_TIMEDOUT"/> <util:constant static-field="org.apache.ignite.events.EventType.EVT_TASK_SESSION_ATTR_SET"/> <util:constant static-field="org.apache.ignite.events.EventType.EVT_TASK_REDUCED"/> <!--Cache events--> <util:constant static-field="org.apache.ignite.events.EventType.EVT_CACHE_OBJECT_PUT"/> <util:constant static-field="org.apache.ignite.events.EventType.EVT_CACHE_OBJECT_READ"/> <util:constant static-field="org.apache.ignite.events.EventType.EVT_CACHE_OBJECT_REMOVED"/> </list> </property> <!-- Explicitly configure TCP discovery SPI to provide list of initial nodes. --> <property name="discoverySpi"> <bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi"> <property name="ipFinder"> <!-- Ignite provides several options for automatic discovery that can be used instead os static IP based discovery. For information on all options refer to our documentation: http://apacheignite.readme.io/docs/cluster-config --> <!-- Uncomment static IP finder to enable static-based discovery of initial nodes. --> <!--<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder">--> <bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMulticastIpFinder"> <property name="addresses"> <list> <!-- In distributed environment, replace with actual host IP address. --> <value>ignite-node1.cmdschool.org:47500..47509</value> <value>ignite-node2.cmdschool.org:47500..47509</value> <value>ignite-node3.cmdschool.org:47500..47509</value> </list> </property> </bean> </property> </bean> </property> <!-- Enabling Apache Ignite Persistent Store. --> <property name="dataStorageConfiguration"> <bean class="org.apache.ignite.configuration.DataStorageConfiguration"> <property name="defaultDataRegionConfiguration"> <bean class="org.apache.ignite.configuration.DataRegionConfiguration"> <property name="persistenceEnabled" value="true"/> </bean> </property> <property name="storagePath" value="/data/ignite/storage"/> </bean> </property> </bean> </beans>
然后,使用如下命令分发配置到集群其他节点,
scp /etc/apache-ignite/default-config.xml ignite-node2:/etc/apache-ignite/ scp /etc/apache-ignite/default-config.xml ignite-node3:/etc/apache-ignite/
根据配置文件,我们需要创建数据持久化目录,
ssh ignite-node1 mkdir -p /data ssh ignite-node2 chown ignite:ignite /data/ ssh ignite-node2 mkdir -p /data ssh ignite-node2 chown ignite:ignite /data/ ssh ignite-node3 mkdir -p /data ssh ignite-node3 chown ignite:ignite /data/
2.3 重启服务使配置生效
In ignite-node1,
ssh ignite-node1 systemctl restart apache-ignite.service ssh ignite-node2 systemctl restart apache-ignite.service ssh ignite-node3 systemctl restart apache-ignite.service
没有评论