关于数据库:败家玩意儿Redis-竟然浪费了这么多内存

36次阅读

共计 2577 个字符,预计需要花费 7 分钟才能阅读完成。

作为内存数据库,内存空间大小对于 Redis 来说是至关重要的。内存越多,意味着存储的数据也会越多。然而不晓得你有没有遇到过这样的状况,明明空间很大,然而内存的应用却不是很现实。

为什么会呈现这样的状况呢?这期咱们就来看看这个 ” 诡异 ” 的事件。

坐好了,筹备发车!

图注:思维导图

查看内存应用状况

首先想要晓得 Redis 内存的应用状况,咱们就须要获取相干的信息。

Redis 中查看内存相干信息是很简略的,只须要在命令行输出『info memory』就能够看到各种相干数据。在这里我列举了一些较为重要的参数:

  • used_memory:曾经应用了的内存大小。
  • used_memory_rss:redis 物理内存的大小。
  • mem_fragmentation_ratio:内存碎片率。

这里有一个内存碎片率的名词须要关注下,它能够用来示意以后的内存应用状况。

具体计算形式:

对于内存碎片率,个别放弃在 1~1.5 之间是最正当的。

什么是内存碎片

理解了内存碎片率,那什么是内存碎片呢?

定义是这样的 :因为一块间断闲暇的空间比所要申请的空间小,导致这块空间不可用,对于内存整体来说就是内存碎片。

举个例子:

假如有一块 100MB 的间断闲暇内存空间,你每次都会从中申请一块 30MB 的内存。那么当你申请了 3 次后,这块内存就只剩下了 10MB 的空间,第 4 次申请的时候就会失败。如果没有其它的空间开释并且每次申请的空间都比 10MB 大,那么剩下的空间对于整块内存来说就是内存碎片。

导致内存碎片的起因

Redis 中,最罕用的是写入、批改、删除数据。这些操作在执行后都会产生 肯定水平的内存碎片。

写入数据

Redis 中分配内存是依据固定的大小来划分内存空间的。为了缩小调配次数,Redis 会依据申请的内存最靠近的固定值调配相应大小的空间。

什么意思呢,如果 Redis 依照 8 字节、16 字节、32 字节、48 字节等来分配内存。当你想要存储一个 18 字节的数据时,此时 Redis 就会调配 32 字节(因为 32 是与 18 最靠近的固定值)。如果这时候,再写入的数据须要的内存空间在 14 个字节内,那 Redis 就无需再进行调配了。

这就像你有不同的箱子,为了装货色,你须要找一个体积最靠近的箱子来装。然而装进去后,你发现还有空间能够放一些小东西,就无需再找箱子了。

然而,这种调配空间的形式会带来肯定水平的内存碎片。咱们能够把固定大小的划分空间看成不同体积的箱子,每种箱子里的空间不同水平上都会有残余。这些残余的空间就是内存碎片。

批改数据

键值对进行批改时,可能会变大也会变小,相应的就会占用额定空间或者开释不必的空间。

如图中所示,以后 A、B、C 别离占用了 3、2、4 个字节,将 A 从 3 字节批改为 2 字节时,此时就会有 1 个字节的空间空了进去,这时就会呈现 1 个字节的碎片。

那如果我将数据 A 从 3 字节批改为 4 字节呢?此时为了保持数据 A 的空间连续性,操作系统会把 B 拷贝到别的空间。此时又会呈现 1 个字节的碎片。

删除数据

了解了批改数据,删除数据就很容易明确了。还是上边的例子,此时删除了数据 B,那么就开释了 2 个字节的空间。这样对于整个内存空间来说就产生了 2 个字节的碎片。

如何解决内存碎片

你可能会有疑难,内存碎片会有什么危害呢?

咱们还是以上边的箱子来示意。你想想,如果你要把这些箱子都装上车运走,每个箱子里都有空进去的空间(内存碎片),那么运行一次的效率及性价比是不是会很低。同样,在 Redis 中,因为大量的碎片存在,会导致理论利用率变低。

那么咱们有没有方法来解决内存碎片呢?

推倒重来

第一种形式很简略,间接推倒重来。也就是把 Redis 间接重启完事儿,内存一断电全世界就喧扰。然而这种暴力省事的形式却有很多隐患。

生产环境中你这么搞的话得提前烧烧香,保佑不会出什么问题。如果你没进行过长久化,那么就别烧了,烧了也没用。如果有长久化的话,那么复原时长还得取决你长久化文件的大小,在这个阶段还无奈提供服务。糟心不?

空间置换

那么有没有不这么刺激的形式。

有的,高版本的 Redis 提供了内存碎片清理的形式。一言以蔽之,就是空间置换。

怎么个置换法?咱们的目标是为了打消内存碎片,那么咱们把已应用的内存数据重新整理到一起不就行了吗?让不间断的空间变成间断的,剩下的空间,持续来调配。

画个图了解下:

然而,说说还是挺容易的,实践到实际两头还隔着性能损耗。

在进行屡次数据拷贝过程中,单线程的 Redis 只能干等着,无奈响应客户端的申请。这时候只能干瞪眼,性能太受影响。

凉,那该咋整?!别急,有缓解的策略,你接着往下看。

Redis 中有专门的参数设置用来进行主动清理内存碎片:activedefrag yes

这个命令是启动清理性能的,这还不够,Redis 中还须要其余的条件限度才可能进行清理。

上面参数都是满足任一条件后就能够进行清理:

  • active-defrag-ignore-bytes 100mb:碎片达到 100MB 时,开启清理。
  • active-defrag-threshold-lower 10:当碎片超过 10% 时,开启清理。
  • active-defrag-threshold-upper 100:内存碎片超过 100%,尽最大清理。

在解决的过程中,为了防止对失常申请的影响,同时又能保障性能。Redis 同时还提供了监控 CPU 占用比例的参数,在满足以下条件时才会保障清理失常发展:

  • active-defrag-cycle-min 5:清理内存碎片占用 CPU 工夫的比例不低于此值,保障清理能失常发展。
  • active-defrag-cycle-max 75:清理内存碎片占用 CPU 工夫的比例不高于此值。一旦超过则进行清理,从而防止在清理时,大量的内存拷贝阻塞 Redis,导致其它申请提早。

总结

查看内存应用状况

  • 在命令行执行 info memory 即可查看 Redis 内存相干信息。依据内存碎片率能够在肯定机会内进行清理碎片清理。

内存碎片导致起因

  • 写入数据时,Redis 为了缩小调配次数在分配内存是依据固定的大小来划分内存空间的。批改数据时会开释或占用额定的内存空间,删除数据时会开释空间。这样就会产生不同水平的内存碎片。

如何解决内存碎片

  • 通过重启 Redis 的形式进行解决,如果没有长久化可能会导致事变。在长久化状况下,复原速度须要取决于文件的大小。
  • 通过空间置换形式,也就是将已应用的内存数据重新整理到一起。

集体 Java 老手学习交换园地

正文完
 0