redis之理解内存

本文主要从3个方面分析:

  • Redis什么地方都消耗内存?

  • Redis中怎么对内存进行管理的?

  • 如何优化内存?

一、内存消耗

查看内存消耗

可以用info memory命令来查看内存消耗的关键指标。其中最重要的指标是used_memory_rss和used_memory以及他们的比值mem_fragmentation_ratio。

  • used_memory_rss:从操作系统角度显示Redis进程占用的 物理内存总量。

  • used_memory:Redis分配器分配的内存总量。

  • mem_fragmentation_ratio:>1,说明used_memory_rss-used_memory多出的部分并没用来存储数据,而是被内存碎片消耗;<1,一般是操作系统将Redis内存交换到硬盘所致,要格外关注,此时redis性能变得很差,甚至僵死。

内存消耗划分

Redis进程内存消耗主要包括:自身内存、对象内存、缓冲内存、内存碎片,其中Redis空进程自身内存消耗比较小,可以忽略不计。

  • 对象内存

    对象内存是 Redis内存占用最大的一块,存储着所有的用户数据。redis中所有的数据都采用 key-value类型,每次创建键值对时,至少创建2个对象:key对象和value对象 。键对象都是字符串,应该避免键过长。value主要包含5个主要的数据类型:List、set、zset、hash、string。其他数据类型都是建立在基本数据类型上的。

  • 内存缓冲

    内存缓冲区主要包括:客户端缓冲区、复制积压缓冲区、AOF缓冲区。

    客户端缓冲区指的是所有接入到Redis服务器TCP连接的输入输出缓冲。
    输入缓冲区无法控制,最大空间为 1G,如果超出将断开链接。

    普通客户端。Redis并没有对普通客户端进的输入缓冲区做限制,一般的客户端内存消耗可以忽 略不计,但是当有大量慢连接客户端接入时,这部分内存消耗就不能忽略了。

    从客户端。从客户端主节点会为从节点单独建立一条连接用于主从复制。当主从节点之间网 络延迟较高或直接点挂载大量从节点时这部分 内存消耗将占很大一大部分。

    订阅客户端。当使用发布订阅功能时,连接客户端使用单独的输出缓冲区。当订阅服务的消息生产快于消费速度时,输出缓冲区会产生挤压造成输出缓冲区溢出。

    复制积压缓冲区:用于实现部分复制功能。对于复制积压缓冲区整个主节点只有一个,所有从节点共享此缓冲区,复制积压缓冲区可有效减少全量复制。
    AOF缓冲区:这部分缓冲区用于在Redis重写期间保存最近写入的命令。

  • 内存碎片

    频繁做更新操作,大量过期键删除,键对象过期后,释放的空间无法得到充分利用,导致碎片率较高。
    解决方法:数据对齐,安全重启。


二、内存管理

内存管理主要有:设置内存上限、动态调整内存上限、内存回收策略等。

内存回收策略。有定期删除和惰性删除2种。

  • 定期删除

    redis 会将每个设置了过期时间的 key 放入到一个独立的字典中,以后会定期遍历这个字典来删除到期的 key。

  1. Redis 默认会每秒进行十次过期扫描(100ms一次),过期扫描不会遍历过期字典中所有的 key,而是采用了一种简单的贪心策略。

  2. 从过期字典中随机 20 个 key;

  3. 删除这 20 个 key 中已经过期的 key;如果过期的 key 比率超过 1/4,那就重复步骤 1;

  • 惰性删除

    除了定期遍历之外,它还会使用惰性策略来删除过期的 key,所谓惰性策略就是在客户端访问这个 key 的时候,redis 对 key 的过期时间进行检查,如果过期了就立即删除,不会给你返回任何东西。

    定期删除是集中处理,惰性删除是零散处理。

为什么要采用定期删除+惰性删除2种策略呢?

如果过期就删除。假设redis里放了10万个key,都设置了过期时间,你每隔几百毫秒,就检查10万个key,那redis基本上就死了,cpu负载会很高的,消耗在你的检查过期key上了。但是问题是,定期删除可能会导致很多过期key到了时间并没有被删除掉,那咋整呢?所以就是惰性删除了。这就是说,在你获取某个key的时候,redis会检查一下 ,这个key如果设置了过期时间那么是否过期了?如果过期了此时就会删除,不会给你返回任何东西。并不是key到时间就被删除掉,而是你查询这个key的时候,redis再懒惰的检查一下。

通过上述两种手段结合起来,保证过期的key一定会被干掉。所以说用了上述2种策略后,下面这种现象就不难解释了:数据明明都过期了,但是还占有着内存。

内存淘汰策略:

这个问题可能有小伙伴们遇到过,放到Redis中的数据怎么没了?

因为Redis将数据放到内存中,内存是有限的,比如redis就只能用10个G,你要是往里面写了20个G的数据,会咋办?当然会干掉10个G的数据,然后就保留10个G的数据了。那干掉哪些数据?保留哪些数据?当然是干掉不常用的数据,保留常用的数据了。

Redis提供的内存淘汰策略有如下几种:

1、noeviction 不会继续服务写请求 (DEL 请求可以继续服务),读请求可以继续进行。这样可以保证不会丢失数据,但是会让线上的业务不能持续进行。这是默认的淘汰策略。

2、volatile-lru 尝试淘汰设置了过期时间的 key,最少使用的 key 优先被淘汰。没有设置过期时间的 key 不会被淘汰,这样可以保证需要持久化的数据不会突然丢失。(这个是使用最多的)

3、volatile-ttl 跟上面一样,除了淘汰的策略不是 LRU,而是 key 的剩余寿命 ttl 的值,ttl 越小越优先被淘汰。

4、volatile-random 跟上面一样,不过淘汰的 key 是过期 key 集合中随机的 key。

5、allkeys-lru 区别于 volatile-lru,这个策略要淘汰的 key 对象是全体的 key 集合,而不只是过期的 key 集合。这意味着没有设置过期时间的 key 也会被淘汰。

6、allkeys-random 跟上面一样,不过淘汰的策略是随机的 key。allkeys-random 跟上面一样,不过淘汰的策略是随机的 key。


三、内存优化

内存优化包括:

  • 缩减键值对象
  • 共享对象池
  • 字符串优化
  • 编码优化
  • 控制键的数量等

参考《Redis开发与运维》
https://mp.weixin.qq.com/s/FyYhLS3X7LDe0PLxooz_cQ
https://blog.csdn.net/Butterfly_resting/article/details/89668661

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值