MinIO 是一个功能强大的 TileDB 主后端,因为它们都为性能和可扩展性而设计。MinIO 是一个单一的 Go 二进制文件,可以在各种云和本地环境中启动。它非常轻量级,但也功能丰富,包括 复制 和 加密 等功能,并提供与各种应用程序的 集成。MinIO 是 TileDB 的完美伴侣,因为它拥有业界领先的性能和可扩展性。MinIO 能够提供强大的性能——我们在仅使用 32 个节点的 现成 NVMe SSD 上对它进行了基准测试,其 GET 速度为 325 GiB/s(349 GB/s),PUT 速度为 165 GiB/s(177 GB/s)——并用于构建具有分析和 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
# 本地路径 array_local = os.path.expanduser("./tiledb_demo")
# 创建一个简单的 1D 数组 tiledb.from_numpy(array_local, np.array([1.0, 2.0, 3.0]))
# 读取数组 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 存储桶
我们将从在我们的 Docker 生态系统中拉取 mc 开始,然后使用 play.min.io 创建存储桶。
拉取 mc Docker 镜像
使用 MinIO Play 测试,列出所有存储桶
% docker run minio/mc ls play
[存储桶的较长截断列表] |
创建一个存储桶以将我们本地的 TileDB 数据移动到该存储桶,将其命名为 tiledb-demo
。
% docker run minio/mc mb play/tiledb-demo 存储桶创建成功 `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 密钥 minio_key = "minioadmin" minio_secret = "minioadmin"
# 带有 MinIO 密钥的配置对象 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"
# 创建 TileDB 配置上下文 ctx = tiledb.Ctx(config)
# TileDB 演示的 MinIO 存储桶 URI 路径 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.] |
我们已经从 MinIO 中读取了数据,接下来让我们看看如何直接将数据写入 MinIO 存储桶,而不是从现有来源复制到 MinIO。
直接写入 MinIO 存储桶
到目前为止,我们已经向您展示了如何读取已存在的数据,无论是本地存储还是现有存储桶。但是,如果您想从头开始直接写入 MinIO,该怎么做呢?让我们来看看。
直接将数据写入 MinIO 存储桶的代码与上面的代码相同,只是更改了两行。
存储 TileDB 数据的 MinIO 存储桶的路径必须更新为 tiledb_minio_demo
(而不是 tiledb_demo
)。
我们将使用tiledb.from_numpy
函数,就像我们之前使用本地存储一样,来创建存储在 MinIO 存储桶中的数组。
[TRUNCATED]
# TileDB 演示的 MinIO 存储桶 URI 路径 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] |
完成这两个更改后,运行脚本,您应该看到以下输出。
% python3 tiledb-minio-demo.py [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 |
最后但并非最不重要的一点是,我见过的最神秘的错误之一是以下错误。
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 |
经过大量调试后,事实证明,如果您使用 http 连接,但 MinIO 服务器启用了 TLS,那么您将看到上述错误。只需确保连接方案设置为正确的配置,在本例中为 config["vfs.s3.scheme"] = "https"。
成堆的成堆的成堆
有一首说唱歌曲(您可以搜索它),他们说唱着拥有成堆的成堆的成堆的 *咳嗽* 现金。但是还有一首说唱歌曲,他们声称他们有这么多堆现金,以至于不能再被称为“堆”了,现在是“成堆”。本质上,当您的堆变得如此之大,如此之高时,您需要成堆的成堆的成堆来存放您的现金堆。
这是一个恰当的比较,因为您的数据堆与他们说唱的现金堆一样重要(或更重要)。如果只有像 MinIO 这样的东西可以保护您所有对象 - 物理或虚拟 - 安全并方便访问。
有了 MinIO,您可以轻松地将 TileDB 扩展到跨多个数据中心的多个机架,而且相对容易。您还可以获得使 MinIO 变得很棒的所有功能,例如安全性与访问控制、分层、对象锁定与保留、密钥加密服务 (KES),以及其他开箱即用的功能。通过将所有数据存储在 MinIO 中,您可以降低所需的存储复杂性,从而大幅节省数据存储成本,同时在商品硬件上运行 MinIO 可提供最佳的性能与成本比。MinIO 为您的 TileDB 引擎提供超凡的性能,让查询变得轻松愉快。
我们已将本博客中使用的代码片段添加到git 存储库中。如果您有任何关于如何将 MinIO 连接到 TileDB 或将数据迁移到 MinIO 的问题,请务必在Slack 上与我们联系!