小米自研vela系统kvdb数据库的使用(一)
KVDB数据库介绍
- KVDB 数据库详细介绍
- KVDB 的基本原理
- KVDB 的应用场景
- 1. 缓存系统
- 2. 配置管理
- 3. 会话存储与用户状态管理
- 4. 实时数据处理
- 5. 日志记录与事件存储
- 6. 分布式存储
- KVDB 的作用
- KVDB 数据库的典型实现
- 1. LevelDB
- 2. RocksDB
- 3. LMDB (Lightning Memory-Mapped Database)
- 4.UnQLite(重点讲述,也是小米自研系统使用的数据库类型)
- KVDB 调用方式
- 1. 安装 UnQLite
- 2. UnQLite 使用示例
- 3. 常用功能说明
- 4. 嵌入式应用中的 UnQLite
- 嵌入式场景kvdb数据库的使用(二)
KVDB 数据库详细介绍
KVDB(Key-Value Database,键值数据库)是一种使用键(Key)和对应的值(Value)来存储数据的数据库。它是 NoSQL 数据库的一种简单而高效的类型,以键值对的形式来存储数据,适合用于高速读写和处理简单查询的场景。KVDB 通常非常轻量,性能高,扩展性强,尤其在分布式系统中具有重要的应用。
KVDB 最常见的实现有 LevelDB、RocksDB、LMDB 、UnQLite等。
小米自研的操作系统vela就是使用的kvdb数据库,具体使用的是UnQLite这种嵌入式轻量数据库,见vela服务与框架中的通用框架KVDB
KVDB 的基本原理
- 键(Key):每个数据项都有一个唯一的键(通常是一个字符串或整数),用来标识该项数据。
- 值(Value):与每个键相关联的数据项,可以是任何类型的数据,如字符串、数字、JSON 数据、二进制数据等。
KVDB 数据库的设计原则是极简和高效,它为键值对的插入、删除和查找操作提供了高性能支持。常见的 KVDB 实现如 LevelDB,通常支持对数据进行持久化存储,但它也能高效地进行内存中的数据操作,提供快速的读写速度。
KVDB 的应用场景
KVDB 数据库通常用于以下场景:
1. 缓存系统
KVDB 由于其高性能的读取和写入操作,广泛用于缓存系统中。它能够提供快速的数据访问,减少数据库的负载,并加快应用的响应速度。例如,Redis 就是一种广泛使用的键值存储系统。
- 场景实例:在 web 应用中,可以将用户的会话信息、频繁访问的数据缓存到 KVDB 数据库中,从而提升系统性能。
2. 配置管理
KVDB 被广泛用于存储和管理应用的配置。由于 KVDB 的简单和高效,很多系统会将配置信息(如 API 密钥、数据库连接信息、应用设置等)存储为键值对。
- 场景实例:微服务架构中的配置中心,利用 KVDB 存储和管理服务的配置信息,便于快速加载和修改配置。
3. 会话存储与用户状态管理
KVDB 也非常适用于存储临时的用户数据,如会话信息和临时状态。常常被用在需要快速读取和写入的应用中,比如 Web 应用中的用户会话管理。
- 场景实例:在用户登录的情况下,使用 KVDB 存储用户的会话信息,并根据会话的键值进行验证和获取用户数据。
4. 实时数据处理
KVDB 可以存储实时生成的海量数据,并进行快速检索。在处理高频率、低延迟的实时数据时,KVDB 系统可以提供极好的性能。
- 场景实例:在物联网 (IoT) 环境中,用 KVDB 存储传感器采集到的实时数据,进行快速查询和处理。
5. 日志记录与事件存储
KVDB 的高性能特性使其适合用于存储应用的日志信息,尤其是那些需要快速写入和检索的日志数据。
- 场景实例:将事件日志数据按时间戳存储为键值对,方便后续的检索和分析。
6. 分布式存储
很多现代 KVDB 数据库(如 RocksDB)被设计为分布式系统的一部分,支持大规模的数据存储和快速访问。在云原生架构和分布式系统中,KVDB 被用于存储分布式数据和状态信息。
- 场景实例:在 Kubernetes 或其他分布式环境中,使用 KVDB 存储节点的状态信息和元数据。
KVDB 的作用
- 高性能:KVDB 的设计通常针对高效的读写操作,支持快速插入、删除和查询数据,适合需要低延迟的应用。
- 简单易用:KVDB 使用键值对的存储方式,数据模型简单易懂,易于使用和维护。
- 灵活性高:KVDB 的值可以是任意格式的数据,不限于字符串和数字,因此它具有很高的灵活性,适用于多种数据存储需求。
- 扩展性:许多 KVDB 实现支持水平扩展,能够适应大规模的数据存储需求。对于分布式 KVDB,多个节点可以协同工作,形成一个高效的集群。
- 数据持久化:大多数 KVDB 提供数据持久化功能,即使系统重启后数据依然能够保持不丢失,确保了数据的持久性。
KVDB 数据库的典型实现
1. LevelDB
LevelDB 是 Google 开发的一个高性能、嵌入式的键值数据库。它在许多应用中得到广泛使用,特别是在需要嵌入式存储的情况下。LevelDB 具有非常高的写入性能和低延迟的查询性能。
特点:
- 基于 Log-Structured Merge Tree(LSM Tree)结构,适合写密集型应用。
- 高性能的存储和读取能力,特别适合嵌入式设备或单一应用。
- 数据存储为 SSTable 文件格式,支持持久化存储。
2. RocksDB
RocksDB 是 Facebook 开发的一个高性能、嵌入式键值数据库,基于 LevelDB 构建,进行了优化。RocksDB 在支持大规模数据和高并发写入方面表现尤为突出。
特点:
- 优化的写入性能和查询速度,支持大规模数据存储。
- 支持高并发的读写操作,适合大数据量和高频访问场景。
- 支持数据压缩和索引,能够有效管理存储空间。
- 提供灵活的事务机制。
3. LMDB (Lightning Memory-Mapped Database)
LMDB 是一个内存映射的键值数据库,它提供极高的性能,特别适用于存储读取密集型数据。它在嵌入式设备和低资源系统中表现出色。
特点:
- 高效的内存映射文件存储机制。
- 支持高并发读取和事务性写入。
- 数据一致性高,支持 ACID 事务。
- 适合在资源有限的环境中使用。
4.UnQLite(重点讲述,也是小米自研系统使用的数据库类型)
UnQLite 是一个轻量级的嵌入式 NoSQL 数据库,它结合了 键值存储 和 文档存储 的特点,支持嵌入式应用,具有高效、易用、内存占用低等特点,适用于资源受限的嵌入式设备。它支持对 JSON 数据进行存储和操作,并且不依赖外部服务器。
KVDB 调用方式
下面以 UnQLite 为例,简要介绍如何在代码中使用 KVDB 数据库。
1. 安装 UnQLite
安装方法(Linux 示例)
从官网或 GitHub 获取源码:
官网下载地址:http://unqlite.org/
GitHub 地址:https://github.com/symisc/unqlite
编译安装(如果你使用的是 Linux 系统):
git clone https://github.com/symisc/unqlite.git
cd unqlite
make
sudo make install
这样就可以在系统中安装好 UnQLite。
Windows 或其他平台
对于 Windows 和其他平台,你可以参考 UnQLite 官方文档,下载预编译的二进制文件,或者从源码进行编译。
2. UnQLite 使用示例
创建数据库
首先我们需要一个 C 程序来演示如何使用 UnQLite 创建数据库、插入数据、读取数据,并关闭数据库。
头文件和库链接
确保在编译时链接 unqlite 库文件。你需要包含 unqlite.h 头文件并链接 libunqlite.so(Linux)或 libunqlite.a(Windows)。
代码示例
以下是一个简单的示例,展示了如何使用 UnQLite 创建数据库、插入键值对、查询数据并关闭数据库。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "unqlite.h"
// 数据库文件名
#define DB_PATH "test.db"
int main() {
// 定义数据库指针
unqlite *db;
// 打开数据库,如果数据库不存在则创建
int rc = unqlite_open(&db, DB_PATH, UNQLITE_OPEN_CREATE);
if (rc != UNQLITE_OK) {
printf("Failed to open database: %d\n", rc);
return -1;
}
// 插入键值对数据
const char *key = "name";
const char *value = "John Doe";
rc = unqlite_kv_store(db, key, strlen(key), value, strlen(value));
if (rc != UNQLITE_OK) {
printf("Failed to insert data: %d\n", rc);
unqlite_close(db);
return -1;
}
// 读取存储的数据
char retrieved_value[100];
int retrieved_len = sizeof(retrieved_value);
rc = unqlite_kv_fetch(db, key, strlen(key), retrieved_value, &retrieved_len);
if (rc != UNQLITE_OK) {
printf("Failed to fetch data: %d\n", rc);
unqlite_close(db);
return -1;
}
// 输出读取到的数据
printf("Retrieved value: %.*s\n", retrieved_len, retrieved_value);
// 关闭数据库
unqlite_close(db);
return 0;
}
代码解析
unqlite_open():打开数据库。如果数据库文件不存在,且指定了 UNQLITE_OPEN_CREATE 参数,它会创建一个新的数据库文件。
unqlite_kv_store():向数据库插入一对键值数据。在这里,key 是 “name”,value 是 “John Doe”。
unqlite_kv_fetch():从数据库中获取指定键(key)对应的值。读取后,retrieved_value 存储了获取的数据。
unqlite_close():关闭数据库,释放相关资源
编译和运行
假设你已经正确安装了 UnQLite 库,使用以下命令编译和运行该程序:
gcc -o unqlite_example unqlite_example.c -lunqlite
./unqlite_example
输出
Retrieved value: John Doe
3. 常用功能说明
- 创建数据库
使用 unqlite_open() 打开数据库,如果数据库文件不存在,则会自动创建一个新的数据库
int unqlite_open(unqlite **ppDb, const char *zDbName, int flags);
- 插入数据(键值存储)
通过 unqlite_kv_store() 插入数据。
int unqlite_kv_store(unqlite *pDb, const void *pKey, int nKeyLen, const void *pData, int nDataLen);
pKey:键的指针。
nKeyLen:键的长度。
pData:值的指针。
nDataLen:值的长度。
- 读取数据
通过 unqlite_kv_fetch() 读取数据。
int unqlite_kv_fetch(unqlite *pDb, const void *pKey, int nKeyLen, void *pData, int *pDataLen);
pKey:键的指针。
nKeyLen:键的长度。
pData:存储读取数据的缓冲区。
pDataLen:输出参数,存储实际读取的值的长度。
- 删除数据
通过 unqlite_kv_delete() 删除数据。
int unqlite_kv_delete(unqlite *pDb, const void *pKey, int nKeyLen);
- 关闭数据库
使用 unqlite_close() 关闭数据库连接并释放资源。
void unqlite_close(unqlite *pDb);
4. 嵌入式应用中的 UnQLite
UnQLite 适用于以下场景:
嵌入式设备:由于它非常轻量,因此特别适合嵌入式应用,如 IoT 设备、智能家居等。
内存受限的设备:UnQLite 可以在内存限制较大的设备上运行,并且能够将数据存储在磁盘上,减少内存占用。
键值对存储:适合存储如设备配置、日志数据等简单的键值对数据。
文档存储:也可以用于存储 JSON 格式的数据,适用于需要存储和查询半结构化数据的应用。