memory - 理解 hash 实现及其在 Redis 中的内存

标签 memory hash redis hashmap

从文档中我们知道 Redis 会对一定范围内的数据进行压缩(默认为 512)。如果哈希范围超过 512,那么内存差异将是 10 倍。

我对从 1 到 512 的哈希值做了一个小实验,发现了一些有趣的模式。

此图表示 1000 个哈希所占用的内存(以 KB 为单位),每个哈希包含从 1 到 512 不等的条目。

enter image description here

正如您在此图中所见。在一定的时间间隔内存中有陡峭的。我知道 redis 中的哈希实现也遵循一些逻辑,当它达到一定范围时扩展大小,而不是为每个新条目增加它。从数字来看,它并没有始终遵循加倍模式,但从 215 到 216 它确实加倍了,从 4 MB 到 8 MB。从 420 到 421,它几乎增加了一半 8 MB 到 12 MB。在 215 以内的陡坡中,我看不到它在 1/4、1/5 和 1/6 之间变化的任何模式。

根据我的观察,以下是我的问题:

  1. 有人可以向我解释一下 hashmap 在内存和大小调整方面的内部情况吗?调整大小时遵循的逻辑是什么?
  2. 如果我不得不松开双倍的内存来存储一个 215 到 216 之间的条目,为什么我不能限制我的应用程序始终具有小于 215 的哈希值,除非并且直到系统最多需要它.
  3. 假设如果我想存储 100 万个哈希值,每个哈希值由 250 个值组成,我需要 800MB。如果我将它们分成 2 个 125 个值的散列,即 200 万个 125 个值的散列,我需要 500MB。通过这种方式,我节省了 300 MB,这是巨大的!!这个计算对吗?在这种情况下我错过了什么吗?

提前致谢

最佳答案

由于你在redis中不断有1000个key,每个hash key中只有field number发生变化,而你的field number低于512,所以这种现象只是jemalloc造成的。

这是我使用 libc 作为我的 mem_allocator 时的行为:

您可以通过以下方式重新制作您的 redis:

make MALLOC=libc

再次运行测试,看看会得到什么。

回答您的问题:

  1. 有人可以向我解释一下 hashmap 在内存和调整大小方面的内部情况吗?调整大小时遵循的逻辑是什么?

    如前所述,您遇到的问题与redis本身无关。 Jemalloc这样做是为了提高效率

  2. 如果我不得不松开双倍的内存来存储一个 215 到 216 之间的条目,为什么我不能限制我的应用程序始终具有小于 215 的哈希值,除非并且直到系统需要它最多。

    当然可以,只要能限制字段数就可以

  3. 假设我要存储 100 万个哈希值,每个哈希值由 250 个值组成,我需要 800MB。如果我将它们分成 2 个 125 个值的散列,即 200 万个 125 个值的散列,我需要 500MB。通过这种方式,我节省了 300 MB,这是巨大的!!这个计算对吗?在这种情况下我错过了什么吗?

    我认为这不是正确的做法。这样做也许可以节省一些内存。但是,缺点是:当你将100万个哈希拆分为200万个时,redis会进行重新哈希(这会占用你一些空间)并且你会花费更多时间来找到一个键,因为它会导致更多哈希冲突的机会.

关于memory - 理解 hash 实现及其在 Redis 中的内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37612022/

相关文章:

c++ - 用于比较无法表示的数字的 std::map 技巧?

node.js如何在中间件中从redis数据库中获取数据

ruby-on-rails - Rails 5.2 和 Sidekiq : Can't find Worker Class

python - python 中的迭代会消耗整个内存 - 错误代码?

internet-explorer - IE 8 丢弃内存页?

c++ - STL C++ 中的内存分配

用于 IODocs 的 Heroku 上的 node.js 和 Redis

java - Java 内存有限环境中的智能缓冲

c# - 如何在我的盐和哈希代码中使用 SHA-512 和 Rfc2898DeriveBytes?

ruby - 不能使用数组作为 Ruby Hash 的默认值吗?