美文网首页
第八章 理解内存

第八章 理解内存

作者: super_pcm | 来源:发表于2019-08-12 21:17 被阅读0次

Redis所有的数据都存在内存中,当前内存虽然越来越便宜,但跟廉价的硬盘相比成本还是比较昂贵,因此如何高效利用Redis内存变得非常重要。高效利用Redis内存首先需要理解Redis内存消耗在哪里,如何管理内存,最后才能考虑如何优化内存。掌握这些知识后能够实现用更少的内存存储更多的数据,从而降低成本。本章主要内容如下:

  • 内存消耗分析。
  • 管理内存的原理与方法。
  • 内存优化技巧。

8.1 内存消耗

理解Redis内存,首先需要掌握Redis内存消耗在哪些方面。有些内存消耗是必不可少的,而有些可以通过参数调整和合理使用来规避内存浪费。内存消耗可以分为进程自身消耗和子进程消耗。

8.1.1 内存使用统计

要查看redis自身的内存使用情况,可以使用info memory命令来获取。下面是部分的指标解析:

属性名 属性说明
used_memory_human 以可读的格式返回used_memory
used_memory_rss_human 从操作系统的绝度显示redis进程占用的物理内存总量
used_memory_peak_human 以可读的方式返回used_memory_peak
used_memory_lua_human Lua引擎所消耗的内存大小
mem_fragmentation_ratio used_memory_rss/used_memory的比值,表示内存碎片率
mem_allocator Redis所使用的内存分配器。默认是jemlloc

这里需要特别说明的是mem_fragmentation_ratio这个指标。
当mem_fragmentation_ratio>1时,说明used_memory_rss-used_memory多出的部分内存并没有用于数据存储,而是被内存碎片所消耗,如果两者相差很大,说明碎片率严重。
当mem_fragmentation_ratio<1时,这种情况一般出现在操作系统把Redis内存交换(Swap)到硬盘导致,出现这种情况时要格外关注,由于硬盘速度远远慢于内存,Redis性能会变得很差,甚至僵死。

8.1.2 内存消耗划分

Redis进程内存的消耗主要包括:自身内存+对象内存+缓冲内存+内存碎片。
其中Redis自身内存消耗非常小,在空载的时候Redis的自身内存使用不超过1MB。Redis主要内存消耗的图如下所示:

Redis内存消耗划分

8.1.3 子进程内存消耗

子进程内存消耗主要指执行AOF/RDB重写时Redis创建的子进程内存消耗。由于Linux采用写时复制技术,Redis在fork操作的时候消耗的内存实际上很小。但是需要关注的一个参数是:Transparent Huge Pages(THP)。在Linux内核(2.6.38)
中增加这个参数后,写时复制的内存页的单位从4KB变成了2MB,如果父进程有大量写命令,会加重内存拷贝量,从而造成过度内存消耗。建议关闭。

子进程内存消耗总结如下:

  • Redis产生的子进程并不需要消耗1倍的父进程内存,实际消耗根据期间写入命令量决定,但是依然要预留出一些内存防止溢出。
  • 需要设置sysctl vm.overcommit_memory=1允许内核可以分配所有的物理内存,防止Redis进程执行fork时因系统剩余内存不足而失败。
  • 排查当前系统是否支持并开启THP,如果开启建议关闭,防止copy-onwrite期间内存过度消耗。

8.2 内存管理

8.2.1 设置内存上限

Redis使用maxmemory参数限制最大可用内存。限制内存的目的主要有:

  • 用于缓存场景,当超出内存上限maxmemory时使用LRU等删除策略释放空间。
  • 防止所用内存超过服务器物理内存。

Redis默认无限使用服务器内存,为防止极端情况下导致系统内存耗尽,建议所有的Redis进程都要配置maxmemory。

8.2.3 内存回收策略

Redis的内存回收机制主要体现在以下两个方面:

  • 删除到达过期时间的键对象。
  • 内存使用达到maxmemory上限时触发内存溢出控制策略。

1. 删除过期键对象

Redis所有的键都可以设置过期属性,内部保存在过期字典中。由于进程内保存大量的键,维护每个键精准的过期删除机制会导致消耗大量的CPU,对于单线程的Redis来说成本过高,因此Redis采用惰性删除和定时任务删除机制实现过期键的内存回收。

  • 惰性删除:惰性删除用于当客户端读取带有超时属性的键时,如果已经超过键设置的过期时间,会执行删除操作并返回空,这种策略是出于节省CPU成本考虑,不需要单独维护TTL链表来处理过期键的删除。但是单独用这种方式存在内存泄露的问题,当过期键一直没有访问将无法得到及时删除,从而导致内存不能及时释放。正因为如此,Redis还提供另一种定时任务删除机制作为惰性删除的补充。

  • 定时任务删除:Redis内部维护一个定时任务,默认每秒运行10次(通过配置hz控制)。定时任务中删除过期键逻辑采用了自适应算法,根据键的过期比例、使用快慢两种速率模式回收键,流程如图8-4所示。

