SSDB 目前已经进展到 1.3.x 版本, 在使用过程中, 程序一直非常稳定, 内存占用也很合理, 即使在一个40G数据在应用中, 内存占用也稳定在1G左右.
最近, SSDB 被应用到了一个极端的环境, 这是一个图片相关的应用, 给 SSDB 造成的压力就是:
- 单条数据较大. 一般的应用也就几K级别的单条数据, 但图片处理一般在1M级别
- 并发数较多, 达20K+
这给 SSDB 和操作系统都带来了明显的压力:
- 整个系统的磁盘 IO write 达 400MB/s, 达到硬盘的极限
- SSDB 内存占用达 30G
第一条只能通过未来升级为 SSD 硬盘来改善, 但第二条存在问题. 根据设计, SSDB 不应该使用如此多的内存.
首先, 我尝试调整 LevelDB 的参数, 发现 LevelDB 没有问题.
接着, 检查 SSDB 是否存在内存泄露的问题. 在代码层面, SSDB 的内存使用非常简单, 不太容易可能内存泄露. 用 valgrind 检查也证明这一点, SSDB 没有内存泄露.
后来, 通过调整 SSDB 的接收和发送缓冲区的内存分配机制, 预先分配大内存, 避免多次调用 realloc(). 这个改动有一定效果, 但并发增多后, 还是出现内存不释放的问题.
最后, 怀疑是 glibc 的 malloc/free 没有真正地释放内存给操作系统. 查了一些资料, 发现 glibc 可能存在某种机制, 不将内存还给操作系统, 但我写了一些简单的程序, 并没有触发这个机制. 可能在比较复杂的情况才能触发这个机制. 考虑到 Redis 等软件都使用 jemalloc, tcmalloc 等, 所以, SSDB 换成 jemalloc 测试, 发现问题解决了, 内存得到真正释放, 内存占用从 30G 降到 2G 以内.
jemalloc 是 Facebook 使用的一个内存分配库, 也是 FreeBSD 系统的默认内存分配库, 另外还有 Google 使用 tcmalloc 可供选择.
SSDB 开源项目: https://github.com/ideawu/ssdb