Skip to content

持久化数据

1.概述

1.1.关于本章节

本章节将介绍在 Docker 环境中使用 Ignite 的 RocksDB 存储引擎和 Chinook 数据库的基础知识。

1.2.前提条件

  • 最新版本的 Docker 和 Docker Compose;
  • 可以访问终端或命令行;
  • 掌握基本的 SQL 知识;
  • Ignite 集群至少有 8GB 的可用内存。

2.了解 Ignite 3 中的持久化

2.1.持久化架构

Ignite 的持久化在设计时即面向高性能,其提供如下的能力:

  • Ignite 将其所有数据存储在磁盘上;
  • 将尽可能多的数据加载到内存中进行处理;
  • 数据被拆分为多个分区,每个分区存储在磁盘上的单独文件中;
  • 除了数据分区之外,Ignite 还将索引和元数据存储在磁盘上。

该架构将内存计算的性能优势与基于磁盘存储的持久化结合起来。

2.2.存储引擎类型

2.2.1.持久化存储选项

  • AIPersist 引擎:具有检查点的默认持久化存储引擎;
  • RocksDB 引擎:基于 LSM 树的持久化存储,面向写入密集型的负载进行了优化。

2.2.2.易失性存储选项

  • AIMem 引擎:没有持久化的内存存储。

2.3.存储方案

在 Ignite 3 中,持久化是在存储方案中配置的,存储方案定义了存储引擎如何存储、缓存和管理数据。

每个存储方案都有特定的属性,具体取决于引擎类型,但所有存储方案都必须指定以下属性:

  • name:存储方案的唯一标识符;
  • engine:要使用的存储引擎。

2.4.分布区

分布区控制数据在集群中的分布方式以及要使用的存储方案,其提供了如下的能力:

  • 控制数据副本数量;
  • 指定哪些节点可以存储数据;
  • 定义数据的分区方式;
  • 分配存储方案以确定持久化类型。

3.设置持久化集群

3.1.Docker 环境配置

这里会使用 Docker Compose 创建一个具有持久化存储的多节点 Ignite 集群。

3.2.创建 Docker Compose 配置文件

在工作目录中创建一个docker-compose.yml文件:

yml
name: ignite3

x-ignite-def: &ignite-def
  image: apacheignite/ignite:3.1.0
  environment:
    JVM_MAX_MEM: "4g"
    JVM_MIN_MEM: "4g"
  configs:
    - source: node_config
      target: /opt/ignite/etc/ignite-config.conf

services:
  node1:
    <<: *ignite-def
    command: --node-name node1
    ports:
      - "10300:10300"
      - "10800:10800"
    volumes:
      - ./data/node1:/opt/ignite/work

  node2:
    <<: *ignite-def
    command: --node-name node2
    ports:
      - "10301:10300"
      - "10801:10800"
    volumes:
      - ./data/node2:/opt/ignite/work

  node3:
    <<: *ignite-def
    command: --node-name node3
    ports:
      - "10302:10300"
      - "10802:10800"
    volumes:
      - ./data/node3:/opt/ignite/work

configs:
  node_config:
    content: |
      ignite {
        network {
          port: 3344
          nodeFinder.netClusterNodes = ["node1:3344", "node2:3344", "node3:3344"]
        }
        "storage": {
          "profiles": [
            {
              name: "rocksDbProfile"
              engine: "rocksdb"
            }
          ]
        }
      }

其中的node_config配置:

  • 添加一个名为rocksDbProfile的使用 RocksDB 引擎的存储方案;
  • 将存储大小设置为默认值 256MB(268435456 字节);
  • 将持久化数据存储在运行 Docker 的data目录中。

3.3.启动集群

执行以下命令启动集群:

shell
docker-compose up -d

3.4.验证集群

检查所有节点是否都在运行:

shell
docker compose ps

输出大致如下:

