Max*_*ysh 1 python memory go redis redigo
我正在使用Go和Redis开发API.问题是RAM的使用不足,我找不到问题的根源.
TL; DR版本
有数百/数千个哈希对象.1 KB对象(键+值)中的每一个都需要大约0.5 MB的RAM.但是,没有内存碎片(INFO没有显示).
此外,dump.rdb比RAM设置小70倍(对于50个对象,360KB dump.rdb对25MB RAM,对于5000对象为35.5MB对2.47GB).
长版
Redis实例主要填充task:123以下类型的哈希:
    "task_id"       : int
    "client_id"     : int
    "worker_id"     : int
    "text"          : string (0..255 chars)
    "is_processed"  : boolean
    "timestamp"     : int
    "image"         : byte array (1 kbyte) 
此外,还有一些整数计数器,一个列表和一个有序集(都由task_id组成).
RAM使用率与任务对象数量呈线性关系.
50个任务的INFO输出:
# Memory
used_memory:27405872
used_memory_human:26.14M
used_memory_rss:45215744
used_memory_peak:31541400
used_memory_peak_human:30.08M
used_memory_lua:35840
mem_fragmentation_ratio:1.65
mem_allocator:jemalloc-3.6.0
和5000个任务:
# Memory
used_memory:2647515776
used_memory_human:2.47G
used_memory_rss:3379187712
used_memory_peak:2651672840
used_memory_peak_human:2.47G
used_memory_lua:35840
mem_fragmentation_ratio:1.28
mem_allocator:jemalloc-3.6.0
dump.rdb50个任务的大小为360kB,5000个任务的大小为35553kB.
每个任务对象的序列化长度约为7KB:
127.0.0.1:6379> DEBUG OBJECT task:2000
Value at:0x7fcb403f5880 refcount:1 encoding:hashtable serializedlength:7096 lru:6497592 lru_seconds_idle:180
我写了一个Python脚本试图重现问题:
import redis
import time
import os 
from random import randint
img_size = 1024 * 1 # 1 kb
r = redis.StrictRedis(host='localhost', port=6379, db=0)
for i in range(0, 5000):
    values = { 
        "task_id"   : randint(0, 65536),
        "client_id" : randint(0, 65536),
        "worker_id" : randint(0, 65536),
        "text"      : "",
        "is_processed" : False,
        "timestamp" : int(time.time()),
        "image"     : bytearray(os.urandom(img_size)),
    }
    key = "task:" + str(i)
    r.hmset(key, values)
    if i % 500 == 0: print(i)
它只消耗80MB的RAM!
我很感激有关如何弄清楚发生了什么的任何想法.
你有很多很小的HASH对象,这很好.但是每个都在redis内存中有很多开销,因为它有一个单独的字典.这有一个很小的优化,通常可以显着改善事物,并且保持内存中的哈希优化,但数据结构稍慢,在这些对象大小应该不重要.从配置:
# Hashes are encoded using a memory efficient data structure when they have a
# small number of entries, and the biggest entry does not exceed a given
# threshold. These thresholds can be configured using the following directives. 
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
现在,您有大的值会导致此优化不起作用.我设置hash-max-ziplist-value为几kbs(取决于你的最大对象的大小),它应该改善这一点(你不应该看到这个HASH大小的任何性能下降).
另外,请记住,redis压缩其RDB文件相对于内存中的内容,因此无论如何都要比内存减少约50%.
[编辑]重新阅读你的问题并看到它只是一个问题,并考虑到压缩的rdb很小的事实,有些东西告诉我你写的尺寸大于你对图像的期望.你有没有机会把它写成[]byte片?如果是这样,也许你没有修剪它,你正在写一个更大的缓冲区或类似的东西?我已经和redigo一起工作了很多次,从未见过你所描述的.