Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/iamlongalong/diskv
easy disk kv store using text
https://github.com/iamlongalong/diskv
Last synced: 8 days ago
JSON representation
easy disk kv store using text
- Host: GitHub
- URL: https://github.com/iamlongalong/diskv
- Owner: iamlongalong
- Created: 2024-10-18T08:59:02.000Z (2 months ago)
- Default Branch: main
- Last Pushed: 2024-11-03T07:48:36.000Z (about 2 months ago)
- Last Synced: 2024-11-03T09:15:15.227Z (about 2 months ago)
- Language: Go
- Size: 177 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# diskv
一般我们要使用 kv 存储时,多用 redis、rocksdb、leveldb 等等,这些存储各有优势,能满足绝大多数的需求。
但这些存储系统有有一个特点: 底层都是基于二进制存储,需要专门的工具才能查看相关数据。
这一操作核心是提升读写的性能,和压缩存储大小。但有些时候,我们希望用更简单的方式去存储数据,简单到我们肉眼就能读懂的程度。
当我们对 "数据丢失" 和 "数据恢复" 操作不熟练时,心中难免多有不安。于是,我希望实现一个极简的 kv 存储系统,满足两个基本理念:
- 以明文方式存储数据,让数据可读性高
- 极力减小对内存的占用,所有操作,尽量都通过直接操作文件系统完成
- 极力减少外部依赖 (当前无外部依赖库)从文件存储上看,如下:
## 快速上手
### 创建一个 db
```go
db, err := diskv.CreateDB(ctx, &diskv.CreateConfig{
Dir: "/tmp/diskv",
KeysLen: 100, // 预分配的 key 的数量
MaxLen: 64, // idx 块的最大长度
})
```### 数据操作
```go
// 存储
err = db.Set(ctx, key, bytesValue)
err = db.SetString(ctx, key, stringValue)// 读取
bytesValue, err := db.Get(ctx, key)
stringValue, err := db.GetString(ctx, key)// 删除
ok, err := db.Delete(ctx, key)// 检查是否存在
has, err := db.Has(ctx, key)// 遍历
err = db.ForEach(ctx, func(key string, value []byte) bool {
return true // 继续遍历
})```
### 文件迁移
由于 key 的空间大小是预分配的,若 key 的数量逐渐增加,达到预分配大小的 75% 以上时(负载 75%),性能就会受到影响。
实测的 benchmark 测试表明,50% 负载时为 10w QPS, 80% 负载时为 9.2w QPS, 当负载达到 100% 时,性能从原 10w QPS 降低到了 2.1w QPS,详见 [benchmark](./benchmark.txt) 文件。```go
db, err := diskv.CreateDB(ctx, &diskv.CreateConfig{
Dir: "/tmp/diskv",
MaxLen: 64,
KeysLen: 1000, // 预分配的 key 的数量
})// 主动迁移
err := db.MigrateIdx(ctx, &diskv.CreateConfig{
MaxLen: 64,
KeysLen: 5000, // 预分配的 key 的数量
})```
当前的 DB 文件,是以 log 的模式增量写入的,idx 只记录最后一次 key 的位置,因此,当修改、删除等操作频繁发生时,log 文件就会持续增长。可通过 `db.MigrateValue()` 进行主动迁移,这个操作会根据 idx 记录的所有 key 信息,把有效的 value 移动到新的 db 文件中,并删除旧的 db 文件。
```go
err := db.MigrateValue(ctx)
```上述的迁移都是阻塞进行的,迁移过程中无法读写数据。
迁移后的文件名不会变动,老的文件会以 `*._bak` 的后缀名保存最近一次的迁移文件。## 带类型存储
详情见 [gkv](./gkv/README.md) 目录.
## TODO
- [x] 支持 idx 文件迁移
- [x] 支持 db 文件压缩 + 迁移
- [x] 支持存储特定结构体的接口