NAME              IMAGE                       COMMAND                  SERVICE   CREATED          STATUS          PORTS
ignite3-node1-1   apacheignite/ignite:3.1.0   "docker-entrypoint.s…"   node1     37 seconds ago   Up 33 seconds   0.0.0.0:10300->10300/tcp, 3344/tcp, 0.0.0.0:10800->10800/tcp
ignite3-node2-1   apacheignite/ignite:3.1.0   "docker-entrypoint.s…"   node2     37 seconds ago   Up 33 seconds   3344/tcp, 0.0.0.0:10301->10300/tcp, 0.0.0.0:10801->10800/tcp
ignite3-node3-1   apacheignite/ignite:3.1.0   "docker-entrypoint.s…"   node3     37 seconds ago   Up 33 seconds   3344/tcp, 0.0.0.0:10302->10300/tcp, 0.0.0.0:10802->10800/tcp

验证 Docker 网络:

shell
docker network ls

4.配置持久化存储

4.1.接入集群

连接到 Ignite 命令行工具:

shell
docker run --rm -it --network=host -e LANG=C.UTF-8 -e LC_ALL=C.UTF-8 apacheignite/ignite:3.1.0 cli

命令行工具会接入默认的节点,这个需要确认,如果连接被拒绝,可以通过键入以下命令重新连接:

shell
connect http://localhost:10300

4.2.初始化集群

使用集群之前需对其进行初始化:

shell
cluster init --name=ignite3

这时会看到luster was initialized successfully这样的消息。

4.3.检查存储方案

验证配置的存储方案:

shell
node config show ignite.storage

这时会看到显示rocksDbProfile配置以及默认配置文件的输出。

4.4.创建用于持久化的分布区

进入交互式 SQL 命令行:

shell
sql

创建一个使用 RocksDB 存储方案的分布区:

sql
CREATE ZONE ChinookRocksDB WITH replicas=2, storage_profiles='rocksDbProfile';

5.创建具有持久化的 Chinook 数据库

5.1.关于Chinook数据库

Chinook 数据库是一个数字媒体商店,其中包含艺术家、专辑、曲目等表,它通常用来演示数据库功能。

5.2.创建数据库表

使用前述 RocksDB 持久化分布区为 Chinook 数据库创建必要的表:

sql
-- Create Artist table
CREATE TABLE Artist (
    ArtistId INT NOT NULL,
    Name VARCHAR(120),
    PRIMARY KEY (ArtistId)
) ZONE ChinookRocksDB;

-- Create Album table
CREATE TABLE Album (
    AlbumId INT NOT NULL,
    Title VARCHAR(160) NOT NULL,
    ArtistId INT NOT NULL,
    PRIMARY KEY (AlbumId, ArtistId)
) COLOCATE BY (ArtistId) ZONE ChinookRocksDB;

-- Create Genre table
CREATE TABLE Genre (
    GenreId INT NOT NULL,
    Name VARCHAR(120),
    PRIMARY KEY (GenreId)
) ZONE ChinookRocksDB;

-- Create MediaType table
CREATE TABLE MediaType (
    MediaTypeId INT NOT NULL,
    Name VARCHAR(120),
    PRIMARY KEY (MediaTypeId)
) ZONE ChinookRocksDB;

-- Create Track table
CREATE TABLE Track (
    TrackId INT NOT NULL,
    Name VARCHAR(200) NOT NULL,
    AlbumId INT,
    MediaTypeId INT NOT NULL,
    GenreId INT,
    Composer VARCHAR(220),
    Milliseconds INT NOT NULL,
    Bytes INT,
    UnitPrice NUMERIC(10,2) NOT NULL,
    PRIMARY KEY (TrackId, AlbumId)
) COLOCATE BY (AlbumId) ZONE ChinookRocksDB;

5.3.加载示例数据

将示例数据插入表中:

sql
-- Insert data into MediaType table
INSERT INTO MediaType (MediaTypeId, Name) VALUES
(1, 'MPEG audio file'),
(2, 'Protected AAC audio file');

