KVStore 多行文章型键值扩展解析:切片存储与客户端多行交互

基于已有的 KV 引擎,本文详细解析文章型键值扩展的完整流程,包括多行正文解析、切片存储机制、增量日志绑定,以及客户端交互反馈示例。

一、文章型键值扩展概览

为了支持 大文本、多行正文 的存储,KVStore 引入了 article.c 扩展模块,提供如下能力:

多行 SET 命令:

SET key <多行正文>

...

END

支持正文超过 CHUNK_SIZE 的自动切片存储

切片存储绑定增量日志,实现持久化

提供 GET、MOD、DEL、EXIST 命令,兼容普通键值与切片键值

核心函数:article_protocol()(协议解析)、article_handler()(网络层接口)

二、切片存储机制(chunked storage)

1. 保存正文

核心函数 save_chunked_value():

cpp 复制代码
static void save_chunked_value(const char *key, const char *value) {
    int len = strlen(value);
    int chunks = (len + CHUNK_SIZE - 1) / CHUNK_SIZE;

    char subkey[512];
    char chunkbuf[CHUNK_SIZE + 1];

    for (int i = 0; i < chunks; i++) {
        snprintf(subkey, sizeof(subkey), "%s#%d", key, i);
        int start = i * CHUNK_SIZE;
        int size = (len - start > CHUNK_SIZE) ? CHUNK_SIZE : (len - start);
        strncpy(chunkbuf, value + start, size);
        chunkbuf[size] = '\0';
        kvs_set(subkey, chunkbuf);
        journal_append("SET", subkey, chunkbuf);
    }

    snprintf(subkey, sizeof(subkey), "%s#meta", key);
    char meta[32];
    sprintf(meta, "%d", chunks);
    kvs_set(subkey, meta);
    journal_append("SET", subkey, meta);
}

将正文拆分为若干片段,每片不超过 4KB

每片单独存储,键名为 key#0, key#1, ...

元信息存储在 key#meta,记录切片数量

每片写入 journal,保证增量持久化

2. 读取正文

核心函数 load_chunked_value():

cpp 复制代码
static char *load_chunked_value(const char *key) {
    char meta_key[512];
    snprintf(meta_key, sizeof(meta_key), "%s#meta", key);
    char *meta_val = kvs_get(meta_key);
    if (!meta_val) return NULL;

    int chunks = atoi(meta_val);
    char *result = malloc(chunks * CHUNK_SIZE + 1);
    result[0] = '\0';

    char subkey[512];
    for (int i = 0; i < chunks; i++) {
        snprintf(subkey, sizeof(subkey), "%s#%d", key, i);
        char *chunk = kvs_get(subkey);
        if (chunk) strcat(result, chunk);
    }
    return result;
}

根据 meta 信息获取切片数量

按序拼接每片正文,恢复完整内容

3. 删除正文

核心函数 delete_chunked_value():

cpp 复制代码
static void delete_chunked_value(const char *key) {
    char meta_key[512];
    snprintf(meta_key, sizeof(meta_key), "%s#meta", key);
    char *meta_val = kvs_get(meta_key);
    if (!meta_val) return;

    int chunks = atoi(meta_val);
    char subkey[512];
    for (int i = 0; i < chunks; i++) {
        snprintf(subkey, sizeof(subkey), "%s#%d", key, i);
        kvs_del(subkey);
        journal_append("DEL", subkey, "");
    }
    kvs_del(meta_key);
    journal_append("DEL", meta_key, "");
}

遍历删除所有切片和 meta

日志记录每条 DEL 操作

三、协议解析与客户端交互

核心函数 article_protocol() 解析客户端命令:

SET:

普通模式:SET key value

正文大于 CHUNK_SIZE 自动切片

写入 journal

多行模式:

SET key

<多行正文>

END

循环读取客户端发送的多行数据

超长正文切片保存

GET:

自动检测切片或普通键值

返回完整内容

MOD:

删除旧切片

保存新内容(切片或普通)

DEL / EXIST:

支持普通键值与切片键值

SAVE / LOAD:

调用 snapshot 持久化接口

SAVE 后清空日志

LOAD 后可回放 journal,保证数据完整性

1. SET 命令示例

客户端发送多行:

SET MESSAGE

The Digital Crossroads: Navigating Human Connection in the Age of Technological Ubiquity

We stand at an unprecedented juncture...

END

服务器处理:

cpp 复制代码
char buf[MAX_BODY_SIZE] = {0};
char line[1024];
while (fgets(line, sizeof(line), fp)) {
    if (strncmp(line, "END", 3) == 0) break;
    strcat(buf, line);
}
if (strlen(buf) > CHUNK_SIZE) save_chunked_value(key, buf);
else { kvs_set(key, buf); journal_append("SET", key, buf); }
sprintf(response, "OK\n");

自动累积多行内容

超长正文切片存储

日志记录每条操作

2. GET 命令示例

cpp 复制代码
char *val = load_chunked_value(key);
if (val) { sprintf(response, "%s\n", val); free(val); }
else { sprintf(response, "(nil)\n"); }

检测是否存在切片

返回完整正文

3. MOD / DEL / EXIST

MOD 自动删除旧片段,保存新内容

DEL 删除所有片段

EXIST 同时检查普通键值与切片键值

四、与持久化机制结合

切片操作 完全兼容 snapshot 和 journal

SAVE/LOAD 调用 snapshot 接口

journal_append 记录每片写入和删除

系统恢复时:

LOAD 恢复全量 snapshot

journal 回放切片 SET/MOD/DEL 操作

保证多行大文本数据完整恢复

五、总结

多行文章型键值扩展:

支持任意长度正文(64KB 上限)

自动切片存储,配合 journal 实现增量持久化

客户端交互:

SET/GET/MOD/DEL/EXIST 命令支持多行正文

超长正文自动切片,透明给客户端

数据恢复:

SAVE/LOAD + journal 回放保证完整性

与普通 KV 引擎兼容

文章型键值扩展,使 KVStore 不仅可以处理简单键值,还能高效存储大文本、多行数据,并确保持久化与恢复完整


根据零声教育教学写作https://github.com/0voice

相关推荐
江湖有缘10 小时前
极简部署Radicale:Docker快速搭建自托管日历 / 联系人服务
运维·docker·容器
秋雨梧桐叶落莳10 小时前
【iOS】 AutoLayout初步学习
学习·macos·ios·objective-c·cocoa·xcode
huanmieyaoseng100311 小时前
Linux安装达梦数据库DM8
linux·运维·数据库
for_ever_love__11 小时前
Objective-C学习UI 的初步了解(2)
学习·ui·objective-c
没bug怎么跑11 小时前
rsync全网备份全流程
linux·运维·github
@insist12311 小时前
网络工程师-网络安全核心加密技术体系:对称 / 非对称加密、数字签名与证书全解析
网络·安全·web安全·网络工程师·软考·软件水平考试
non-action_pilgrim11 小时前
《小坦克大战小怪兽》小游戏实战四:基于 protoactor-go 的游戏服务器框架与状态持久化实战
服务器·游戏·golang
盐真卿11 小时前
华为数通 | VRRP负载分担与网关冗余实验:主备切换+流量分流,企业高可用网络实战
网络·华为
TechMasterPlus11 小时前
Linux 驱动开发深度解析:从内核模块到设备驱动
linux·运维·驱动开发
m0_7167652311 小时前
数据结构--顺序表的插入、删除、查找详解
c语言·开发语言·数据结构·c++·学习·算法·visual studio