找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

3241

积分

0

好友

415

主题
发表于 2026-2-13 02:38:36 | 查看: 29| 回复: 0

eloqstore 是什么?这是一款基于 io_uring 的高性能混合层键值存储引擎。它将对象存储(兼容 S3)与本地 NVMe SSD 相结合,旨在提供卓越的写入吞吐量和亚毫秒级的读取延迟。作为 EloqData 数据库产品的基础存储层,它使得基于 SSD 的工作负载能够实现接近内存的延迟特性,同时兼顾了数据的持久性与成本效益。

那么,如何让这个用 C++ 编写的存储引擎更好地服务于 Rust 生态呢?这就是 eloqstore Rust SDK 的使命。它本质上是一个精心设计的 FFI(外部函数接口)层,核心目标是在 Rust 程序中安全、高效地调用 eloqstore 的原生功能。对于开发者而言,一套简洁高效的接口就是 SDK 最大的价值。你可以将其理解为一个“简单且高效的定制传话层”:将 Rust 中的操作指令原封不动地传递给 eloqstore 内核执行,再将结果准确无误地返回。

整个集成过程遵循清晰的设计原则,大致可以分为以下几个阶段:

前提与边界约定

在开始之前,必须确立几条铁律以确保跨语言调用的稳定与安全:

  • 边界只走 C ABI:所有导出函数必须使用 extern “C”,避免导出复杂的 C++ 类、STL 容器或模板。
  • 异常不跨边界:在 C++ 封装层内部使用 try/catch(...) 捕获所有异常,并将其转换为明确的错误码返回给 Rust 侧。
  • 所有权清晰:跨越 FFI 边界的内存必须遵循“谁分配,谁释放”的原则,必要时需要提供对应的 free_xxx() 函数供 Rust 调用。

选择并导出核心 API

第一步是确定需要暴露给 Rust 的核心操作,例如读(read)、写(write)、扫描(scan)等。

  1. C++ 侧:编写一个 C API 头文件,使用 extern “C” 导出一组面向过程的、基于 C 语言的函数。这些函数内部再去调用真正的 C++ 类实现功能。
  2. Rust 侧:使用 extern “C” 声明这些函数,并通过 unsafe 块进行调用。最关键的一步是,围绕这些原始的 unsafe 接口,构建一层利用 RAII(资源获取即初始化)等 Rust 安全特性的高级封装,最终向用户提供安全的 API。

在这个过程中,数据结构的布局需要做出适配:

  1. 字符串/字节数组:统一使用 (const uint8_t* ptr, size_t len)(const char* ptr, size_t len) 这样的指针加长度的组合来表示。
  2. 调用方分配内存:由 Rust 传入一个 buffer 指针及其容量,C++ 函数将数据填充进去并返回实际使用的长度。
  3. 被调用方分配内存:由 C++ 侧通过 mallocnew 分配内存并返回指针,Rust 侧在使用完毕后,必须调用对应的 free_xxx() 函数来释放(这是最常用的模式)。

编译动态链接库

完成接口定义后,需要将 C++ 部分的代码编译成动态库,例如 libeloqstore_combine.so。之后,Rust 程序在运行时需要能够找到这个动态库,可以通过设置 rpath 或环境变量(如 LD_LIBRARY_PATH)来实现。

创建 Rust 项目结构

接下来,创建一个组织良好的 Rust 项目(crate)来作为调用层。一个推荐的目录结构如下:

.
|-- Cargo.lock
|-- Cargo.toml
|-- README.md
|-- docs
|   |-- API.md
|   |-- LINKING.md
|   `-- QUICK_START.md
|-- eloqstore                      # 上层安全封装 crate(推荐使用)
|   |-- Cargo.toml
|   |-- README.md
|   |-- examples
|   |   |-- basic_usage.rs
|   |   `-- cloud_storage.rs
|   |-- src
|   |   |-- error.rs
|   |   |-- lib.rs
|   |   |-- request.rs
|   |   |-- response.rs
|   |   |-- store.rs
|   |   `-- traits.rs
|   `-- tests
|       |-- integration_test.rs
|       `-- simple_bench.rs
`-- eloqstore-sys                    # 底层 FFI crate(包含原始绑定)
    |-- Cargo.toml
    |-- build.rs
    |-- src
    |   |-- embedded_lib.rs
    |   |-- error.rs
    |   |-- lib.rs
    |   `-- types.rs
    `-- vendor
        |-- CMakeLists.txt
        |-- README.md
        |-- external -> ../../../external
        |-- ffi
        |   |-- include
        |   |   `-- eloqstore_capi.h
        |   `-- src
        |       `-- eloqstore_capi.cpp
        |-- include -> ../../../include
        `-- src -> ../../../src

这里采用了常见的双 crate 设计:

  • eloqstore-sys:底层 FFI crate,直接与 C 动态库交互,包含 unsafe 绑定。
  • eloqstore:上层安全封装 crate,为开发者提供符合 Rust 习惯的、安全易用的 API。

在 Rust 侧链接动态库

链接工作主要在 eloqstore-sysCargo.tomlbuild.rs 中配置。首先,在 Cargo.toml 中声明构建脚本和依赖:

[package]
name = "eloqstore-sys"
version = "0.1.0"
edition = "2024"
build = "build.rs"

[dependencies]
libc = "0.2"
tempfile = "3"

[features]
default = []
metrics = []

[build-dependencies]
cmake = "0.1"

然后,编写 build.rs 脚本,它的核心作用是告诉 Cargo 构建系统:去哪里查找动态库以及具体链接哪一个库。

手动编写 Rust FFI 声明

最后,也是最细致的一步,就是在 eloqstore-sys 中手动编写与 C 头文件对应的 Rust FFI 函数和类型声明。这些声明通常放在 src/lib.rs 或类似的文件中,需要严格匹配 C 侧的签名。

总结

通过上述一套完整的流程,EloqStore Rust SDK 实现了清晰高效的 FFI 架构,并带来了多重优势:

  1. 零拷贝传输:在 FFI 边界上精心设计,确保数据最多只被复制一次,最小化内存开销。
  2. 类型安全:在 Rust 侧构建了完整的类型安全抽象,在编译期就保证了调用的正确性。
  3. 批量性能极佳:充分利用底层 COW B-tree 架构的特性,使得批量写入操作性能表现突出。
  4. 灵活的双 API 设计:为简单场景提供 RocksDB-style 的易用接口,为复杂场景提供基于 Trait 的、更富表现力的 Request 接口,兼顾了易用性与灵活性。

这种将高性能 C++ 存储引擎 与现代化 Rust 语言生态结合的模式,为开发兼具性能与安全性的存储系统提供了宝贵参考。对类似技术实践感兴趣的开发者,可以关注 云栈社区 以获取更多深度内容。

相关链接


(以下为 Rust 日报同期其他内容)

Rust 基金会 2025 年度报告及三年战略规划

-- From 日报小组 侯盛鑫




上一篇:Rust 开发中嵌入 LLM 生成代码?Reddit 热议背后的效率陷阱与争议
下一篇:Anthropic首份报告:Claude Opus 4.6的AI破坏风险评估与行业影响
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-2-23 14:31 , Processed in 0.742457 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表