redis 是一种内存数据库,将数据保存在内存中,读写效率要比传统的将数据保存在磁盘上的数据库要快很多 。所以,监控 Redis 的内存消耗并了解 Redis 内存模型对高效并长期稳定使用 Redis 至关重要 。

文章插图
内存使用统计通过 info memory 命令可以获得 Redis 内存相关的指标 。较为重要的指标和解释如下所示:

文章插图

文章插图
当 memfragmentationratio > 1 时,说明有部分内存并没有用于数据存储,而是被内存碎片所消耗,如果该值很大,说明碎片率严重 。
当 memfragmentationratio < 1 时,这种情况一般出现在操作系统把 Redis 内存交换 (swap) 到硬盘导致,出现这种情况要格外关注,由于硬盘速度远远慢于内存,Redis 性能会变得很差,甚至僵死 。
当 Redis 内存超出可以获得内存时,操作系统会进行 swap,将旧的页写入硬盘 。从硬盘读写大概比从内存读写要慢5个数量级 。used_memory 指标可以帮助判断 Redis 是否有被swap的风险或者它已经被swap 。
在 Redis Administration 一文 (链接在文末) 建议要设置和内存一样大小的交换区,如果没有交换区,一旦 Redis 突然需要的内存大于当前操作系统可用内存时,Redis 会因为 out of memory 而被 Linix Kernel 的 OOM Killer 直接杀死 。虽然当 Redis 的数据被换出 (swap out) 时,Redis的性能会变差,但是总比直接被杀死的好 。
Redis 使用 maxmemory 参数限制最大可用内存 。限制内存的目的主要有:
- 用于缓存场景,当超出内存上限 maxmemory 时使用 LRU 等删除策略释放空间 。
- 防止所用的内存超过服务器物理内存,导致 OOM 后进程被系统杀死 。
内存消耗划分Redis 进程内消耗主要包括:自身内存 + 对象内存 + 缓冲内存 + 内存碎片,其中 Redis 空进程自身内存消耗非常少,通常 usedmemoryrss 在 3MB 左右时,used_memory 一般在 800KB 左右,一个空的 Redis 进程消耗内存可以忽略不计 。

文章插图
对象内存对象内存是 Redis 内存占用最大的一块,存储着用户所有的数据 。Redis 所有的数据都采用 key-value 数据类型,每次创建键值对时,至少创建两个类型对象:key 对象和 value 对象 。对象内存消耗可以简单理解为这两个对象的内存消耗之和(还有类似过期之类的信息) 。键对象都是字符串,在使用 Redis 时很容易忽略键对内存消耗的影响,应当避免使用过长的键 。有关 Redis 对象系统的详细内容,请看我之前的文章十二张图带你了解 Redis 的数据结构和对象系统 。
缓冲内存【一文了解 Redis 内存监控和内存消耗】缓冲内存主要包括:客户端缓冲、复制积压缓冲区和 AOF 缓冲区 。
客户端缓冲指的是所有接入到 Redis 服务器 TCP 连接的输入输出缓冲 。

文章插图
输入缓冲无法控制,最大空间为 1G,如果超过将断开连接 。而且输入缓冲区不受 maxmemory 控制,假设一个 Redis 实例设置了 maxmemory 为 4G,已经存储了 2G 数据,但是如果此时输入缓冲区使用了 3G,就已经超出了 maxmemory 限制,可能导致数据丢失、键值淘汰或者 OOM 。
输入缓冲区过大主要是因为 Redis 的处理速度跟不上输入缓冲区的输入速度,并且每次进入输入缓冲区的命令包含了大量的 bigkey 。
输出缓冲通过参数 client-output-buffer-limit 控制,其格式如下所示 。
client-output-buffer-limit [hard limit] [soft limit] [duration]hard limit 是指一旦缓冲区大小达到了这个阈值,Redis 就会立刻关闭该连接 。而 soft limit 和时间 duration 共同生效,比如说 soft time 为 64mb、duration 为 60,则只有当缓冲区持续 60s 大于 64mb 时,Redis 才会关闭该连接 。
普通客户端是除了复制和订阅的客户端之外的所有连接 。Reids 对其的默认配置是 client-output-buffer-limit normal 0 0 0 , Redis 并没有对普通客户端的输出缓冲区做限制,一般普通客户端的内存消耗可以忽略不计,但是当有大量慢连接客户端接入时这部分内存消耗就不能忽略,可以设置 maxclients 做限制 。特别当使用大量数据输出的命令且数据无法及时推送到客户端时,如 monitor 命令,容易造成 Redis 服务器内存突然飙升 。相关案例可以查看这篇文章美团在Redis上踩过的一些坑-3.redis内存占用飙升 。
推荐阅读
- 3个案例让你了解什么是互联网营销思维
- 10分钟就理解Redis序列化协议,你也能编写redis客户端
- Redis 到底是怎么实现“附近的人”这个功能的呢?
- PHP 使用 Redis
- 一文告诉你信息流和竞价的区别在哪里?
- 一文看懂Oracle查询表空间的每日增长量和历史情况统计
- Java 使用 Redis
- 一文读懂线性回归、岭回归和Lasso回归
- 喝茶的人还必须了解生活
- 世界上对茶的最了解不超过苏东坡
