现在系统的这个数据库设计,是不是有4k浪费问题?
← 返回列表

当前位置: 作者:kanshan · 2026-05-18 04:56:18

#1 kanshan · 2026-05-18 04:56:18
stalltrix
看了下数据的存储空间,竟然超过1M了。但是感觉现在的人不是很多,帖子也不是很多,为什么会超过1M呢。

ls -la看了下,所有的小于4k的帖子全部占用都是4k。查了下好像是ext4文件系统的4k对齐导致的浪费问题。即使一条回复只有几个字,也会占用4k

这种应该需要解决下,使用KV方式是最简单补丁方法
#2 skymmap · 2026-05-18 07:10:43
stalltrix
以前也讨论过4k问题,但发现如果软件层面存储为一个整块大文件,软件就需要用户态实现复杂的管理逻辑。

并且当初设计为文件部分损坏也可以跳过并启动。因此就要设计文件损坏导致偏移损坏怎么处理以及跳过损坏块的问题,复杂度太高,暂时搁置了。

后来为了简化实现,直接存硬盘目录KV+索引,用内核现成的队列调度。

其实所有小文件的系统都有这个问题。因为Linux的默认页对齐就是4k。




解决小文件系统,可以挂着一个ReiserFS 的存储块,让ReiserFS 内核模块管理文件偏移。对外也是一个整块大文件块。

简单说一下:

```bash
truncate -s 16G /mnt/reiserfs.img
mkfs.reiserfs /mnt/reiserfs.img

mkdir /mnt/reiserfs
mount -o loop -t reiserfs /mnt/reiserfs.img /mnt/reiserfs
```

这种对外就是16G的整块存储,暂时能解决4k浪费问题。

mkfs.reiserfs不存在的话,可使用apt install reiserfsprogs
#3 BitForge · 2026-05-18 07:34:35
stalltrix
ReiserFS 不是 Linux 6.13 后就被移除了吗
#4 星河 · 2026-05-18 07:41:09
stalltrix
linux的ext4文件系统,可以把默认的块大小,从4k调整为1k。这样每个帖子只占用1k。

建立一个raw.img文件块,格式化为ext4 1k-block,使用loop挂载为出来,专门给kep-data/0-n这种细碎文件使用。`mkfs.ext4 -b 1024`就行
#5 skymmap · 2026-05-18 23:51:01
stalltrix
@星河 ext4系统调小block大小也可以。

不过ext4注意一下inode 耗尽问题。每个文件都必须占用 1 个 inode放元数据。ext4的 inode 在格式化时就分配好的,固定的。

其实是初始化时候,通过参数 mkfs.ext4 -i 4096 格式化时生成的。可以提前调整大一点
#6 skymmap · 2026-05-19 00:08:30
stalltrix
@BitForge 文件格式系统,这个可以自行解决。选其他文件格式也行。这种细碎文件的4k问题,不只是kep-data存在,很多直接使用文件存数据而不是sql存数据的系统都存在。


kep-data其实是写多读少的,webui读取后,会存入内存与redis,这种没有4k问题。写入是edge程序负责的,几乎是并发写入的。硬盘文件是存档设计,单文件避免多文件聚合损坏后导致数据全丢问题。

不过项目本身也是完全开源的,可以自己diy一个自己喜欢的存储实现。


#7 hua · 2026-05-19 01:07:53
stalltrix
我建议还是设计一款新的存储系统,不需要维持复杂结构,只需要维持偏移的起始与结束就行了。

看了下站长的描述,以及我自己读了一下代码的理解。kep-data写多读少,写入后的文件几乎不会修改。可以设计为append方案

我是写java,对go不太熟悉,不方便直接写出这个实现,简单说下我的思路

现阶段,文件写入似乎是一个程序实现的,因此可以使用操作系统的内部append调用,实现顺序写入实现。

现阶段,目录结构应该是这种

```
home/
└── kep/
└── kep-data
├── 0
├── 1
└── 2
```

现阶段存储是这种的

```
kep/
└── kep-data/
└── 0
├── hash1.mdb
├── hash2.mdb
└── hash3.mdb
```

每个mdb就是一个单帖子/回复文件

mdb并不是巨硬家格式,我猜测一个mini-db之类的意思?




其实可以存储为这种,分为两个文件,元数据与索引

cdb,聚合文件



```
kep/
└── kep-data/
└── 0
├── metadata.cdb
└── metadata.idx
```

metadata.cdb存放元数据



```
| hash1.mdb | hash2.mdb | hash3.mdb |
| [0-54) | [54-123) | [123-198)|
```

这种把大量细碎mdb,存放到一个一个聚合文件中

然后索引存储偏移格式



索引为了简单,直接txt格式

内部txt就这种
```txt
hash1 0-54
hash2 54-123
hash2 123-198
```

人类可读,机器可直接append顺序写入。并且机器读取解析也并不复杂



强烈建议设计新数据存储系统,站长给出的解决方案,实际上是偷懒方法,严重依赖内核特性,不利于跨平台以及小设备轻量部署。


#8 duso · 2026-05-19 01:19:11
stalltrix
好好好,站长应该是go大佬,java大佬快和go大佬打起来。我要看血流成河。
#9 星河 · 2026-05-19 01:30:01
stalltrix

> "依赖内核特性,是偷懒方案"其实应该不是。

依赖成熟文件系统是工程上最常见的做法。结构简单清晰,责任逻辑明确,unix哲学就是这种。最多就是小文件效率差,很多系统也顶着4k问题继续用,也是这个原因。

此外cdb解决方法,如果只写入不修改/删除,应该没有问题。如果修改/删除,那么偏移大概会变,必须重建整个cdb文件。数据量一大,重建与回收空间非常麻烦,造成的问题可能比4k问题还要严重。
#10 kanshan · 2026-05-19 03:12:52
stalltrix
感谢大佬的讨论与建议。

看了下大概两种方案,1.文件系统解决,2.应用层解决

我觉得如果真的以文件系统解决解决的话,可以先用fuse试试水。

不过来说我更倾向于KV解决方法,但是应用层自己管理空间与回收确实麻烦,不过可以采用现成数据库或者KV组件解决。
#11 skymmap · 2026-05-19 12:53:23
stalltrix
之前建议使用reiserfs确实有点不妥,现在现在人少帖子少,过早优化也许不必要?。等帖子突破10k大关了。肯定会优化的,不是我优化就是有大佬站出来优化。
#12 LoopLab · 2026-05-28 15:42:58
stalltrix
小白的建议,不是很懂这个领域哈。

> 听说F2FS文件系统可以直接把小于3K的数据直接存到inode的inline data,这样不用单独占用一个额外的4k block存放数据了。

不知道这种是否可行
#13 pbox · 2026-06-09 13:26:46
stalltrix
最近忙里偷闲有空在写一个kep-worker,我也是使用的KV模式而不是SQL模式。

我感觉没有topic的话,reply没有意义,于是把reply直接数据复写到topic后面。

这个实现有个小问题:删除topic会损坏reply。但是感觉问题不大。

没有按单KV实现,使用了topic为单独一个聚合对象,与官方每个msg都是单独KV的实现不一样。

等之后搞完后放出来给大家看看,看看这种设计如何。

注册

或使用第三方注册

登录

没有账号? 立即注册
技术
闲聊
开发
正在提交...