我在redis数据库中存储~300M对象。该对象包括:
我使用ID /日期作为键,我正在寻找存储48个值的最佳方式(内存使用)。
值为整数,通常介于[1-1000]之间。
我使用的第一种方法是在Java中使用对象构建并使用自动序列化对象的框架(spring-data-redis)。
结果格式如下:
{\ “@类\”:\ “com.mycompany.Points \”,\ “faceId \”:1234,\ “日期\”:[\ “java.util.Date \”,1509663600000],\ “点\”:5,5,10,10,10,10,60,60,60,60,60,60,40,40,40,40,40,40,30,30,30,30, 30,80,80,80,80,80,80,80,20,20,20,20,20,10,10,10,10,10,5,5,5,5,5,5,5, 5]}
然后我使用此命令在redis中跟踪此对象的大小:
redis 127.0.0.1:6379> DEBUG OBJECT POINTS_215004#03-11-2017
Value at:0x7fce4b2b6ac0 refcount:1 encoding:raw serializedlength:206 lru:2074768 lru_seconds_idle:10
因此,如果我正确阅读,该条目在数据库中需要 206 (206 what?)。
我尝试将其存储为列表:
redis 127.0.0.1:6379> lpush dummy 1 2 3 4 5 [...] 48
(integer) 48
实际上,尺寸几乎相同:
redis 127.0.0.1:6379> DEBUG OBJECT dummy
Value at:0x7fce467c2800 refcount:1 encoding:ziplist serializedlength:205 lru:2074809 lru_seconds_idle:10
类型ziplist
可能更耗费内存。
然后我尝试将其存储为普通字符串:
redis 127.0.0.1:6379> set dummy [5,5,10,10,10,10,60,60,60,60,60,60,40,40,40,40,40,40,30,30,30,30,30,80,80,80,80,80,80,80,20,20,20,20,20,10,10,10,10,10,5,5,5,5,5,5,5,5]
尺寸减少到 53 :
redis 127.0.0.1:6379> debug object dummy
Value at:0x7fce470b2dc0 refcount:1 encoding:raw serializedlength:53 lru:2074818 lru_seconds_idle:10
有一种更适合存储此阵列的方法吗?
答案 0 :(得分:12)
有一种更适合存储此阵列的方法吗?
这取决于你的Redis版本,但是从v3.2开始就有令人难以置信的BITFIELD
,如果你将它用于无符号的10位字段(最接近2的幂),这就是你的选择。 1000)。
注意: DEBUG OBJECT
的输出不是衡量Redis中密钥内存消耗的可靠方法 - serializedlength
字段以字节为单位给出,以保持持久性对象,而不是内存中包含各种管理开销的实际占用空间。从v4开始,我们使用MEMORY USAGE
命令做得更好 - 请参阅https://github.com/antirez/redis-doc/pull/851了解详细信息。
$ for i in {0..47}; do redis-cli BITFIELD dummy SET u10 \#$i $i; done
...
$ redis-cli
127.0.0.1:6379> strlen dummy
(integer) 60
127.0.0.1:6379> DEBUG OBJECT dummy
Value at:0x7f83e040e430 refcount:1 encoding:raw serializedlength:61 lru:16563203 lru_seconds_idle:27
127.0.0.1:6379> MEMORY USAGE dummy
(integer) 117
对于早期版本的Redis,您可以探索使用Lua脚本并编写基于脚本的相同逻辑变体和/或尝试使用数组的MessagePack编码。