Redis估算内存占用

半兽人 发表于: 2016-07-13   最后更新时间: 2019-10-26 16:45:16  
{{totalSubscript}} 订阅, 8,031 游览

环境

  • redis版本
    redis_version:2.4.4
  • 操作系统(uname -a)
    Linux CentOS 2.6.32-220.13.1.el6.x86_64 #1 SMP Tue Apr 17 23:56:34 BST 2012 x86_64 x86_64 x86_64 GNU/Linux
  • python版本(python –version)
    Python 2.6.6

Strings

测试脚本

#!/bin/env python

import redis
import uuid
import time

r = redis.Redis(host='localhost', port=6379, db=0)
for num_strings in (100000,):
    r.flushall()
    time.sleep(1.0)
    initial_size = r.dbsize()
    initial_info = r.info()

    for i in xrange(0, num_strings):
        r.set(str(uuid.uuid4()), time.time())
        #r.setex(str(uuid.uuid4()), time.time(), 100000)
    final_size = r.dbsize()
    final_info = r.info()

    print "For %s strings." % (num_strings,)
    print "Keys: %s => %s" % (initial_size, final_size)
    print "Memory: %s => %s" % (initial_info['used_memory'],
                                    final_info['used_memory'])
    print "Memory per key: %d"%((int(final_info['used_memory']) - int(initial_info['used_memory'])) / num_strings)
测试结果
  • set
    每个key-value占用138字节,可见redis本身的维护开销为89字节
  • setex
    每个key-value占用180字节,可见redis本身的维护开销为131字节,启用过期时间需要42字节开销(这是因为redis使用新的链表保存设置了过期时间的条目)。

Sets

测试脚本

#!/bin/env python

import redis
import math
import time

r = redis.Redis(host='localhost', port=6379, db=0)
set_capcity = int(r.config_get("set-max-intset-entries")["set-max-intset-entries"])

def set_name(i, num_strings, set_capcity):
    set_num = math.ceil(num_strings/float(set_capcity))
    return "s%d"%(i%set_num)

for num_strings in (100000,):
    r.flushall()
    time.sleep(1.0)
    initial_size = r.dbsize()
    initial_info = r.info()

    for i in xrange(0, num_strings):
        #r.sadd("s", str(i))
        r.sadd(set_name(i, num_strings, set_capcity), str(i))
    final_size = r.dbsize()
    final_info = r.info()

    print "For %s strings." % (num_strings,)
    print "Keys: %s => %s" % (initial_size, final_size)
    print "Memory: %s => %s" % (initial_info['used_memory'],
                                    final_info['used_memory'])
    print "Memory per key: %d"%((int(final_info['used_memory']) - int(initial_info['used_memory'])) / num_strings)
测试结果
  • 启用压缩
    每个value占用4字节
  • 不启用压缩
    每个value占用39字节

注意: redis的set仅当值为整型,压缩才会生效。

内存预留

除非你能够保证你的机器总是有一半的空闲内存,否则别使用快照方式持久化数据或者通过执行BGREWRITEAOF压缩aof文件。 redis在执行bgsave时,会进行一次fork,fork后的进程负责将内存中的数据写入磁盘,由于fork采用Copy-On-Write,两个redis进程共享内存中的数据。redis如果有数据更新,则会将对应的共享内存页创建一份副本再更新,当更新操作足够频繁时,共享的内存空间会迅速地副本化,导致物理内存被耗光,系统被迫动用交换空间,从而导致redis服务极不稳定,整个系统堵塞在磁盘io上。

参考:https://lethain.com/notes-on-redis-memory-usage/

更新于 2019-10-26

查看redis更多相关的文章或提一个关于redis的问题,也可以与我们一起分享文章