定时任务删除过期键逻辑

流程说明:

  1. 定时任务在每个数据库空间随机检查20个键,当发现过期时删除对应的键。
  2. 如果超过检查数25%的键过期,循环执行回收逻辑直到不足25%或运行超时为止,慢模式下超时时间为25毫秒。
  3. 如果之前回收键逻辑超时,则在Redis触发内部事件之前再次以快模式运行回收过期键任务,快模式下超时时间为1毫秒且2秒内只能运行1次。
  4. 快慢两种模式内部删除逻辑相同,只是执行的超时时间不同。

2. 内存溢出控制策略

当Redis所用内存达到maxmemory上限时会触发相应的溢出控制策略。具体策略受maxmemory-policy参数控制,Redis支持6种策略。

  1. noeviction:默认策略,不会删除任何数据,拒绝所有写入操作并返回客户端错误信息(error)OOM command not allowed when used memory,此时Redis只响应读操作。
  2. volatile-lru:根据LRU算法删除设置了超时属性(expire)的键,直到腾出足够空间为止。如果没有可删除的键对象,回退到noeviction策略。
  3. allkeys-lru:根据LRU算法删除键,不管数据有没有设置超时属性,直到腾出足够空间为止。
  4. allkeys-random:随机删除所有键,直到腾出足够空间为止。
  5. volatile-random:随机删除过期键,直到腾出足够空间为止。
  6. volatile-ttl:根据键值对象的ttl属性,删除最近将要过期数据。如果没有,回退到noeviction策略。

内存溢出控制策略可以采用config set maxmemory-policy{policy}动态配置。Redis支持丰富的内存溢出应对策略,可以根据实际需求灵活定制,比如当设置volatile-lru策略时,保证具有过期属性的键可以根据LRU剔除,而未设置超时的键可以永久保留

8.3 内存优化

内存优化的点包括:

  1. redisObject对象,也就是要捣鼓redis数据结构的对象了,设置一个合适长度的encoding,可能会有一个较大的优化效果。
  2. 缩减键值对象,比如user:uid修改为u:uid;也可以使用序列化效率更高的工具。
  3. 共享对象池,redis内部维护一个[0-9999]的整数对象池。创建整数的对象的时候,直接新增一个共享连接即可,不需要创建新的对象。但是这在设置了maxmemory并启用LRU相关淘汰策略的时候,这个共享池是会被禁用的。
  4. 字符串优化。
  5. 编码的优化,使用ziplist压缩编码优化hash、list等结构,注重效率和空间的平衡。
  6. 控制键的数量,比如可以用hash结构来代替string结构,这样可以降低键的数量。

相关文章

  • 第八章 理解内存

    Redis所有的数据都存在内存中,当前内存虽然越来越便宜,但跟廉价的硬盘相比成本还是比较昂贵,因此如何高效利用Re...

  • ULK3 based on kenerl 2.6.11 读书笔

    第八章 内存管理 本章通过三部分内容描述内核给自己动态分配内存: ...

  • 2. 托管内存

    对于Unity内存管理而言,需要理解托管堆。对于如何分析托管内存和如何优化内存,可以参见Unity优化中的理解托管...

  • 理解内存管理

    • 堆和栈 内存泄露、野指针 堆和栈是逻辑分区也是物理分区。Stack Overflow,堆栈溢出是一起溢出的。堆...

  • 内存的理解

    1 程序运行为什么需要内存 1.1 计算机程序运行的目的 计算机为什么需要编程?编程已经编了很多年,已经写了很多程...

  • 理解内存管理

    引用计数简介 引用计数可以有效的管理对象的生命周期。当我们创建一个对象的时候,它的引用计数为1。当有一个新的指针指...

  • iOS 内存理解

    对于iOS开发者来说,第一个要过的关大概就是iOS的内存管理吧。 那么我第一篇就从iOS的内存管理讲起: iOS内...

  • 内存泄漏理解

    1.简单理解 内存泄漏指的是堆内存泄漏,栈不会发生内存泄漏,只会发生栈溢出(StackOverFlow)。简单一个...

  • 内存的理解

    内存:用于暂时存放CPU中的运算数据以及与硬盘等外部存储器交换的数据 计算机在运行中,CPU就会把需要运算的数据调...

  • 内存管理

    ARC内存管理机制详解理解 iOS 的内存管理

网友评论

      本文标题:第八章 理解内存

      本文链接:https://www.haomeiwen.com/subject/fpvpjctx.html