-- Insert data into Artist table
INSERT INTO Artist (ArtistId, Name) VALUES
(1, 'AC/DC'),
(2, 'Accept'),
(3, 'Aerosmith'),
(4, 'Alanis Morissette'),
(5, 'Alice In Chains');

-- Insert data into Album table
INSERT INTO Album (AlbumId, Title, ArtistId) VALUES
(1, 'For Those About To Rock We Salute You', 1),
(2, 'Balls to the Wall', 2),
(3, 'Restless and Wild', 2),
(4, 'Let There Be Rock', 1),
(5, 'Big Ones', 3);

-- Insert data into Genre table
INSERT INTO Genre (GenreId, Name) VALUES
(1, 'Rock'),
(2, 'Jazz'),
(3, 'Metal'),
(4, 'Alternative & Punk'),
(5, 'Rock And Roll');

-- Insert data into Track table
INSERT INTO Track (TrackId, Name, AlbumId, MediaTypeId, GenreId, Composer, Milliseconds, Bytes, UnitPrice) VALUES
(1, 'For Those About To Rock (We Salute You)', 1, 1, 1, 'Angus Young, Malcolm Young, Brian Johnson', 343719, 11170334, 0.99),
(2, 'Balls to the Wall', 2, 2, 1, 'U. Dirkschneider, W. Hoffmann, H. Frank, P. Baltes, S. Kaufmann, G. Hoffmann', 342562, 5510424, 0.99),
(3, 'Fast As a Shark', 3, 2, 1, 'F. Baltes, S. Kaufman, U. Dirkschneider & W. Hoffman', 230619, 3990994, 0.99),
(4, 'Restless and Wild', 3, 2, 1, 'F. Baltes, R.A. Smith-Diesel, S. Kaufman, U. Dirkschneider & W. Hoffman', 252051, 4331779, 0.99),
(5, 'Princess of the Dawn', 3, 2, 1, 'Deaffy & R.A. Smith-Diesel', 375418, 6290521, 0.99);

5.4.查询数据库

测试数据是否正确插入:

sql
SELECT a.Name AS Artist, al.Title AS Album, t.Name AS Track
FROM Track t
JOIN Album al ON t.AlbumId = al.AlbumId
JOIN Artist a ON al.ArtistId = a.ArtistId
WHERE t.AlbumId = 1;

6.测试持久化功能

6.1.重启前验证数据

执行几个查询以确保数据存储正常:

sql
-- Count tracks by genre
SELECT g.Name AS Genre, COUNT(t.TrackId) AS TrackCount
FROM Track t
JOIN Genre g ON t.GenreId = g.GenreId
GROUP BY g.Name;

-- Check all albums by artist
SELECT a.Name AS Artist, COUNT(al.AlbumId) AS AlbumCount
FROM Album al
JOIN Artist a ON al.ArtistId = a.ArtistId
GROUP BY a.Name;

6.2.重启集群

要重启集群,需要先退出命令行工具:

  • 使用exit命令退出 SQL 命令行;
  • 再使用exit命令退出命令行工具。

重新启动 Docker 容器:

shell
docker-compose down
docker-compose up -d

6.3.重启后验证数据持久化

重新接入命令行:

shell
docker run --rm -it --network=host -e LANG=C.UTF-8 -e LC_ALL=C.UTF-8 apacheignite/ignite:3.1.0 cli

集群已经初始化,因此可以直接转到 SQL 命令行:

shell
sql

运行相同的查询以验证重启后数据还在:

sql
SELECT a.Name AS Artist, al.Title AS Album, t.Name AS Track
FROM Track t
JOIN Album al ON t.AlbumId = al.AlbumId
JOIN Artist a ON al.ArtistId = a.ArtistId
WHERE t.AlbumId = 1;

7.总结

Ignite 3 采用的 RocksDB 持久化存储,提供了数据持久化的强大能力,同时还可以利用内存计算的性能优势。RocksDB 特别适合写入密集型负载,使其成为许多生产场景的绝佳选择。

7.1.其他资源

18624049226