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():
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():
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():
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
服务器处理:
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 命令示例
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
