使用 MinIO 超级充电 TileDB 引擎-LMLPHP

MinIO 是一个强大的主要 TileDB 后端,因为两者都是为性能和规模而构建的。MinIO 是一个单一的 Go 二进制文件,可以在许多不同类型的云和本地环境中启动。它非常轻量级,但也具有复制和加密等功能,并且提供与各种应用程序的集成。MinIO 是 TileDB 的完美伴侣,因为它具有行业领先的性能和可扩展性。MinIO 具有出色的性能——我们在 GET 上以 325 GiB/s (349 GB/s) 的速度对其进行了基准测试,在 PUT 上以 165 GiB/s (177 GB/s) 的速度对其进行了基准测试,只需 32 个现成的 NVMe SSD 节点即可将其用于构建具有分析和 AI/ML 工作负载的数据湖/湖屋。

TileDB 用于将数据存储在各种应用程序中,例如基因组学、地理空间、生物医学成像、金融、机器学习等。TileDB 的强大功能源于这样一个事实,即任何数据都可以有效地建模为密集或稀疏的多维数组,这是大多数数据科学工具内部使用的格式。通过将您的数据和元数据存储在 TileDB 数组中,您可以抽象出所有数据存储和管理的难题,同时通过我们众多的 API 和集成使用您最喜欢的编程语言或数据科学工具有效地访问数据。

设置 TileDB

让我们深入了解并使用 TileDB 创建一些测试数据

安装 TileDB 模块,该 pip 模块也应安装 numpy 依赖项。

% pip3 install tiledb


Collecting tiledb

  Downloading tiledb-0.25.0-cp311-cp311-macosx_11_0_arm64.whl (10.4 MB)

 	━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 10.4/10.4 MB 2.7 MB/s eta 0:00:00

Collecting packaging

  Downloading packaging-23.2-py3-none-any.whl (53 kB)

 	━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 53.0/53.0 kB 643.1 kB/s eta 0:00:00

Collecting numpy>=1.23.2

  Downloading numpy-1.26.3-cp311-cp311-macosx_11_0_arm64.whl (14.0 MB)

 	━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 14.0/14.0 MB 2.5 MB/s eta 0:00:00

Installing collected packages: packaging, numpy, tiledb

Successfully installed numpy-1.26.3 packaging-23.2 tiledb-0.25.0

通过运行以下 Python 脚本创建一个测试数组,将其 tiledb-demo.py 命名为 。

import tiledb

import numpy as np

import os, shutil


# Local path

array_local = os.path.expanduser("./tiledb_demo")


# Create a simple 1D array

tiledb.from_numpy(array_local, np.array([1.0, 2.0, 3.0]))


# Read the array

with tiledb.open(array_local) as A:

	print(A[:])

运行脚本

% python3 tiledb-demo.py

[1. 2. 3.]

这将创建一个目录 tiledb_demo 来存储实际数据。

% ls -l tiledb_demo/

total 0

drwxr-xr-x  3 aj  staff   96 Jan 31 05:27 __commits

drwxr-xr-x  2 aj  staff   64 Jan 31 05:27 __fragment_meta

drwxr-xr-x  3 aj  staff   96 Jan 31 05:27 __fragments

drwxr-xr-x  2 aj  staff   64 Jan 31 05:27 __labels

drwxr-xr-x  2 aj  staff   64 Jan 31 05:27 __meta

drwxr-xr-x  4 aj  staff  128 Jan 31 05:27 __schema


您可以继续按原样使用它,但如果一切都是本地的,那就没有问题了,因为如果本地磁盘或节点发生故障,那么您将丢失整个数据。让我们做一些有趣的事情,比如从 MinIO 存储桶中读取相同的数据。

将数据迁移到 MinIO Bucket

我们将首先在 docker 生态系统中拉取 mc,然后使用 play.min.io 创建存储桶。

拉取 mc docker 镜像

% docker pull minio/mc


通过列出所有存储桶来使用 MinIO Play 进行测试

% docker run minio/mc ls play


[LONG TRUNCATED LIST OF BUCKETS]

创建一个存储桶以将我们的本地 TileDB 数据移动到其中,将其命名为 tiledb-demo 。

% docker run minio/mc mb play/tiledb-demo


Bucket created successfully `play/tiledb-demo`.

将 tiledb_demo 数据目录的内容复制到 MinIO tiledb-demo 存储桶

