Redis原理(1) 内存全面详解

本文深入探讨Redis的内存管理,包括如何观察内存使用、内存碎片实战、虚拟内存的移除、OOM处理策略以及大key排查方法。讲解了Redis内存分配器jemalloc的工作原理,介绍了Redis内存碎片的产生和影响,以及Redis如何处理虚拟内存。此外,还讨论了Redis OOM时的策略选择和大key排查技巧,帮助理解Redis内存管理的核心概念。
摘要由CSDN通过智能技术生成

一. 我们怎么观察线上Redis内存

我们如果在我们的redis.conf配置文件里面配置:

# 最大内存设置,100M
maxmemory 104857600

查看redis内存信息 (info Memory)

172.29.2.11:7002> info Memory
# Memory
used_memory:2598042
used_memory_human:2.48M
used_memory_rss:3002368
used_memory_rss_human:2.86M
maxmemory:104857600
maxmemory_human:100.00M
mem_fragmentation_ratio:1.16
....

先大致看下几个字段的概念:

  • 1. maxmemory

用户配置的(maxmemory )最大内存量, maxmemory_human 人能看懂的单位。

  • 2. used_memory

Redis使用的内存总量,它包含了实际缓存占用的内存(包含虚拟内存)和Redis自身运行所占用的内存(如元数据、lua)。它是由Redis使用内存分配器分配的内存,所以这个数据并没有把内存碎片的内存给统计进去

  • 3. used_memory_rss

从操作系统角度看redis进程占用的内存量。包括进程运行本身需要的内存、内存碎片等,但是不包括虚拟内存

  • 4. mem_fragmentation_ratio

used_memory_rss/used_memory的值,可以代表碎片化。

mem_fragmentation_ratio越大,used_memory_rss就越大,内存碎片就越大。

mem_fragmentation_ratio小于1时,代表使用了过多的虚拟内存,由于虚拟内存的媒介是磁盘,比内存速度要慢很多,当这种情况出现时,应该及时排查,如果内存不足应该及时处理,如增加Redis节点、增加Redis服务器的内存、优化应用等。

 

那问题来了,内存碎片是什么?怎么产生的? 虚拟内存又是什么?如何能产生?

带着这些问题,我又薅掉了些自己仅存的几根头发,又欣喜的瞄了下对面老大的光头,并发誓我一定不会变成这样!就是带着这伟大的理想,我做了下面的事情。

二. Redis内存碎片实战

首先我配置maxmemory为100M ,然后写程序一直set key value 到 内存爆满后(注意是不同的key),直到程序抛出OOM异常:

然后我查看了下此时内存信息


used_memory_rss和used_memory 都达到了100M,证明内存已经打满了。

但是我们的mem_fragmentation_ratio 还很正常,于是我执行了下flushdb,删除当前数据库所有key。

172.29.2.10:7000> flushdb
OK
172.29.2.10:7000> info Memory
# Memory
used_memory:2617096
used_memory_human:2.50M
used_memory_rss:112009216
used_memory_rss_human:106.82M
...
mem_fragmentation_ratio:42.80

然后惊奇的发现: used_memory被释放了,但是used_memory_rss 还是雷打不动。mem_fragmentation_ratio内存碎片比达到了42.8之多,碎片化很严重。如果此时不清理掉碎片, 会导致redis重新设置大key时没法存放,这很严重。

Redis为什么这么做?

Redis有自己的内存分配器(jemalloc),当数据删除后,释放的内存空间由Redis自己的内存分配器管理,并没有立即将内存返回给操作系统,所以对于操作系统而言,仍然认为Redis占用了内存。这样的好处是,减少Redis向系统申请内存分配的次数,提升Redis自身性能。

jemalloc简单介绍

Redis在编译时便会指定内存分配器;内存分配器可以是 libc 、jemalloc或者tcmalloc, 默认是jemalloc

jemalloc 内存分配方式为 按照一系列固定大小分配内存空间,jemalloc 按照申请的内存大小分配最接近的内存空间;

比如申请220字节,jemalloc 会分配256字节,如果还要继续写入20字节,Redis则不会继续向系统申请内存空间,直接写。

总而言之 : 按页分配内存,而不是按实际数据大小来分配,碎片产生的原因就是页内部分数据回收了,这个页还是占着空间。

 

三. Redis使用虚拟内存实战

首先我们在redis.conf配置文件配置虚拟内存:

# #开启虚拟内存
vm-enabled yes
# #交换出来的value保存的文件路径
vm-swap-file /usr/local/app/redis-cluster/7002/redis.swap
# #redis使用的最大内存上限
vm-max-memory 134857600

然后启动居然报错了:

*** FATAL CONFIG FILE ERROR ***
Reading the configuration file, at line 26
>>> 'vm-enabled yes'
Bad directive or wrong number of arguments

最后发现,据说redis2.6后面的版本已经把虚拟内存配置去掉了。~~~

此时,仿佛看到了一位不负责的男一号,疯狂的肆虐着女一号,女二号,女三号.... 为啥后面版本去掉了,我也不清除,我就简单介绍下虚拟内存思想吧:

redis 发现大部分数据都是冷数据(不常访问的数据),于是搞出虚拟内存来专门存放这些冷数据,这样就可以大大节省实际内存空间。 但是redis虚拟内存只是存储value,而不存储key。

好了我就知道这么多,即使你用虎头铡 我也只能言尽了~

 

四. Redis OOM

在上面有个环节,redis报了oom,原因就是使用的内存已经超过了配置的maxmemory。

## 客户端报错
OOM command not allowed when used memory > ‘maxmemory’

此时redis进程还是在的,并没有崩溃。如果在设置值也可能会设置进去,取决与下面这个配置:

maxmemory-policy volatile-lru

maxmemory-policy 为 内存达到峰值后,淘汰现有key,以便接受新数据 的策略,有下面几个可选参数:

  • noeviction: 不淘汰现有key,直接返回异常,不再接受set key了。
  • allkeys-lru: 优先删除掉最近最不经常使用的key,用以保存新数据。
  • volatile-lru: 删除 最近不常使用的 且 设置了过期时间的key 。
  • allkeys-random
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值