# remdb **Repository Path**: totaltrust/remdb ## Basic Information - **Project Name**: remdb - **Description**: Embedded Database in Rust - **Primary Language**: Rust - **License**: MulanPSL-2.0 - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 6 - **Forks**: 1 - **Created**: 2025-12-22 - **Last Updated**: 2026-08-26 ## Categories & Tags **Categories**: database-service **Tags**: None ## README # remdb - 嵌入式内存数据库 [English Version](./README_EN.md) remdb是一个轻量级的嵌入式内存数据库,专为资源受限的嵌入式系统设计,支持no_std环境,具有可预测的内存使用和高性能。 ## 主要功能 - **内存表存储**:高效的内存表实现,支持插入、删除、查询和遍历操作 - **索引机制**: - 基于哈希的主键索引,提供O(1)的查询性能 - 多种辅助索引类型:Hash、SortedArray、BTree(默认)、TTree - SortedArray、BTree和TTree索引支持范围查询 - **事务支持**:完整的ACID事务支持,包括原子性、一致性、隔离性和持久性 - **内存管理**:支持静态内存分配和动态内存分配,固定大小块内存池 - **平台抽象层**:支持POSIX和裸机环境 - **编译时配置**:使用宏实现表和数据库的编译时配置,优化性能 - **低功耗模式**:优化内存使用,减少事务日志写入频率 - **增量快照**:只保存版本号变化的记录,减少快照大小和保存时间 - **SQL查询支持**:支持标准SQL SELECT语句查询内存数据库的数据,包括聚合函数、数学函数、时间转换函数、JOIN操作和LIKE模式匹配运算符 - **SQL DDL支持**:支持CREATE TABLE和DROP TABLE语句,允许动态创建和删除表结构 - **SQL数据库管理支持**:支持CREATE DATABASE和DROP DATABASE语句,允许创建和管理数据库 - **UTF8字符支持**:完全支持UTF8字符编码,包括字符串存储、字符函数、LIKE运算符和排序 - **JSON支持**:原生JSON数据类型,支持JSON路径查询、JSON修改函数、JSON索引和JSON与其他功能的结合 - **SAMPLE BY语法**:支持按指定时间间隔对时序数据进行采样,提供简洁的时间窗口聚合语法 - **FILL语法**:支持在时间序列数据中填充缺失的时间窗口,确保时间序列的连续性,支持多种填充方式 - **数据库监控**:实时监控数据库指标,包括内存使用、查询性能、事务状态等 - **基于UDP的高可靠数据订阅与发布**:支持单播、广播和组播模式,提供基于NACK的重传机制 - **高可用支持**: - 主从复制机制,支持一主一从或一主多从拓扑结构 - 基于心跳机制的自动故障检测和切换 - 支持同步和异步两种复制一致性模式: - 同步模式:主节点等待至少一个从节点确认后才返回,确保数据一致性 - 异步模式:主节点立即返回,异步复制到从节点,提供更高的性能 - 自动故障转移,服务中断窗口小于2秒 - 从节点确认机制:从节点接收到WAL日志后发送确认给主节点 - 复制状态检查:定期检查复制状态,包括从节点数量、延迟等 - 支持全量和增量同步:从节点可以请求全量同步或从特定日志索引开始的增量同步 - **启动同步协议**:完整的启动同步机制,确保从节点启动时与主节点数据一致 - 协议流程:SYNC_REQUEST → SYNC_DATA_BEGIN → SYNC_DATA_CHUNK* → SYNC_DATA_END → SYNC_ACK - 全量同步:发送完整数据库快照,支持大容量数据分块传输 - 增量同步:发送指定日志索引后的WAL日志,减少网络传输 - 数据完整性:支持CRC32校验和验证 - **向量数据库支持**: - 原生向量数据类型:`VECTOR(dimension)` - 支持多种距离度量:L2(欧几里得距离)、IP(内积)、COSINE(余弦相似度) - 多种向量索引类型:HNSW、HNSW_SQ(带标量量化)、HNSW_BQ(带二值量化)、IVF、IVF_FLAT(带扁平量化)、IVF_PQ(带乘积量化) - 向量相似性查询:支持L2距离 `<->`、内积 `<#>`、余弦相似度 `<=>` 操作符 - 混合查询:支持向量搜索与标量过滤的混合查询 - **时序数据库支持**: - 专用的时序表实现,优化时间序列数据存储和查询 - 支持多种压缩算法 - 支持时间序列数据分区 - 支持时间序列数据生命周期管理 - 支持时间序列数据索引 - **C语言接口**:提供C语言API,方便C/C++应用程序使用 - **RBAC权限管理**:基于角色的访问控制(RBAC),支持用户、角色和权限管理,提供细粒度的数据访问控制 - **AI模型推理**:集成ONNX运行时,支持AI模型推理,提供内置模型和自定义模型加载 - **WAL日志压缩**:支持LZ4和Zstd两种WAL日志压缩算法,减少日志存储空间 - **系统表**:提供系统表管理,支持数据库元数据查询和系统信息监控 ## 技术特点 - **零外部依赖**:不依赖任何外部库,支持no_std环境 - **静态内存分配**:可预测的内存使用,适合资源受限的嵌入式系统 - **编译时优化**:通过宏实现编译时配置,减少运行时开销 - **多平台支持**:支持POSIX和裸机环境 - **类型安全**:使用Rust的类型系统确保数据安全 - **高效的同步机制**:实现了自旋锁同步机制,适合多线程环境 ## 快速开始 ### 安装 将remdb添加到你的Cargo.toml文件中: ```toml [dependencies] remdb = { path = "./remdb", default-features = false } # 可选特性 # features = ["std", "posix", "pubsub", "ha"] # 注意:ha依赖pubsub功能,启用ha时会自动启用pubsub ``` ### 特性说明 | 特性名 | 依赖 | 描述 | |-------|------|------| | std | - | 启用标准库支持 | | posix | - | 启用POSIX平台支持 | | baremetal | log | 启用裸机平台支持(无标准库依赖) | | pubsub | std | 启用基于UDP的高可靠数据订阅与发布功能 | | ha | pubsub | 启用高可用支持(主从复制机制) | | log | - | 启用日志功能 | | debug | - | 启用debug级别日志(仅在debug构建时生效) | | c-api | - | 启用C语言API接口 | | wal-compression-lz4 | lz4 | 启用LZ4 WAL日志压缩 | | wal-compression-zstd | zstd | 启用Zstd WAL日志压缩 | | model-runtime | ort, serde, bincode, tokio, ndarray | 启用ONNX运行时模型推理 | | model-download | reqwest, sha2, std, futures, ureq | 启用模型下载功能 | ### 日志配置 remdb提供了灵活的日志配置选项,支持不同环境下的日志输出: #### 标准库环境日志配置 ```rust use remdb::log::{init_logger, init_logger_with_file}; // 基础初始化(输出到控制台,debug级别) init_logger(); // 带文件输出的初始化 // debug_mode: true - 输出DEBUG及以上级别日志 // debug_mode: false - 仅输出INFO及以上级别日志 init_logger_with_file("/var/log/remdb.log", true).unwrap(); ``` #### no_std环境日志配置 在no_std环境下,日志级别由编译模式自动控制: - **Debug构建**:输出DEBUG及以上级别日志 - **Release构建**:仅输出WARN及以上级别日志 ```rust use remdb::log::init_logger; // 初始化no_std日志 init_logger(); // 使用日志宏 use remdb::log::{debug, info, warn, error}; debug!("调试信息"); // 仅在debug构建中输出 info!("普通信息"); warn!("警告信息"); error!("错误信息"); ``` #### 日志级别说明 | 级别 | 描述 | Debug构建 | Release构建 | |-----|------|----------|-------------| | TRACE | 最详细的跟踪信息 | ✓ | ✗ | | DEBUG | 调试信息 | ✓ | ✗ | | INFO | 普通信息 | ✓ | ✓ | | WARN | 警告信息 | ✓ | ✓ | | ERROR | 错误信息 | ✓ | ✓ | ## Rust语言的三种使用方式 remdb提供了三种主要的Rust语言使用方式,以满足不同场景的需求: ### 1. 直接定义表数据结构 使用`remdb::table!`宏直接定义表结构,这是最基础的使用方式,适合简单场景: ```rust #![no_std] #![feature(alloc_error_handler)] extern crate alloc; use core::alloc::Layout; use remdb::*; // 定义内存缓冲区 static mut DB_MEMORY: [u8; 65536] = [0u8; 65536]; // 直接定义表结构 remdb::table!( users, 100, // 最大记录数 primary_key: id, secondary_index: name, fields: { id: i32, name: str(32), // 32字节定长字符串 age: i8, active: bool, created_at: u64 } ); // 定义数据库配置 remdb::database!( tables: [users] ); // 内存分配错误处理 #[alloc_error_handler] fn alloc_error_handler(layout: Layout) -> ! { panic!("Allocation error: {:?}", layout); } fn main() { unsafe { // 初始化内存分配器 memory::allocator::init_global_allocator( DB_MEMORY.as_mut_ptr(), DB_MEMORY.len() ); // 初始化平台抽象层 platform::init_platform(platform::posix::get_posix_platform()); // 初始化全局数据库 let db = init_global_db( database!(tables: [users]), &mut [None; 1], &mut [None; 1], &mut [None; 1] ).unwrap(); // 使用数据库... } } ``` ### 2. 宏定义MemTable 使用`#[derive(MemdbTable)]`宏定义表,支持内联DDL和外部DDL文件,提供更灵活的表定义方式: #### 内联DDL模式 ```rust use remdb_macros::MemdbTable; // 使用内联DDL定义带索引的表 #[derive(MemdbTable)] #[memdb_schema(ddl = "CREATE TABLE user (id INTEGER PRIMARY KEY, name TEXT NOT NULL, age INTEGER, active BOOLEAN); CREATE INDEX idx_user_name ON user USING btree (name); CREATE INDEX idx_user_age ON user USING hash (age);")] struct UserTable; fn main() { // 测试生成的User结构体 let user = User { id: 1, name: "Alice".to_string(), age: Some(30), active: Some(true), }; println!("生成的User结构体: {:?}", user); println!("用户名: {}", user.name); println!("年龄: {:?}", user.age); } ``` #### 文件模式 ```rust use remdb_macros::MemdbTable; // 使用外部DDL文件定义带索引的表 #[derive(MemdbTable)] #[memdb_schema(file = "./schema.ddl")] struct MyDatabase; // schema.ddl内容: // CREATE TABLE user ( // id INTEGER PRIMARY KEY, // name TEXT NOT NULL, // email TEXT UNIQUE NOT NULL // ); // // CREATE INDEX idx_user_name ON user USING btree (name); // CREATE INDEX idx_user_email ON user (email); -- 默认使用BTree ``` ### 3. 使用DdlExecutor通过动态DDL创建 使用`DdlExecutor` trait在运行时动态创建表和索引,适合需要在运行时灵活配置表结构的场景: ```rust use remdb::{RemDb, DdlExecutor, types::{DataType, IndexType}}; use remdb::config::{DbConfig, MemoryAllocator}; use core::ptr::NonNull; // 简单的内存分配器实现 struct SimpleAllocator { base_ptr: NonNull, size: usize, used: usize, } impl SimpleAllocator { pub const fn new(base_ptr: NonNull, size: usize) -> Self { Self { base_ptr, size, used: 0, } } } impl MemoryAllocator for SimpleAllocator { fn allocate(&self, size: usize) -> Option> { let new_used = self.used + size; if new_used <= self.size { let ptr = NonNull::new((self.base_ptr.as_ptr() as usize + self.used) as *mut u8)?; Some(ptr) } else { None } } fn deallocate(&self, _ptr: NonNull, _size: usize) { // 简化实现,不实际释放内存 } } fn main() { // 分配内存用于数据库 let mut buffer = [0u8; 1024 * 1024]; // 1MB let base_ptr = NonNull::new(buffer.as_mut_ptr()).unwrap(); // 创建内存分配器 let allocator = SimpleAllocator::new(base_ptr, buffer.len()); // 创建数据库配置 let config = DbConfig { tables: vec![], total_memory: buffer.len(), low_power_mode_supported: false, low_power_max_records: None, memory_allocator: &allocator, #[cfg(feature = "pubsub")] pubsub_config: None, #[cfg(feature = "ha")] ha_role: remdb::config::HARole::Auto, #[cfg(feature = "ha")] replication_mode: remdb::config::ReplicationMode::Asynchronous, #[cfg(feature = "ha")] ha_config: None, #[cfg(feature = "ha")] replication_sync_timeout: 5000, }; // 初始化表和索引数组 let mut tables = [None; 8]; let mut primary_indices = [None; 8]; let mut secondary_indices = [None; 8]; // 创建数据库实例 let mut db = RemDb::new( &config, &mut tables, &mut primary_indices, &mut secondary_indices ); // 使用DdlExecutor trait创建表 let result = db.create_table( "users", &[ ("id", DataType::UInt32), ("name", DataType::VarChar), ("age", DataType::UInt8), ("active", DataType::Bool), ], Some(0) // 主键为id字段 ); // 使用SQL语句创建表 let result = db.sql_query( "CREATE TABLE products (id UINT32 PRIMARY KEY, name STRING, price FLOAT32, in_stock BOOL);" ); // 使用DdlExecutor trait创建索引 let result = db.create_index( "users", "name", IndexType::BTree ); } ``` ## 其他访问方式 ### C语言接口访问 remdb提供了C语言接口,方便C/C++应用程序使用: ```c #include "remdb_c.h" int main() { // 初始化数据库 remdb_t *db = remdb_init(); // 创建表 remdb_create_table(db, "users", ...); // 插入数据 remdb_insert(db, "users", ...); // 查询数据 remdb_result_t *result = remdb_query(db, "SELECT * FROM users"); // 处理结果... // 释放资源 remdb_free_result(result); remdb_close(db); return 0; } ``` ### JDBC访问 remdb提供了JDBC驱动,允许Java应用程序通过JDBC API访问remdb数据库: ```java import java.sql.*; public class RemdbExample { public static void main(String[] args) { try { // 加载驱动 Class.forName("com.remdb.jdbc.Driver"); // 建立连接 String url = "jdbc:remdb://localhost:8080/dbname"; Connection conn = DriverManager.getConnection(url); // 创建Statement Statement stmt = conn.createStatement(); // 执行查询 ResultSet rs = stmt.executeQuery("SELECT * FROM users"); // 处理结果集 while (rs.next()) { System.out.println(rs.getInt("id") + ": " + rs.getString("name")); } // 关闭资源 rs.close(); stmt.close(); conn.close(); } catch (Exception e) { e.printStackTrace(); } } } ``` ### 基于UDP的高可靠数据订阅与发布 > 注意:使用此功能需要在Cargo.toml中启用`pubsub`特性 remdb提供了基于UDP的高可靠数据订阅与发布机制,支持单播、广播和组播模式,适合分布式系统中的数据同步。系统内置了多种预定义主题,用于发布不同类型的数据库事件: #### 预定义主题 | 主题名称 | 主题ID | 描述 | 消息格式 | |---------|--------|------|---------| | wal | - | 所有WAL操作 | WAL_LOG_: Operation=, Table=, ID=, Data= | | tables | - | 表创建/删除事件 | CREATE:table=,id=,fields= 或 DELETE:table=,id= | | metrics | - | 数据库指标 | JSON格式的数据库指标数据 | | healthstatus | - | 健康状态 | JSON格式的健康状态数据 | | table. | - | 表内容变更 | INSERT:table=,id=,data= 或 UPDATE:table=,id=,data= | | SYNC_REQUEST | 2 | 同步请求主题 | 从节点发送同步请求给主节点 | | SYNC_DATA_BEGIN | 5 | 同步数据开始 | 主节点发送同步元数据给从节点 | | SYNC_DATA_CHUNK | 6 | 同步数据块 | 主节点发送同步数据块给从节点 | | SYNC_DATA_END | 7 | 同步数据结束 | 主节点标记同步数据传输结束 | | SYNC_ACK | 8 | 同步确认 | 从节点发送确认给主节点 | #### 使用示例 ```rust use std::time::Duration; use remdb::pubsub::{PubSub, PubSubConfig, UdpMode}; // 创建发布/订阅配置 let config = PubSubConfig { udp_mode: UdpMode::Broadcast, multicast_addr: None, port: 5555, max_topics: 32, max_subscribers_per_topic: 16, buffer_size: 4096, enable_nack: true, retransmit_timeout: Duration::from_millis(100), max_retransmits: 3, heartbeat_interval: Duration::from_secs(10), frame_pool_size: 128, }; // 创建发布/订阅实例 let mut pubsub = PubSub::new(config).expect("Failed to create PubSub instance"); pubsub.init().expect("Failed to initialize PubSub"); // 定义订阅回调 let callback = |topic_id: u16, data: &[u8]| -> bool { println!("Received data on topic {}: {:?}", topic_id, String::from_utf8_lossy(data)); true }; // 订阅主题 let subscription_id = pubsub.subscribe(0, callback).expect("Failed to subscribe"); // 发布数据 let msg = "Hello, PubSub!"; pubsub.publish(0, msg.as_bytes()).expect("Failed to publish"); // 取消订阅 pubsub.unsubscribe(subscription_id).expect("Failed to unsubscribe"); ``` ## SQL查询示例 remdb支持标准SQL SELECT语句查询内存数据库的数据,包括各种聚合函数、数学函数和时间转换函数: ```rust // 执行SQL查询获取所有用户 let result = db.sql_query("SELECT * FROM users").unwrap(); println!("{}", result.to_string()); // 执行带条件的SQL查询 let result = db.sql_query("SELECT name, age FROM users WHERE age > 25 ORDER BY name ASC LIMIT 10").unwrap(); for row in result { println!("{}: {}", row.get(0), row.get(1)); } // 执行带条件和排序的SQL查询 let result = db.sql_query("SELECT * FROM users WHERE active = true ORDER BY created_at DESC").unwrap(); for row in result { println!("ID: {}, Name: {}, Age: {}, Active: {}", row.get(0), row.get(1), row.get(2), row.get(3)); } // 使用时间转换函数 let result = db.sql_query("SELECT id, name, TO_ISO8601(created_at) AS iso_created FROM users").unwrap(); // 使用TO_CHAR函数格式化时间 let result = db.sql_query("SELECT id, name, TO_CHAR(created_at, 'YYYY-MM-DD HH24:MI:SS') AS formatted_date FROM users").unwrap(); // 使用TO_EPOCH函数获取Unix时间戳 let result = db.sql_query("SELECT id, name, TO_EPOCH(created_at) AS unix_time FROM users").unwrap(); // 结合聚合函数和时间函数 let result = db.sql_query("SELECT TO_CHAR(timestamp, 'YYYY-MM-DD') AS date, AVG(value) AS avg_value FROM sensor_data GROUP BY date").unwrap(); // 使用LIKE运算符进行模式匹配 let result = db.sql_query("SELECT * FROM users WHERE name LIKE 'A%'").unwrap(); // 匹配以'A'开头的名称 let result = db.sql_query("SELECT * FROM users WHERE name LIKE '%son'").unwrap(); // 匹配以'son'结尾的名称 let result = db.sql_query("SELECT * FROM users WHERE name LIKE '%mi%'").unwrap(); // 匹配包含'mi'的名称 let result = db.sql_query("SELECT * FROM users WHERE name LIKE 'A__e'").unwrap(); // 匹配长度为4且以'A'开头、以'e'结尾的名称 ``` ## 时序数据库 remdb提供了强大的时序数据库功能,专为时间序列数据的高效存储和查询而设计: ### 基本使用 ```rust use remdb::*; use remdb::time_series::*; use std::time::{Duration, SystemTime}; // 定义时序表结构 remdb::table!( sensor_data, 5000, // 最大记录数 primary_key: id, secondary_index: timestamp, fields: { id: i32, sensor_id: str(32), // 传感器ID sensor_type: str(32), // 传感器类型 value: f64, // 传感器数值 timestamp: u64, // 时间戳 location: str(64) // 位置信息 } ); // 定义数据库配置 remdb::database!( DB_CONFIG, tables: [sensor_data] ); fn main() { unsafe { // 初始化内存分配器 let memory_size = 128 * 1024 * 1024; // 128MB static mut DB_MEMORY: [u8; 128 * 1024 * 1024] = [0u8; 128 * 1024 * 1024]; memory::allocator::init_global_allocator( DB_MEMORY.as_mut_ptr(), DB_MEMORY.len() ).expect("Failed to initialize memory allocator"); // 初始化平台抽象层 platform::init_platform(platform::posix::get_posix_platform()); // 初始化全局数据库 let db = init_global_db(&DB_CONFIG).unwrap(); // 获取表引用 let table_mut = db.get_table_mut(0).unwrap(); // 模拟插入传感器数据... // 查询时间范围内的数据 let start_time = base_time; let end_time = base_time + 30 * 60000; // 30分钟 let mut result_buffer = [0u8; 160 * 50]; // 50条记录的缓冲区 let found_count = table_mut.get_records_in_time_window( 4, // timestamp字段索引 start_time, end_time, result_buffer.as_mut_ptr(), 50 ).unwrap(); // 计算时间范围内的统计信息 match table_mut.aggregate_count(4, start_time, end_time) { Ok(count) => { println!("时间范围内记录数: {}", count); // 计算平均值、总和、最小值、最大值... }, Err(e) => println!("统计记录数失败: {:?}", e) } } } ### 时序数据预聚合 remdb 现在支持时序数据预聚合功能,在数据写入时自动计算并存储不同时间间隔的聚合结果,显著提高查询性能。 #### 核心特性 - **自动更新**:当写入新数据时,预聚合数据会自动更新 - **多种聚合函数**:支持 SUM、AVG、MIN 和 MAX 聚合函数 - **自定义时间间隔**:允许配置不同的预聚合时间间隔 - **线程安全**:使用 Mutex 确保并发写入时的数据一致性 - **高效存储**:将预聚合数据存储在哈希表中,实现快速查找 #### 使用示例 ```rust use remdb::*; use remdb::time_series::*; // 获取时序表引用 let ts_table = db.get_time_series_table("sensor_data").unwrap(); // 添加预聚合配置 ts_table.add_pre_aggregation(60, "AVG").unwrap(); // 1分钟平均值 ts_table.add_pre_aggregation(300, "SUM").unwrap(); // 5分钟总和 // 写入数据(预聚合会自动更新) let records = vec![ TimeSeriesRecord { timestamp: 1609459200000, // 2021-01-01 00:00:00 value: 25.5, tags: vec!["sensor_id=1"], }, // 更多记录... ]; ts_table.batch_write(&records).unwrap(); // 查询预聚合数据 let start_time = 1609459200000; let end_time = 1609462800000; // 1小时后 // 查询1分钟平均值数据 let avg_result = ts_table.query_pre_aggregated(start_time, end_time, 60, "AVG").unwrap(); for record in avg_result { println!("时间: {}, 平均值: {}", record.timestamp, record.value); } // 查询5分钟总和数据 let sum_result = ts_table.query_pre_aggregated(start_time, end_time, 300, "SUM").unwrap(); for record in sum_result { println!("时间: {}, 总和: {}", record.timestamp, record.value); } ``` #### 优势 - **查询速度更快**:直接获取预计算结果,避免实时计算 - **减少CPU使用**:避免实时聚合计算 - **性能稳定**:查询性能不受数据量影响 - **配置灵活**:支持多种聚合函数和时间间隔 #### 适用场景 - **实时监控**:快速查询最近的聚合数据 - **历史数据分析**:高效查询长时间范围的聚合结果 - **仪表盘展示**:预计算常用时间间隔的聚合数据 - **告警系统**:基于预聚合数据进行阈值判断 ## 向量数据库 remdb提供了强大的向量数据库功能,支持原生向量类型、多种距离度量和高效的向量索引: ### 基本使用 ```rust use remdb::*; use remdb::config::{DbConfig, WALConfig}; // 初始化数据库配置 let config = Box::leak(Box::new(DbConfig { tables: vec![], total_memory: 16 * 1024 * 1024, // 16MB low_power_mode_supported: false, low_power_max_records: None, memory_allocator: &SimpleAllocator, wal_config: WALConfig { log_path: "./wal".to_string(), log_mode: remdb::config::LogMode::Async, checkpoint_interval_ms: 60000, log_file_size_limit: 16 * 1024 * 1024, log_prealloc_size: 4 * 1024 * 1024, log_segment_size: 16 * 1024 * 1024, retained_checkpoints: 2, }, time_series_defaults: TimeSeriesConfig { partition_duration_secs: 3600, retention_period_secs: 7 * 24 * 3600, compression: remdb::time_series::compression::CompressionType::None, max_partitions: 100, }, })); // 初始化数据库 let mut db = RemDb::new(config); db.init()?; // 创建包含向量字段的表 let create_sql = r#"CREATE TABLE products ( id INT32 PRIMARY KEY, name TEXT, embedding VECTOR(4) WITH DISTANCE=IP )"#; db.sql_query(create_sql)?; // 插入向量数据 let insert_sql = r#"INSERT INTO products (id, name, embedding) VALUES (1, 'product1', '[0.1, 0.2, 0.3, 0.4]'), (2, 'product2', '[1.0, 0.9, 0.8, 0.7]') "#; db.sql_query(insert_sql)?; // 向量相似性查询 - 内积距离 let similarity_sql = "SELECT id, name, embedding <#> '[0.2, 0.3, 0.4, 0.5]' AS similarity FROM products ORDER BY similarity DESC LIMIT 2"; let similarity_result = db.sql_query(similarity_sql)?; // 创建向量索引 let create_index_sql = "CREATE INDEX idx_products_embedding ON products (embedding) USING HNSW WITH (M=16, ef_construction=200)"; db.sql_query(create_index_sql)?; ``` ## RBAC权限管理 remdb提供基于角色的访问控制(RBAC),支持用户、角色和权限管理,提供细粒度的数据访问控制。 ### 基本使用 ```rust use remdb::rbac::{Permission, Role, User, RbacManager}; // 创建RBAC管理器 let mut rbac = RbacManager::new(); // 创建角色 let role = Role::new("admin", "Administrator"); rbac.create_role(role); // 创建用户 let user = User::new("alice", "password_hash"); rbac.create_user(user); // 分配角色给用户 rbac.assign_role("alice", "admin"); // 授予权限 rbac.grant_permission("admin", Permission::Select("*")); rbac.grant_permission("admin", Permission::Insert("*")); rbac.grant_permission("admin", Permission::Delete("*")); // 检查权限 let has_permission = rbac.check_permission("alice", &Permission::Select("users")); ``` ## AI模型推理 remdb集成ONNX运行时,支持AI模型推理,提供内置模型和自定义模型加载功能。 ### 基本使用 ```rust use remdb::model::{OnnxModel, ModelManager, ModelUDF}; use remdb::model::builtin_models::{list_builtin_models, get_builtin_model}; // 列出内置模型 let models = list_builtin_models(); // 加载内置模型 let model = get_builtin_model("bge-m3"); // 创建模型管理器 let mut manager = ModelManager::new(); let model_path = "models/model.onnx"; let model = OnnxModel::load(model_path)?; manager.register_model("my_model", model); // 执行模型推理 let input = vec![0.1, 0.2, 0.3, 0.4]; let output = manager.infer("my_model", &input)?; ``` ## WAL日志压缩 remdb支持LZ4和Zstd两种WAL日志压缩算法,有效减少日志存储空间。 ### 配置示例 ```rust use remdb::config::WALCompressionType; // 使用LZ4压缩 let mut config = DbConfig::default(); config.wal_compression = WALCompressionType::Lz4; // 使用Zstd压缩 config.wal_compression = WALCompressionType::Zstd; ``` ## 系统表 remdb提供系统表管理功能,支持数据库元数据查询和系统信息监控。 ### 基本使用 ```sql -- 查询所有表信息 SELECT * FROM information_schema.tables; -- 查询表结构信息 SELECT * FROM information_schema.columns WHERE table_name = 'users'; -- 查询数据库状态 SELECT * FROM information_schema.database_status; ``` ## 平台支持 ### POSIX平台 启用POSIX平台支持: ```toml features = ["posix"] ``` ### 裸机平台 启用裸机平台支持: ```toml features = ["baremetal"] ``` ## 测试 ### 运行核心库测试 ```bash cargo test --lib ``` ### 运行带有特定特性的核心库测试 ```bash cargo test --lib --features "pubsub ha" ``` ### 运行完整测试套件 ```bash cargo test ``` ### 检查编译 在no_std环境下检查编译: ```bash cargo check --tests --no-default-features ``` ### 在baremetal环境下检查编译: ```bash cargo check --no-default-features --features=baremetal ``` ### 在baremetal环境下运行测试 由于测试框架依赖std库,直接运行`cargo test`在baremetal环境下会失败。但你可以通过以下步骤验证代码在baremetal环境下的正确性: 1. 确保代码可以成功编译: ```bash cargo check --no-default-features --features=baremetal ``` 2. 对于实际的baremetal硬件测试,你可能需要: - 使用交叉编译工具链 - 编写针对目标硬件的测试代码 - 配置适当的链接脚本 - 使用烧录工具将可执行文件写入硬件 3. 示例交叉编译命令(以ARM Cortex-M为例): ```bash cargo build --target thumbv7m-none-eabi --no-default-features --features=baremetal ``` ### 测试注意事项 - 核心库测试(`cargo test --lib`)不依赖于特定特性,是验证基本功能的最佳方式 - 完整测试套件(`cargo test`)可能会因为示例和集成测试依赖特定特性而失败 - 带有特性的测试(如`--features "pubsub ha"`)需要确保相关特性已正确配置 - 部分示例和集成测试可能需要特定的运行环境或配置 ## 示例 查看`examples`目录下的示例代码: - `basic_usage.rs`:基本使用示例,展示表定义、插入、查询和事务操作 - `low_power_mode.rs`:低功耗模式示例,展示如何配置和使用低功耗模式 - `incremental_snapshot.rs`:增量快照示例,展示如何保存和恢复增量快照 - `sql_query.rs`:SQL查询示例,展示如何使用SQL查询内存数据库 - `ddl_example.rs`:DDL示例,展示如何使用DDL宏定义表和索引 - `ddl_runtime_example.rs`:运行时DDL配置示例,展示如何使用运行时DDL API - `pubsub_example.rs`:发布/订阅示例,展示如何使用基于UDP的高可靠数据订阅与发布功能 - `time_series.rs`:时间序列示例,展示如何处理时间序列数据 - `vector_example.rs`:向量数据库示例,展示如何使用向量字段、插入向量数据和执行向量相似性查询 - `vector_distance_test.rs`:向量距离测试示例,展示不同距离度量的向量相似性计算 - `drop_table_example.rs`:DROP TABLE示例,展示如何使用SQL DROP TABLE语句删除表结构 - `test_remdb_server.rs`:主从复制示例,展示如何使用同步或异步复制模式运行主从服务器 ### 主从复制示例 > 注意:使用此功能需要在Cargo.toml中启用`ha`特性 `test_remdb_server.rs`示例展示了如何使用主从复制功能,支持通过命令行参数设置同步或异步复制模式: #### 主节点启动命令 ```bash # 同步模式 cargo run --example test_remdb_server master sync # 异步模式 cargo run --example test_remdb_server master async ``` #### 从节点启动命令 ```bash # 同步模式 cargo run --example test_remdb_server slave sync # 异步模式 cargo run --example test_remdb_server slave async ``` #### 示例输出 ``` Starting RemDB Server... Role: Master Replication Mode: Sync RemDB Server started successfully! Listening on UDP port 5555 Topics available: - WAL_INSERT (ID: 1) - WAL insert operations - WAL_UPDATE (ID: 2) - WAL update operations - WAL_DELETE (ID: 3) - WAL delete operations - WAL_TIMESERIES_INSERT (ID: 4) - WAL timeseries insert operations - WAL_COMMIT (ID: 5) - WAL commit operations - WAL_ABORT (ID: 6) - WAL abort operations - WAL_CHECKPOINT (ID: 7) - WAL checkpoint operations - WAL_ALL (ID: 8) - All WAL operations - TABLES (ID: 9) - Table creation/deletion events - HEARTBEAT - Sent every 5 seconds ``` ## 项目结构 ``` remdb/ ├── src/ │ ├── lib.rs # 主库入口 │ ├── types.rs # 基本数据类型定义 │ ├── config.rs # 编译时配置宏 │ ├── table.rs # 内存表实现 │ ├── index.rs # 索引实现 │ ├── transaction.rs # 事务管理 │ ├── monitor.rs # 数据库监控模块 │ ├── c_api.rs # C语言接口实现 │ ├── compression.rs # 数据压缩模块 │ ├── log.rs # 日志模块 │ ├── utf8.rs # UTF8字符支持 │ ├── sync.rs # 同步原语 │ ├── system_tables.rs # 系统表管理 │ ├── wal_compression.rs # WAL日志压缩 │ ├── sql/ │ │ ├── mod.rs # SQL查询模块 │ │ ├── query_parser.rs # SQL查询解析器 │ │ ├── query_executor.rs # SQL查询执行器 │ │ ├── result_set.rs # 结果集处理 │ │ ├── error.rs # SQL错误处理 │ │ ├── utils.rs # SQL工具函数 │ │ ├── functions/ # SQL函数 │ │ │ ├── mod.rs │ │ │ ├── aggregate.rs # 聚合函数 │ │ │ ├── math.rs # 数学函数 │ │ │ ├── string.rs # 字符串函数 │ │ │ ├── time.rs # 时间函数 │ │ │ └── json.rs # JSON函数 │ │ └── operations/ # SQL操作 │ │ ├── mod.rs │ │ ├── expression.rs # 表达式处理 │ │ ├── comparison.rs # 比较操作 │ │ ├── ddl.rs # DDL操作 │ │ └── vector.rs # 向量操作 │ ├── memory/ │ │ ├── allocator.rs # 静态内存分配器 │ │ ├── pool.rs # 内存池 │ │ └── mod.rs │ ├── platform/ │ │ ├── mod.rs # 平台抽象层定义 │ │ ├── posix.rs # POSIX平台实现 │ │ └── baremetal.rs # 裸机平台实现 │ ├── ha/ │ │ ├── mod.rs # 高可用模块入口 │ │ ├── manager.rs # HA管理器实现 │ │ ├── replication.rs # 复制功能实现 │ │ ├── heartbeat.rs # 心跳检测实现 │ │ ├── role.rs # 角色管理实现 │ │ ├── protocol.rs # 同步协议定义 │ │ ├── sync_handler.rs # 主节点同步处理器 │ │ └── sync_receiver.rs # 从节点同步接收器 │ ├── pubsub/ │ │ ├── mod.rs # 发布/订阅模块入口 │ │ ├── protocol.rs # 协议帧定义与解析 │ │ ├── udp.rs # 跨平台UDP套接字封装 │ │ ├── subscriber.rs # 订阅者管理 │ │ ├── publisher.rs # 发布者管理 │ │ ├── topics.rs # 预定义主题 │ │ ├── ttl_ringbuffer.rs # TTL环形缓冲区 │ │ └── crc32.rs # CRC32校验实现 │ ├── json/ │ │ ├── mod.rs # JSON模块入口 │ │ ├── document.rs # JSON文档处理 │ │ ├── path.rs # JSON路径查询 │ │ └── memory_pool.rs # JSON内存池 │ ├── rbac/ │ │ ├── mod.rs # RBAC权限管理模块 │ │ ├── user.rs # 用户管理 │ │ ├── role.rs # 角色管理 │ │ ├── permission.rs # 权限定义 │ │ └── manager.rs # 权限管理器 │ ├── model/ │ │ ├── mod.rs # AI模型模块入口 │ │ ├── model_manager.rs # 模型管理器 │ │ ├── builtin_models.rs # 内置模型 │ │ ├── onnx_runtime.rs # ONNX运行时 │ │ ├── model_udf.rs # 模型UDF函数 │ │ ├── cache.rs # 模型缓存 │ │ ├── downloader.rs # 模型下载器 │ │ ├── worker_manager.rs # 工作进程管理 │ │ └── worker_protocol.rs # 工作进程协议 │ └── time_series/ │ ├── mod.rs # 时序数据库模块入口 │ ├── table.rs # 时序表实现 │ ├── index.rs # 时序数据索引 │ ├── compression.rs # 压缩算法实现 │ ├── partition.rs # 数据分区实现 │ ├── lifecycle.rs # 数据生命周期管理 │ └── config.rs # 时序数据库配置 ├── examples/ # 示例代码 │ ├── api/ # API使用示例 │ ├── sql/ # SQL使用示例 │ └── misc/ # 其他示例 ├── tests/ # 测试代码 ├── include/ # C语言头文件 ├── models/ # AI模型文件 ├── onnxruntime/ # ONNX运行时文件 ├── Cargo.toml # 项目配置 └── README.md # 项目说明文档 ``` ## 许可证 MIT许可证 ## 贡献 欢迎提交问题和拉取请求! ## 项目链接 - 国内:https://gitee.com/totaltrust/remdb - 国外:https://github.com/bobjia/remdb - Crates:https://crates.io/crates/remdb ## 注意事项 1. remdb专为嵌入式系统设计,不适合大规模数据存储 2. 在no_std环境下使用时,需要提供适当的内存分配器实现 3. 请确保在使用前正确初始化内存分配器和平台抽象层 ## 未来计划 - 支持更多的数据类型 - 优化内存使用 - 提供更多的索引类型 - 增加更多的示例和文档 - 实现更复杂的内存优化算法 - 实现更灵活的内存分配策略 - 完善运行时DDL配置API,支持完整的表和索引创建功能 - 支持ALTER TABLE语句 - 优化运行时DDL操作的性能 - 支持更复杂的索引配置选项