% docker run -v $(pwd)/tiledb_demo:/tiledb_demo minio/mc cp --recursive /tiledb_demo play/tiledb-demo


`/tiledb_demo/__commits/__1706696859767_1706696859767_777455531063403b811b2a2bf79d40e7_21.wrt` -> `play/tiledb-demo/tiledb_demo/__commits/__1706696859767_1706696859767_777455531063403b811b2a2bf79d40e7_21.wrt`

`/tiledb_demo/__fragments/__1706696859767_1706696859767_777455531063403b811b2a2bf79d40e7_21/a0.tdb` -> `play/tiledb-demo/tiledb_demo/__fragments/__1706696859767_1706696859767_777455531063403b811b2a2bf79d40e7_21/a0.tdb`

`/tiledb_demo/__fragments/__1706696859767_1706696859767_777455531063403b811b2a2bf79d40e7_21/__fragment_metadata.tdb` -> `play/tiledb-demo/tiledb_demo/__fragments/__1706696859767_1706696859767_777455531063403b811b2a2bf79d40e7_21/__fragment_metadata.tdb`

`/tiledb_demo/__schema/__1706696859758_1706696859758_74e7040e138a4cca93e34aca1c587108` -> `play/tiledb-demo/tiledb_demo/__schema/__1706696859758_1706696859758_74e7040e138a4cca93e34aca1c587108`


Total: 3.24 KiB, Transferred: 3.24 KiB, Speed: 1.10 KiB/s

列出 的内容 tiledb-demo ,以确保数据已复制

% docker run minio/mc ls play/tiledb-demo/tiledb_demo

[2024-01-15 14:15:57 UTC] 	0B __commits/

[2024-01-15 14:15:57 UTC] 	0B __fragments/

[2024-01-15 14:15:57 UTC] 	0B __schema/

注意:MinIO 客户端 ( mc ) 或任何 S3 兼容客户端仅复制非空文件夹。这样做的原因是,在对象存储世界中,数据是根据存储桶前缀组织的,因此不需要非空文件夹。在以后的博客中,我们将更深入地探讨如何使用前缀和文件夹来组织数据。因此,您只能看到这 3 个文件夹,而看不到我们在本地文件夹中看到的其余文件夹。

现在,让我们尝试使用下面的 Python 代码直接从 MinIO 存储桶中读取相同的数据,将文件 tiledb-minio-demo.py 命名为 。

import tiledb

import numpy as np


# MinIO keys

minio_key = "minioadmin"

minio_secret = "minioadmin"


# The configuration object with MinIO keys

config = tiledb.Config()

config["vfs.s3.aws_access_key_id"] = minio_key

config["vfs.s3.aws_secret_access_key"] = minio_secret

config["vfs.s3.scheme"] = "https"

config["vfs.s3.region"] = ""

config["vfs.s3.endpoint_override"] = "play.min.io:9000"

config["vfs.s3.use_virtual_addressing"] = "false"


# Create TileDB config context

ctx = tiledb.Ctx(config)


# The MinIO bucket URI path of tiledb demo

array_minio = "s3://tiledb-demo/tiledb_demo/"


with tiledb.open(array_minio, ctx=tiledb.Ctx(config)) as A:

	print(A[:])
    

输出应该看起来很熟悉

% python3 tiledb-minio-demo.py

[1. 2. 3.]
[TRUNCATED]


# The MinIO bucket URI path of tiledb demo

array_minio = "s3://tiledb-demo/tiledb_minio_demo/"


tiledb.from_numpy(array_minio, np.array([1.0, 2.0, 3.0]), ctx=tiledb.Ctx(config))


[TRUNCATED]

我们已经阅读了 MinIO,接下来让我们看看如何直接将数据写入 MinIO 存储桶,而不是将其从现有源复制到 MinIO。

% python3 tiledb-minio-demo.py

[1. 2. 3.]

直接写入 MinIO 存储桶

到目前为止,我们已经向您展示了如何读取本地存储或现有存储桶中已存在的数据。但是,如果您想从一开始就直接向 MinIO 写入内容,那么这将如何工作?让我们来看看。

直接写入 MinIO 存储桶的代码与上述相同,只是更改了两行。

存储 TileDB 数据的 MinIO 存储桶的路径必须更新为 tiledb_minio_demo (而不是 tiledb_demo )。

