redis 中有 4 亿条记录会占多少内存?

2017-04-26 19:10:15 +08:00
 bccber
key:md5 16 字节
value: int64 8 字节
考虑到 redis 内部可能用到链表 多加一个 next 4 字节
占用内存 400000000 * 28 /1073741824 GB

实际上,我公司这个 redis 已经占到 40GB 的内存了
7929 次点击
所在节点    程序员
13 条回复
cheetah
2017-04-26 19:17:34 +08:00
so?
zts1993
2017-04-26 19:40:27 +08:00
key:md5 16 字节 这个不对。
value: int64 8 字节 这个也不对
链表 这个也不对。。

整个估算都不太对。。。。
如果有疑问看一下 info 里面的内存碎片率:)
Ouyangan
2017-04-26 20:33:27 +08:00
这是在当数据库在跑啊
sagaxu
2017-04-26 20:45:40 +08:00
### What's the Redis memory footprint?
To give you a few examples (all obtained using 64-bit instances):
* An empty instance uses ~ 1MB of memory.
* 1 Million small Keys -> String Value pairs use ~ 100MB of memory.
* 1 Million Keys -> Hash value, representing an object with 5 fields, use ~ 200 MB of memory.

4 亿约等于 0.4G ,按照 100 字节一条, 100*0.4 刚好是 40G ,官方 Faq 还是蛮准的
bccber
2017-04-26 21:05:48 +08:00
@sagaxu 问题是我的内容没有 100 字节啊
额外的字节占这么多啊?
sagaxu
2017-04-26 21:35:03 +08:00
@bccber
MD5 是 16 字节,但是你序列化成了 ASCII 字符是 32 个字符,就是 32 字节了,
Value 不可能只存 Value 本身,至少还要存类型和长度, 64 位机器,指针是 8 字节。
Redis 还有超时机制需要额外的字节数,分配内存时也往往会对齐到 64 字节或者 128 字节等等。
数据结构如 hash 本身也有一定的闲置浪费,再算上内存碎片产生的浪费, 100 字节一点儿都不算多。
v2orz
2017-04-26 21:36:14 +08:00
key value 不是只存你的数据就完了,还有些为了性能上优化而设置的字段
如果是简单字符串结构,当字符数组存的数据从一个较长的串被修改为较小的串的时候,不是马上就回收空间的
同样是哈希对象,存的时候看你使用情景,没准还有用 ziplist 实现的,这还省了一部分内存
xmbaozi
2017-04-27 00:30:18 +08:00
xiezefan
2017-04-27 11:09:17 +08:00
你可以尝试一些 Redis 内存压缩,Google Keyword:Redis 内存压缩 Redis Ziplist

关于内存预估,你可以本地存 100W 数据,然后横向对比 4Y 数据,就可以估算大概的内存消耗了。
内存消耗不好直接给出的原因在于,单位数据使用的内存,与你当前 Redis 版本有关(他们使用了不同的内存分配器)。

一般来讲,用 ZipList,只要方案合理,能节省 70%左右的内存。
fancy20
2017-04-27 13:54:25 +08:00
我们的 redis 存的 kv 都比较长,几千万的时候占到 20+G 了,于是换成了 ssdb,感觉仅 kv 的话还不错,原先数据全放进去跑只几百兆内存(可以根据情况配置),性能下降的也不是很多
stackpop
2017-04-27 15:59:20 +08:00
use hash + ziplist to reduce memory cost
soulmine
2017-04-27 17:31:51 +08:00
1 到 1 亿的 crc32 彩虹表 10 个 G
luw2007
2017-05-02 13:30:41 +08:00
存储思路:
使用 hash 存储,将 16 位 md5 分割成 2 部分,一部分做 hash 的 key,一部分总 hash 的 field。
由此可以节省大量内存

伪代码:
keys = [md5(str(i)).digest() for i in range(100000000)]
for i, key in enumerate(keys):
r.hset(key[:3], key[3:], i)

结果:
hash 存储 1 亿 md5 占用 3.43G,4 亿 预计不到 14G

127.0.0.1:6379>info
used_memory:3680560224
used_memory_human:3.43G
...
db0:keys=16733694,expires=0,avg_ttl=0

127.0.0.1:6379> hgetall "\xcd\x05b"
1) "\x0e\x1e\xef\xde\x93\xa7\xbd\x19\x1bd=\xcb\xd8"
2) "7098931"
3) "\xd2\xb6B^\xebs\xba\xdcb\x17\xa6\xe0\xec"
4) "9063155"
5) "R\xd0\xb1R\xe2\t\x0f}\x8b^\xfb\x82C"
6) "47193476"
7) "\xf4\xcb\xd1_/\x89\xb9\xc4\xc2\xe0mF\xf5"
8) "70502533"
9) "Wd4\xee\xf0\xbc\xec\xa6\xfb\x01\rD5"
10) "83701386"

缺陷:
hash 做 key 选取的长度一旦固定,无法控制 hash 的 field 个数。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/357551

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2017 V2EX