redis内存管理

Redis主进程的内存消耗:

Redis自身使用的内存:消耗很少,3MB多点
对象内存
缓冲内存
内存碎片

1. 对象内存:

  • 所有key对象长度 + 所有value对象长度
  • 每次创建键值对时,至少创建两个类型对象:key对象、value对象,应该使用短键名

2. 缓冲内存:

  • 每个客户端的输入、输出缓冲内存:
    • 输入缓冲最大1G,超出则关闭该客户端连接;
    • 输出缓冲:16KB的固定缓冲区、动态缓冲区,动态缓冲区可通过client-output-buffer-limit配置参数限制(根据客户端类型normal、slave、pubsub,分开设置)
      • client-output-buffer-limit normal 0 0 0
      • client-output-buffer-limit slave 256mb 64mb 60 //超过256MB时,或者持续超过64MB达60秒,关闭连接
      • client-output-buffer-limit pubsub 32mb 8mb 60
  • 复制积压缓冲内存:用于主从复制的部分复制,所有客户端共享该缓冲区,默认1MB,可通过repl-backlog-size调整,适当调大,可有效避免全量复制;
  • AOF缓冲内存:用于保存在AOF重写期间的写命令,便于重写完毕后把缓冲的命令追加到AOF文件中;

3. 内存碎片:

当存储的数据长短差异较大时,就容易出现大量内存碎片,应该尽可能地保持数据对齐或使用固定长度的字符串;
内存碎片只能通过完全重启Redis来清除;

Redis子进程内存消耗:

在执行AOF重写和RDB快照持久化时,会fork一个子进程,父子进程将共享此刻的内存快照,期间,在Linux下使用写时复制技术:父进程会为新进的写命令请求需要修改的内存页复制出一份副本来完成写操作,子进程结束后,父进程再把该副本覆盖回原来的内存页。
Linux默认开启的THP把写时复制期间的内存页复制单位从4KB变为2MB,加大了持久化时的内存消耗,应该关闭该功能:sudo echo never > /sys/kernel/mm/transparent_hugepage/enabled

最大内存设置

默认情况下,在32位OS中,Redis最大使用3GB的内存,在64位OS中则没有限制。

在使用Redis时,应该对数据占用的最大空间有一个基本准确的预估,并为Redis设定最大使用的内存。否则在64位OS中Redis会无限制地占用内存(当物理内存被占满后会使用swap空间),容易引发各种各样的问题。

通过如下配置控制Redis使用的最大内存:

maxmemory 100mb

在内存占用达到了maxmemory后,再向Redis写入数据时,Redis会:

  • 根据配置的数据淘汰策略尝试淘汰数据,释放空间
  • 如果没有数据可以淘汰,或者没有配置数据淘汰策略,那么Redis会对所有写请求返回错误,但读请求仍然可以正常执行

在为Redis设置maxmemory时,需要注意:

如果采用了Redis的主从同步,主节点向从节点同步数据时,会占用掉一部分内存空间,如果maxmemory过于接近主机的可用内存,导致数据同步时内存不足。所以设置的maxmemory不要过于接近主机可用的内存,留出一部分预留用作主从同步。

内存回收

当maxmemory限制达到的时候Redis会使用的行为由 Redis的maxmemory-policy配置指令来进行配置。

以下的策略是可用的:

  • allkeys-lru: 使用LRU算法进行数据淘汰,所有的key都可以被淘汰。
  • volatile-lru:使用LRU算法进行数据淘汰(淘汰上次使用时间最早的,且使用次数最少的key),只淘汰设定了有效期的key(在过期集合的键)。
  • allkeys-random: 随机淘汰数据,所有的key都可以被淘汰。
  • volatile-random:随机淘汰数据,只淘汰设定了有效期的key。
  • volatile-ttl:淘汰剩余有效期最短的key。
  • noeviction:不进行数据淘汰,当达到内存限制并且客户端尝试执行会让更多内存被使用的命令时返回错误(大部分的写入指令,但DEL和几个例外)。

最好为Redis指定一种有效的数据淘汰策略以配合maxmemory设置,避免在内存使用满后发生写入失败的情况。
一般来说,推荐使用的策略是volatile-lru,并辨识Redis中保存的数据的重要性。对于那些重要的,绝对不能丢弃的数据(如配置类数据等),应不设置有效期,这样Redis就永远不会淘汰这些数据。对于那些相对不是那么重要的,并且能够热加载的数据(比如缓存最近登录的用户信息,当在Redis中找不到时,程序会去DB中读取),可以设置上有效期,这样在内存不够时Redis就会淘汰这部分数据。

lru算法:最近最久未使用算法
Redis的LRU算法并非完整的实现。这意味着Redis并没办法选择最佳候选来进行回收,也就是最久未被访问的键。相反它会尝试运行一个近似LRU的算法,通过对少量keys进行取样,然后回收其中一个最好的key(被访问时间较早的)。
Redis LRU有个很重要的点,你通过调整每次回收时检查的采样数量,以实现调整算法的精度。这个参数可以通过以下的配置指令调整:

maxmemory-samples 5

Redis为什么不使用真实的LRU实现是因为这需要太多的内存。不过近似的LRU算法对于应用而言应该是等价的。

参考文章:
https://www.jianshu.com/p/2f14bc570563

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值