我们将使用该 tiledb.from_numpy 函数,就像我们之前对本地存储所做的那样,创建要存储在 MinIO 存储桶中的数组。

[TRUNCATED]


# The MinIO bucket URI path of tiledb demo

array_minio = "s3://tiledb-demo/tiledb_minio_demo/"


tiledb.from_numpy(array_minio, np.array([1.0, 2.0, 3.0]), ctx=tiledb.Ctx(config))


[TRUNCATED]

进行这 2 项更改后,运行脚本,您应该看到下面的输出

% python3 tiledb-minio-demo.py

[1. 2. 3.] [1. 2.3.]


如果再次运行脚本,它将失败并出现以下错误,因为它将尝试再次写入。

tiledb.cc.TileDBError: [TileDB::StorageManager] Error: Cannot create array; Array 's3://tiledb-demo/tiledb_minio_demo/' already exists

只需注释掉以下行,即可多次重新运行它。

# tiledb.from_numpy(array_minio, np.array([1.0, 2.0, 3.0]), ctx=tiledb.Ctx(config))

% python3 tiledb-minio-demo.py

[1. 2. 3.]


% python3 tiledb-minio-demo.py

[1. 2. 3.]

检查 MinIO Play 存储桶,确保数据按预期存在

% docker run minio/mc ls play/tiledb-demo/tiledb_minio_demo/

[2024-01-15 16:45:04 UTC] 	0B __commits/

[2024-01-15 16:45:04 UTC] 	0B __fragments/

[2024-01-15 16:45:04 UTC] 	0B __schema/

好了,将数据导入 MinIO 就是这么简单。你得到的结果和之前一样吗?你应该有,但如果你没有,你可以检查一些东西。

常见陷阱

我们将介绍您在尝试读取/写入 MinIO 时可能遇到的一些常见错误。

如果您的访问密钥和私有密钥不正确,您应该会看到如下错误消息

tiledb.cc.TileDBError: [TileDB::S3] Error: Error while listing with prefix 's3://tiledb-demo/tiledb_minio_demo/__schema/'... The request signature we calculated does not match the signature you provided. Check your key and signing method.

接下来,您需要确保主机名和端口正确无误,如果没有正确的端点,这些错误就会遇到

主机名不正确:

tiledb.cc.TileDBError: [TileDB::S3] Error: … Couldn't resolve host name


端口不正确:

tiledb.cc.TileDBError: [TileDB::S3] Error: … Couldn't connect to server

最后但并非最不重要的一点是,我见过的最隐晦的错误之一是

经过大量调试后,事实证明,如果您使用 http 进行连接,但 MinIO 服务器激活了 TLS,那么您将看到上述错误。只要确保连接方案设置为正确的配置,在这种情况下,config[“vfs.s3.scheme”] = “https”.

tiledb.cc.TileDBError: [TileDB::S3] Error: … [HTTP Response Code: -1] [Remote IP: 98.44.32.5] : curlCode: 56, Failure when receiving data from the peer

机架上的机架 机架上的机架

有一首说唱歌曲(你可以搜索它),他们说唱有一堆堆的咳嗽现金。但是还有另一首说唱歌曲,他们声称他们有这么多的现金,以至于他们不能再被称为“堆栈”,他们现在是“架子”。从本质上讲,当你的筹码变得如此之大和如此之高时,你需要一个架子上的架子来存储你的现金堆栈。

这是一个恰当的比较,因为你的数据堆对你来说意味着与他们正在说唱的一堆现金一样多(或更多)。要是有像 MinIO 这样的东西来保证你所有的对象——物理的或虚拟的——安全且易于访问就好了。

借助 MinIO,您可以轻松地将 TileDB 扩展到多个数据中心的多个机架。您还可以获得使 MinIO 出色的所有功能,例如安全和访问控制、分层、对象锁定和保留、密钥加密服务 (KES) 等开箱即用。通过将所有数据保存在 MinIO 中,您可以降低所需的存储复杂性,从而节省大量数据存储成本,同时在商用硬件上运行 MinIO 可提供最佳的性价比。MinIO 以行业领先的性能增强您的 TileDB 引擎,让查询成为一种乐趣。

我们已将本博客中使用的代码片段添加到 git 存储库中。如果您对如何将 MinIO 连接到 TileDB 或将数据迁移到 MinIO 有任何疑问,请务必联系我们!

02-12 19:21