# sqlkv **Repository Path**: MM-Q/sqlkv ## Basic Information - **Project Name**: sqlkv - **Description**: No description available - **Primary Language**: Go - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-08-04 - **Last Updated**: 2026-08-05 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README
# 🗄️ sqlkv **基于 SQLite 模拟 Redis 设计的轻量级键值库(纯 Go、零 CGO)** [![Go](https://img.shields.io/badge/Go-1.26.4-00ADD8?logo=go&logoColor=white)](https://go.dev/) [![License](https://img.shields.io/badge/License-MIT-green.svg)](./LICENSE) [![Status](https://img.shields.io/badge/Status-Active-brightgreen.svg)](https://gitee.com/MM-Q/sqlkv) [![CGO](https://img.shields.io/badge/CGO-No-9cf.svg)](./go.mod) [![Database](https://img.shields.io/badge/Database-SQLite-blue.svg)](https://www.sqlite.org/) [![仓库](https://img.shields.io/badge/Gitee-MM--Q%2Fsqlkv-orange.svg)](https://gitee.com/MM-Q/sqlkv) [仓库地址](https://gitee.com/MM-Q/sqlkv) · [功能特性](#-核心特性) · [快速开始](#-快速开始) · [API 文档](#-api-文档概述) · [许可证](#-许可证)
--- ## 📖 项目简介 **sqlkv** 是一个基于 **SQLite** 模拟 **Redis** 使用体验的轻量级键值库。它保留了 Redis 简洁的 API 风格(`Set` / `Get` / `Del` / `Select` 切换 16 个逻辑库等),底层由 SQLite 提供持久化、事务与并发保证。 使用纯 Go 实现(基于 `modernc.org/sqlite`),**无 CGO 依赖**,交叉编译简单、部署零成本——非常适合作为嵌入式存储、配置中心、小型缓存或数据迁移的中间格式。 ``` ┌─────────────────────────────────────────────┐ │ sqlkv (Redis 风格 API) │ ├─────────────────────────────────────────────┤ │ Set · Get · Del · Exists · Keys · ForEach │ │ SetNX · SetMany · GetMany · Count │ │ Select(0~15) · FlushDB · FlushAll │ │ SetJSON/GetJSON · SetString/GetString │ │ Dump · Load · Backup · Vacuum · DBSize │ ├─────────────────────────────────────────────┤ │ SQLite (modernc.org/sqlite) │ │ WAL · 预编译语句 · 连接池 · 事务 │ └─────────────────────────────────────────────┘ ``` --- ## ✨ 核心特性 - 🚀 **纯 Go、零 CGO**:基于 `modernc.org/sqlite`,跨平台交叉编译无障碍,无需 C 工具链 - 🔑 **Redis 风格 API**:`Select` 切换 0~15 共 16 个逻辑库,语义贴近 Redis - ⚡ **高性能优化**:预编译语句(Statement Cache)、UPSERT 写入、WAL 模式、连接池多路复用 - 💾 **持久化**:数据落盘 SQLite 单文件,天然具备事务与崩溃恢复能力 - 🔒 **并发安全**:多连接读写并发安全(`-race` 检测通过),多进程写冲突自动等待 - 🧩 **JSON 原生支持**:`SetJSON` / `GetJSON` 直接存取任意结构体 - 📦 **批量操作**:`SetMany` / `GetMany` 事务化批量读写 - 🗂️ **流式导入导出**:`Dump` / `DumpTo` / `Load` / `LoadFrom` 支持任意大小数据的流式迁移 - 🛠️ **运维能力**:`Backup`(一致性快照)、`Vacuum`(空间回收)、`DBSize`(容量统计) - 🎯 **错误语义清晰**:内置 `ErrKeyNotFound` 等 sentinel error,配合 `errors.Is` 精确判断 --- ## 📦 安装指南 ### 环境要求 | 要求 | 说明 | |------|------| | Go 版本 | **1.26.4** 或更高 | | 操作系统 | Windows / Linux / macOS(纯 Go,无平台限制) | | 依赖 | 无 CGO,仅需 `modernc.org/sqlite` | ### 安装 在你的项目目录中执行: ```bash go get gitee.com/MM-Q/sqlkv ``` > 💡 仓库地址:[https://gitee.com/MM-Q/sqlkv.git](https://gitee.com/MM-Q/sqlkv.git) --- ## 🚀 快速开始 ### 基础用法 ```go package main import ( "fmt" "log" kvstore "gitee.com/MM-Q/sqlkv" ) func main() { // 打开数据库(不存在则自动创建,默认切换到 DB 0) kv, err := kvstore.New("data.db") if err != nil { log.Fatal(err) } defer kv.Close() // 写入与读取 if err := kv.Set("name", []byte("sqlkv")); err != nil { log.Fatal(err) } val, err := kv.Get("name") if err != nil { log.Fatal(err) } fmt.Printf("name = %s\n", val) // name = sqlkv // 判断键是否存在 if kv.Exists("name") { fmt.Println("key 'name' 存在") } // 删除与计数 _ = kv.Del("name") cnt, _ := kv.Count() fmt.Printf("剩余键数: %d\n", cnt) } ``` ### 高级用法 **多逻辑库隔离** ```go // 切换 16 个逻辑库之一(0~15),各库数据完全隔离 _ = kv.Select(1) _ = kv.Set("k", []byte("db1")) _ = kv.Select(2) _ = kv.Set("k", []byte("db2")) _ = kv.Select(1) v, _ := kv.Get("k") // "db1" — 不互相干扰 ``` **分布式锁(SetNX)** ```go // 仅当键不存在时写入,成功返回 true —— 天然适合做分布式锁 locked, err := kv.SetNX("lock:order:1001", []byte("holder")) if err != nil { log.Fatal(err) } if locked { defer kv.Del("lock:order:1001") // 临界区逻辑... } ``` **批量读写(单事务)** ```go items := map[string][]byte{ "a": []byte("1"), "b": []byte("2"), "c": []byte("3"), } if err := kv.SetMany(items); err != nil { // 全部成功或全部回滚 log.Fatal(err) } got, _ := kv.GetMany("a", "b", "c", "missing") // 缺失的键不会出现在结果中 fmt.Println(string(got["b"])) // "2" ``` **结构化数据(JSON)** ```go type User struct { Name string `json:"name"` Age int `json:"age"` } _ = kv.SetJSON("user:1", User{Name: "张三", Age: 30}) var u User if err := kv.GetJSON("user:1", &u); err != nil { log.Fatal(err) } fmt.Printf("%s, %d 岁\n", u.Name, u.Age) ``` **遍历与迭代** ```go // 按键升序遍历当前库全部键值,回调返回错误即中止 _ = kv.ForEach(func(key string, value []byte) error { fmt.Printf("%s = %s\n", key, value) return nil }) // 列出全部键 keys, _ := kv.Keys() fmt.Println(keys) ``` **备份与迁移** ```go // 一致性快照备份(等效 sqlite3 .backup) _ = kv.Backup("backup.db") // 导出全部数据为 JSON,可导入任意新库 data, _ := kv.Dump() _ = data // []byte // 从 JSON 恢复(合并语义:覆盖已有键、保留无关键) _ = kv.Load(data) ``` --- ## 📚 API 文档概述 ### 基础操作 | 方法 | 签名 | 说明 | |------|------|------| | `New` | `New(path string) (*KVStore, error)` | 打开数据库,自动建表,默认 DB 0 | | `Close` | `Close() error` | 关闭预编译语句并关闭数据库 | | `Select` | `Select(db int) error` | 切换 DB(0~15),越界返回 `ErrInvalidDBIndex` | | `Set` | `Set(key string, value []byte) error` | 写入键值(UPSERT,已存在则覆盖) | | `Get` | `Get(key string) ([]byte, error)` | 读取键值,缺失返回 `ErrKeyNotFound` | | `Del` | `Del(key string) error` | 删除键(不存在不报错) | | `Exists` | `Exists(key string) bool` | 判断键是否存在 | | `Count` | `Count() (int, error)` | 当前 DB 键总数 | | `Keys` | `Keys() ([]string, error)` | 列出当前 DB 全部键(升序) | ### 批量与迭代 | 方法 | 签名 | 说明 | |------|------|------| | `SetMany` | `SetMany(items map[string][]byte) error` | 单事务批量写入,失败整体回滚 | | `GetMany` | `GetMany(keys ...string) (map[string][]byte, error)` | 批量读取,缺失键不出现在结果中 | | `SetNX` | `SetNX(key string, value []byte) (bool, error)` | 键不存在才写入(可用于分布式锁) | | `ForEach` | `ForEach(fn func(key, value []byte) error) error` | 升序遍历当前库,回调报错即中止 | ### 便捷方法 | 方法 | 签名 | 说明 | |------|------|------| | `SetString` | `SetString(key, value string) error` | 字符串形式写入 | | `GetString` | `GetString(key string) (string, error)` | 字符串形式读取 | | `SetJSON` | `SetJSON(key string, v any) error` | 序列化任意值为 JSON 后写入 | | `GetJSON` | `GetJSON(key string, out any) error` | 读取并反序列化 JSON(out 需为指针) | ### 运维管理 | 方法 | 签名 | 说明 | |------|------|------| | `FlushDB` | `FlushDB() error` | 清空当前 DB 全部键 | | `FlushAll` | `FlushAll() error` | 清空全部 16 个 DB | | `Dump` | `Dump() ([]byte, error)` | 导出全部数据为 JSON | | `DumpTo` | `DumpTo(w io.Writer) error` | 流式导出(内存占用恒定) | | `Load` | `Load(data []byte) error` | 从 JSON 导入(合并语义) | | `LoadFrom` | `LoadFrom(r io.Reader) error` | 流式导入 | | `Backup` | `Backup(path string) error` | 一致性快照备份 | | `Vacuum` | `Vacuum() error` | 压缩数据库,回收磁盘空间 | | `DBSize` | `DBSize() (int64, error)` | 当前 DB 键值总字节数 | ### 错误常量(sentinel error) | 错误 | 含义 | 使用方式 | |------|------|---------| | `ErrKeyNotFound` | 键不存在 | `errors.Is(err, kvstore.ErrKeyNotFound)` | | `ErrInvalidDBIndex` | Select 库编号越界 | 同上 | | `ErrInvalidDumpData` | 导入数据非合法 JSON 数组 | 同上 | | `ErrInvalidDumpDBIndex` | 导入数据中 db 越界 | 同上 | | `ErrEmptyKey` | 导入数据中包含空 key | 同上 | --- ## 🗂️ 支持的功能与格式 | 类别 | 支持内容 | |------|---------| | 📊 数据类型 | `[]byte` 二进制 / `string` / 任意结构体(经 JSON) | | 🗄️ 逻辑库 | 16 个(DB 0~15),`Select` 切换,数据完全隔离 | | 🔁 持久化 | SQLite 单文件,WAL 模式,崩溃恢复 | | ⚙️ 并发 | 多连接读写、事务、busy 等待(多进程) | | 📦 序列化格式 | Dump JSON 数组:`[{"db":0,"key":"...","value":"base64"}]` | | 🧵 存储引擎 | SQLite(modernc.org/sqlite v1.56+,纯 Go 无 CGO) | --- ## ⚙️ 配置选项 sqlkv 在打开数据库时自动应用合理的默认优化配置,无需额外设置即可获得良好性能: | 配置项 | 默认值 | 说明 | |--------|--------|------| | `journal_mode` | `WAL` | 写前日志模式,读写互不阻塞 | | `busy_timeout` | `5000ms` | 多进程/多连接写冲突时等待而非直接报错 | | `synchronous` | `NORMAL` | WAL 官方推荐组合,大幅提升写吞吐(崩溃最多丢最近几笔,不会损坏库) | | `cache_size` | `64MB` | SQLite 页缓存,减少高频读磁盘 I/O | | `mmap_size` | `256MB` | 数据库文件内存映射,降低读系统调用 | | `temp_store` | `MEMORY` | 排序等临时数据放内存 | | `MaxOpenConns` | `5` | 最大打开连接数(读并行 + 写串行) | | `MaxIdleConns` | `5` | 最大空闲连接数(复用,避免反复重建) | | `ConnMaxIdleTime` | `5min` | 空闲连接超时回收,释放文件句柄(Windows 友好) | > ⚠️ **关于 `synchronous=NORMAL`**:该设置牺牲"断电丢失最近几笔写入"换取显著写性能,但**绝不会损坏数据库**。若你的场景要求每笔写入必须可靠落盘,请在 `New` 的 DSN 中移除该 PRAGMA。 --- ## 📁 项目结构 ``` sqlkv/ ├── go.mod # 模块定义(gitee.com/MM-Q/sqlkv) ├── go.sum # 依赖校验 ├── LICENSE # MIT 许可证 ├── sqlkv.go # 核心结构:New / Close / Select / 预编译 / 连接池配置 ├── basic.go # 基础操作:Set / Get / Del / Keys / ForEach / 批量操作 ├── admin.go # 管理操作:Flush / Backup / Vacuum / Dump / Load / DBSize ├── convenience.go # 便捷方法:SetString / GetString / SetJSON / GetJSON ├── sqlkv_test.go # 核心结构测试(New / Select / 并发 / 库隔离) ├── basic_test.go # 基础操作测试 ├── admin_test.go # 管理操作测试 └── convenience_test.go # 便捷方法测试 ``` --- ## 🧪 测试说明 项目包含 **40+** 个测试用例,覆盖全部公开 API、边界条件与并发安全: ```bash # 运行全部测试(含 -race 数据竞争检测,推荐) go test -race -count=1 ./... # 运行全部测试(详细输出) go test -v ./... # 静态检查 go vet ./... golangci-lint run ./... ``` 覆盖范围:基础读写、覆盖写、缺失键错误语义、`Set(nil)` 边界、库间数据隔离、并发读写(`-race`)、批量操作、JSON 序列化往返、导入格式校验(非法输入零写入)、备份恢复、Dump/Load 往返等。 --- ## 🤝 贡献指南 欢迎贡献!请遵循以下流程: 1. **Fork** 本仓库并克隆到本地 2. 创建特性分支:`git checkout -b feature/your-feature` 3. 编写代码并**补充相应测试**(`*_test.go`) 4. 确保通过:`go vet ./... && go test -race ./...` 5. 提交并推送:`git push origin feature/your-feature` 6. 发起 **Pull Request**(请清晰描述改动内容与动机) **开发约定** - 保持零 CGO 与零额外依赖(仅标准库 + modernc.org/sqlite) - 所有导出的函数/方法需添加中文函数级注释 - 新 API 必须配套测试用例 - 保持 Redis 风格 API 的一致性 --- ## 📄 许可证 本项目基于 **MIT License** 开源,Copyright © 2026 M乔木。 你可以自由地使用、复制、修改、合并、发布、分发、再许可及销售本软件的副本,前提是保留原始版权声明。详见 [LICENSE](./LICENSE)。 --- ## 📫 联系方式与相关链接 | 资源 | 链接 | |------|------| | 📦 项目仓库 | [https://gitee.com/MM-Q/sqlkv](https://gitee.com/MM-Q/sqlkv) | | 🔗 Git 克隆 | `git clone https://gitee.com/MM-Q/sqlkv.git` | | ⬇️ Go 安装 | `go get gitee.com/MM-Q/sqlkv` | | 🧱 底层驱动 | [modernc.org/sqlite](https://gitlab.com/cznic/sqlite)(纯 Go SQLite 驱动) | | 🗄️ 数据库 | [SQLite 官网](https://www.sqlite.org/) | ---
**如果这个项目对你有帮助,欢迎 ⭐ Star 支持!** [仓库地址:https://gitee.com/MM-Q/sqlkv](https://gitee.com/MM-Q/sqlkv)