哈希映射与字符串键的 Redis 内存优化

Redis memory optimization for hashmap vs String keys

我一直在尝试在两种情况下评估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 个字节。

Since Redis 2.2 many data types are optimized to use less space up to a certain size. Hashes, Lists, Sets composed of just integers, and Sorted Sets, when smaller than a given number of elements, and up to a maximum element size, are encoded in a very memory efficient way that uses up to 10 times less memory (with 5 time less memory used being the average saving).

这个优化我试过了,但是没实现。配置为默认配置。可能出了什么问题?

已编辑

场景一

    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();

场景一中,info1中使用的内存为“used_memory:844640”,info2中使用的内存为“used_memory:852176”。所以,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中使用的内存为“used_memory:845576”,info2中使用的内存为“used_memory:847208”。所以,info2 和 info1 之间的差异是 1632 字节。

我评价对了吗?

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

DEBUG OBJECT is a debugging command that should not be used by clients. Check the OBJECT command instead.

换句话说,无论你从 DebugParams.OBJECT 得到什么,即使不是完全不相关,也很可能与你想要实现的目标无关。

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

6. The new MEMORY command.

I love it, as much as I loved LATENCY DOCTOR that once introduced cut the percentage of “My Redis is slow” complains in the mailing list to a minor fraction. Now we have it for the memory issues as well.

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

your mission on Earth and fill it with some data. The new Sam and I will be back to our programming as soon as I finished rebooting.

Movie rights owners will probably sue me for taking inspirations of sci-fi dialogues but that’s fine. Bring oranges for me when I’ll be in jail.

MEMORY does a lot more than that.

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"

The memory usage reporting of the USAGE subcommand is going to be very useful, but also the in depth informations provided by “STATS”.

For now all this is totally not documented, so have fun figuring out what the heck it does.