针对hashmap vs String键的Redis内存优化

时间:2017-04-27 11:29:34

标签: java data-structures redis memory-optimization

我一直在尝试在两种情况下评估redis的内存大小。

情境-1:

    String commonString = "Test";
    long commonId = 1234567890L;
    int size = 0;
    for(int i = 1; i <= 100; i++)
    {
        jedis.set((commonString+"_"+commonId+"_KEY_"+i).getBytes(),("Value_"+i).getBytes());
        DebugParams debugParams = DebugParams.OBJECT(commonString+"_"+commonId+"_KEY_"+i);
        size += Integer.parseInt(debugged.split(":")[4].split(" ")[0]);
    }

在这种情况下,大小为892字节

情境-2:

    String commonString = "Test";
    long commonId = 1234567890L;
    int size = 0;
    for(int i = 1; i <= 100; i++)
    {
        jedis.hset((commonString+"_"+commonId).getBytes(),SafeEncoder.encode("KEY_"+i),("Value_"+i).getBytes());
    }
    DebugParams debugParams = DebugParams.OBJECT(commonString+"_"+commonId);
    String debugged = jedis.debug(debugParams);
    size = Integer.parseInt(debugged.split(":")[4].split(" ")[0]);

在这种情况下,需要925个字节。

  

自Redis 2.2以来,许多数据类型都经过优化,可以使用更少的空间到一定的大小。散列,列表,仅由整数组成的集合,以及排序集,当小于给定数量的元素时,以及最大元素大小,以非常高效的内存方式进行编码,使用的内存最多可减少10倍(5时间更少的内存使用是平均节省。)

我已经尝试过这种优化,但我还没有实现它。配置是默认配置。可能出了什么问题?

被修改

方案-1

    String commonString = "Test";
    long commonId = 1234567890L;
    jedis.flushAll();
    String info1 = jedis.info();
    for(int i = 1; i <= 75; i++)
    {
        jedis.set(commonString+"_"+commonId+"_KEY_"+i, "VALUE_"+i);
    }
    String info2 = jedis.info();

在场景-1中,在info1中使用的内存是&#34; used_memory:844640&#34;在info2中使用的内存是&#34; used_memory:852176&#34;。因此,info2和info1之间的差异是7536字节。

方案-2

    String commonString = "Test";
    long commonId = 1234567890L;
    jedis.flushAll();
    String info1 = jedis.info();
    for(int i = 1; i <= 75; i++)
    {
        jedis.hset(commonString+"_"+commonId,"KEY_"+i,"VALUE_"+i);
    }
    String info2 = jedis.info();

在场景-2中,在info1中使用的内存是&#34; used_memory:845576&#34;在info2中使用的内存是&#34; used_memory:847208&#34;。因此,info2和info1之间的差异是1632字节。

我的评估是否正确?

1 个答案:

答案 0 :(得分:1)

如果您参考有关DEBUG OBJECT的文档,您将了解到:

  

DEBUG OBJECT是一个不应被客户端使用的调试命令。改为检查OBJECT命令。

换句话说,无论你从DebugParams.OBJECT取回什么,最有可能几乎与你想要达到的目标完全无关。

好消息是Redis v4引入了新的MEMORY(Doctor)命令。以下摘自@antirez's 'The first release candidate of Redis 4.0 is out'

  

6。新的MEMORY命令。

     

我喜欢它,就像我喜欢的LATENCY DOCTOR一样,在邮件列表中减少了“My Redis很慢”的百分比抱怨   一小部分。现在我们也有内存问题。

127.0.0.1:6379> MEMORY DOCTOR
Hi Sam, this instance is empty or is using very little memory, my issues detector can't be used in these conditions. Please, leave for
     

你在地球上的任务,并填写一些数据。新的山姆和我   我会在完成重启后立即回到我们的编程。

     

电影版权所有者可能会因为接受科幻对话的灵感而起诉我,但这很好。我将会为我带来橘子   在监狱里。

     

MEMORY做的远不止这些。

127.0.0.1:6379> MEMORY HELP
1) "MEMORY USAGE <key> [SAMPLES <count>] - Estimate memory usage of key"
2) "MEMORY STATS                         - Show memory usage details"
3) "MEMORY PURGE                         - Ask the allocator to release memory"
4) "MEMORY MALLOC-STATS                  - Show allocator internal stats"
     

USAGE子命令的内存使用情况报告非常有用,但也是“STATS”提供的深入信息。

     

目前所有这些都没有记录,所以要好好搞清楚它的作用。