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

相关推荐
寻星探路3 分钟前
【深度长文】万字攻克网络原理:从 HTTP 报文解构到 HTTPS 终极加密逻辑
java·开发语言·网络·python·http·ai·https
执笔论英雄3 小时前
【大模型学习cuda】入们第一个例子-向量和
学习
wdfk_prog3 小时前
[Linux]学习笔记系列 -- [drivers][input]input
linux·笔记·学习
七夜zippoe3 小时前
CANN Runtime任务描述序列化与持久化源码深度解码
大数据·运维·服务器·cann
盟接之桥3 小时前
盟接之桥说制造:引流品 × 利润品,全球电商平台高效产品组合策略(供讨论)
大数据·linux·服务器·网络·人工智能·制造
会员源码网4 小时前
理财源码开发:单语言深耕还是多语言融合?看完这篇不踩坑
网络·个人开发
米羊1215 小时前
已有安全措施确认(上)
大数据·网络
Fcy6485 小时前
Linux下 进程(一)(冯诺依曼体系、操作系统、进程基本概念与基本操作)
linux·运维·服务器·进程
袁袁袁袁满5 小时前
Linux怎么查看最新下载的文件
linux·运维·服务器
代码游侠5 小时前
学习笔记——设备树基础
linux·运维·开发语言·单片机·算法