redis 内存不足 排查_Redis——内存占用优化
# 1.优化内存占用
了解redis的内存模型,对优化redis内存占用有很大帮助。下面介绍几种优化场景。
- 1)利用jemalloc特性进行优化
上一小节所讲述的90000个键值便是一个例子。由于jemalloc分配内存时数值是不连续的,因此key/value字符串变化一个字节,可能会引起占用内存很大的变动;在设计时可以利用这一点。
例如,如果key的长度如果是8个字节,则SDS为17字节,jemalloc分配32字节;此时将key长度缩减为7个字节,则SDS为16字节,jemalloc分配16字节;则每个key所占用的空间都可以缩小一半。
- 2)使用整型/长整型
如果是整型/长整型,Redis会使用int类型(8字节)存储来代替字符串,可以节省更多空间。因此在可以使用长整型/整型代替字符串的场景下,尽量使用长整型/整型。
- 3)共享对象
利用共享对象,可以减少对象的创建(同时减少了redisObject的创建),节省内存空间。目前redis中的共享对象只包括10000个整数(0-9999);可以通过调整``REDIS_SHARED_INTEGERS``参数提高共享对象的个数;例如将REDIS_SHARED_INTEGERS调整到20000,则0-19999之间的对象都可以共享。
考虑这样一种场景:论坛网站在redis中存储了每个帖子的浏览数,而这些浏览数绝大多数分布在0-20000之间,这时候通过适当增大REDIS_SHARED_INTEGERS参数,便可以利用共享对象节省内存空间。
- 4)避免过度设计
然而需要注意的是,不论是哪种优化场景,都要考虑内存空间与设计复杂度的权衡;而设计复杂度会影响到代码的复杂度、可维护性。
如果数据量较小,那么为了节省内存而使得代码的开发、维护变得更加困难并不划算;还是以前面讲到的90000个键值对为例,实际上节省的内存空间只有几MB。但是如果数据量有几千万甚至上亿,考虑内存的优化就比较必要了。
# 2.关注内存碎片率
内存碎片率是一个重要的参数,对redis 内存的优化有重要意义。
如果内存碎片率过高(jemalloc在1.03左右比较正常),说明内存碎片多,内存浪费严重;这时便可以考虑重启redis服务,在内存中对数据进行重排,减少内存碎片。
如果内存碎片率小于1,说明redis内存不足,部分数据使用了虚拟内存(即swap);由于虚拟内存的存取速度比物理内存差很多(2-3个数量级),此时redis的访问速度可能会变得很慢。因此必须设法增大物理内存(可以增加服务器节点数量,或提高单机内存),或减少redis中的数据。
要减少redis中的数据,除了选用合适的数据类型、利用共享对象等,还有一点是要设置合理的数据回收策略(maxmemory-policy),当内存达到一定量后,根据不同的优先级对内存进行回收。
# 3.内存增长排查
## 3.1 Redis内存分析
### 3.1.1 内存组成
```bash
redis> info memory
"# Memory
used_memory:29020136
used_memory_human:27.68M
used_memory_rss:15560704
used_memory_peak:45295152
used_memory_peak_human:43.20M
used_memory_lua:36864
mem_fragmentation_ratio:0.54
mem_allocator:jemalloc-3.6.0
"
```
属性名属性说明
used_memory Redis 分配器分配的内存量,也就是实际存储数据的内存总量used_memory_human 以可读格式返回 Redis 使用的内存总量used_memory_rss 从操作系统的角度,Redis进程占用的总物理内存used_memory_peak 内存分配器分配的最大内存,代表used_memory的历史峰值used_memory_peak_human 以可读的格式显示内存消耗峰值used_memory_lua Lua引擎所消耗的内存mem_fragmentation_ratio used_memory_rss /used_memory比值,表示内存碎片率mem_allocator Redis 所使用的内存分配器。默认: jemalloc
---
计算公式如下:
```
used_memory = 自身内存+对象内存+缓冲内存+lua内存
used_rss = used_memory + 内存碎片
```
如下图所示:
![](https://ghost.oss.sherlocky.com/7/e9/424ebf6d90efcb0796ec856f0e4d0.png)
### 3.1.2 内存分析
- 1) 自身内存:一个空的Redis占用很小,可以忽略不计
- 2) kv内存:key对象 + value对象
- 3) 缓冲区:客户端缓冲区(普通 + slave伪装 + pubsub)以及aof缓冲区(比较固定,一般没问题)
- 4) Lua:Lua引擎所消耗的内存
### 3.1.3. 内存突增常见问题
- 1) kv内存:bigkey、大量写入
- 2) 客户端缓冲区:一般常见的有普通客户端缓冲区(例如monitor命令)或者pubsub客户端缓冲区
## 3.2 可能出现的问题排查
- 1) bigkey?
> redis --bigkeys:可以对redis整个 keyspace 进行统计(数据量大时采样,调用 scan 命令),寻找每种数据类型较大的 keys,给出数据统计
``redis-cli --bigkeys -i 0.1 -h 127.0.0.1``
- 2) 键值个数增加?
- 3) 客户端缓冲区
> 如果是因为缓冲区问题,会从``info clients``找到明显问题。重点观察是否明显的``omem``大于0的情况。
- 4) Redis的kv哈希表做了 rehash
## 3.4 rehash
### 3.4.1 Redis的kv存储结构
如下图所示,Redis的所有kv保存在dict中,其中ht对应两个哈希表ht[0]和ht[1],平时一个空闲,一个用于存储数据,只有当需要rehash时,ht[1]才会用到。
![](https://ghost.oss.sherlocky.com/1/2c/b8ce4bb1f0d5576fd95549fe3a9a4.png)
### 3.4.2 Redis的字典rehash
为了保证哈希表的负载,当哈希表的元素个数等于哈希表槽数时候,会进行rehash扩容。扩容后h[1]的容量等于第一个大于等于ht[0].size*2的2n,例如hash表的初始化容量是4,那么下一次扩容就是8,以此类推。
## 3.5 总结
由于哈希表的特性,Redis 中键值数量大,不会对存取造成性能影响,但是会出现内存增长的情况。
控制键个数有几个建议:
- 无用的键值设置过期时间或者定期删除
- 优化键值设计:例如可以使用 ziplist hash合并优化部分字符串类型。-
- 未来改进:内核层面支持 rehash 的审计日志以及增强 rehash 的速度
参考:
[精讲Redis内存模型](https://my.oschina.net/u/3779583/blog/1829617)
[一次 Redis 内存诡异增长的排查过程](https://mp.weixin.qq.com/s/eXKkfhdG8VyS9OmKZOkeEw)
redis 内存不足 排查_Redis——内存占用优化相关推荐
- redis 内存不足 排查_Redis内存溢出问题排查
Redis内存溢出问题排查 最近生产环境服务器上的redis内存波动,导致了一次OOM,查询/var/log/messages后发现原本只会在1~2G大小之间波动的Redis内存竟然达到8G,然后OO ...
- redis 内存不足 排查_Redis 系统学习之 redis 内存模型
关注:架构师学习路线,每日更新互联网最新技术文章与你不断前行,实战资料,笔试面试 前言 Redis是目前最火爆的内存数据库之一,通过在内存中读写数据,大大提高了读写速度,可以说Redis是实现网站高并 ...
- java内存问题怎么排查,java占内存高排查 java应用占用内存过高排查的解决方案...
想了解java应用占用内存过高排查的解决方案的相关内容吗,zhaixing_0307在本文为您仔细讲解java占内存高排查的相关知识和一些Code实例,欢迎阅读和指正,我们先划重点:java,占内存过 ...
- linux 内存溢出排查_java 内存溢出 栈溢出的原因与排查方法
1. 内存溢出的原因是什么? 内存溢出是由于没被引用的对象(垃圾)过多造成JVM没有及时回收,造成的内存溢出.如果出现这种现象可行代码排查: 一)是否应用中的类中和引用变量过多使用了Static修饰 ...
- redis 内存不足 排查_redis莫名数据被清问题排查记录
新版系统刚发布,前端反馈redis中的值经常被清空,第一反应怀疑谁的代码里面执行了flushall或者flushdb操作 通过redis的monitor追踪一波, redis-cli -a " ...
- Linux用户态进程监控内存写排查踩内存
高铁北京回杭州的路上,想到一个简单的话题. 在一个复杂的程序中,发生踩内存是一件非常恶心的事情,很难通过什么线索直到谁在哪个函数中往哪个地址写了什么,比方说数组越界写什么的. 去年,我曾经长篇大论了一 ...
- redis存储对象_redis内存优化总结
本文主要参考<>一书,主要分为以下六个部分: 1.redisObject对象 2.缩减键值对象 3.共享对象池 4.字符串优化 5.编码优化 6.控制key的数量 一. redisObje ...
- redis 内存不足 排查_一文深入了解 Redis 内存模型,Redis 的快是有原因的!
前言 一.Redis内存统计 二.Redis内存划分 1.数据 2.进程本身运行需要的内存 3.缓冲内存 4.内存碎片 三.Redis数据存储的细节 1.概述 2.jemalloc 3.redisOb ...
- gin redis 链接不上_内存优化,Redis是如何实现的!
点击上方"小罗技术笔记",关注公众号 第一时间送达实用干货 各位朋友新年开工好,今年由于特殊情况好多小伙伴今天在家开启远程办公模式(一直很向往),不过在这真想吐槽一下现有的远程办公 ...
最新文章
- 为什么说 TCP/IP 是一个不确定性网络
- mysql5.0修改字符集,查看mysql字符集及修改表结构
- 一颗椰子糖机器人_孩子编程启蒙机器人玩了不下10个,最推荐哪个呢?
- 使用pytorch的相关问题总结
- QualityCenter的备份
- php16进制密钥签名对接支付,简单理解rsa的加密和签名-PHP实现
- Jquery实现定时器实例
- JAVA责任链设计模式
- 相机模型-Extended Unified Camera Model
- 用python写论文_[文章] 编写高质量 Python 的 6 个技巧
- 《算法设计与分析基础》第2版
- 在Linux下安装GmSSL
- mmdetection 绘制PR曲线
- 加州大学戴维斯计算机博士生,关于加州大学戴维斯分校博士研究生CSC奖学金信息分享会的通知...
- 手机摄影技巧总结——永远拍出美美的照片
- 计算机上计算器不见,win10系统自带的计算器不见了的处理教程
- 计算机文化基础(高职高专版 第十一版)第一章答案
- rem和vw,vh的介绍
- 在12306的程序猿面前,没人敢说委屈
- 奋斗(2)第15集剧情介绍
热门文章
- 【Python】使用生成器(yield from)和装饰器封装函数
- vue+element 创建Cron表达式生成器组件 [带最近五次执行时间]
- 域控锁定计算机和用户,AD域账户锁定时间
- Oracle数据库常用函数总结
- 数据结构 - 串的模式匹配
- 如何不浪费青春,让游戏快速上架 Steam
- 【Java】判断电话号码所属的运营商
- 【观察】数智驱动+知识封装,鼎捷软件如何炼就“雅典娜”这个“新物种”?...
- 第四章第8节 网络中的网络(NiN)
- linux中tr的功能多多