Redis内存——内存消耗(内存都去哪了?)
Reids作为一个基于内存的数据库,内存是否能够高效合理的利用至关重要!从价格上来讲,我们从某宝或某东上可以看到内存条的价格要比普通的机械硬盘贵上十几倍,就算是是固态硬盘也要贵上不少,从性能上来说,内存占用过高同样会引起Reids响应变慢,从高可用上来说,内存过大可能会会引起部分数据丢失,故障恢复变慢.......
我们首先要知道Redis都消耗在哪,才能更好的管理优化内存的使用,已达到使用更少的内存存储更多的数据、节省成本的目的,才能真正实现Redis的高性能、高可用。
1 Redis内存消耗
Redis内存消耗主要在于其主进程消耗和子进程消耗。而主进程消耗又主要包括自身内存、对象内存、缓冲区内存、内存碎片五个方面。
1.1 自身内存
自身内存是指Redis进程自身所占用的内存,这部分内存通常很小,一个空的Redis进程所消耗的内存几乎可以忽略不计。因此我们在分析内存消耗的时候一般不考虑其自身内存。
1.2 对象内存
对象内存是Redis内存中占用最大的。我们知道Redis主要有五大对象,字符串、列表、哈希、集合、有序集合。其它如BigMaps、GEO等也都是基于这五大对象实现的。每种对象底层所使用的数据结构都是不同的,因此它们所占用的内存空间大小也是不同的。在使用过程中我们要根据场景选择合适的对象,以达到内存合理利用、避免溢出的目的。
关于Redis的五大对象和其底层所使用的几种数据结构,可以查看我的其他几篇文章。传送门
此外,Redis的每一种对象都是key-value的键值对形式。每个键值对的创建都包含两个对象,key对象和value对象。因此对象内存的消耗可以理解为sizeof(key)+sizeof(value)。而key对象都是字符串类型的,在使用过程中我们不应该忽略key对象所占用的内存,应该避免使用过大的key。
1.3 缓冲区内存
Redis主要有三个缓冲区,客户端缓冲区、AOF缓冲区、复制积压缓冲区。
客户端缓冲区是为了解决客户端和服务端请求和处理速度不匹配问题的,它又分为输入和输出缓冲区。
输入缓冲区会先把客户端发送过来的命令暂存起来,Redis 主线程再从输入缓冲区中读取命令,进行处理。当在处理完数据后,会把结果写入到输出缓冲区,再通过输出缓冲区返回给客户端。
AOF缓冲区我们前面的文章已经学习过,是在进行AOF持久化时所用到的缓冲区,AOF缓冲区消耗的内存取决于AOF重写时间和写入命令量, 这部分空间占用通常很小关于AOF缓冲区的介绍我们可以复习一下
复制积压缓冲区则是在集群环境中为了保证主从节点数据同步的所设置的。
主节点在向从节点传输 RDB 文件的同时,会继续接收客户端发送的写命令请求。这些写命令就会先保存在复制缓冲区中,等 RDB 文件传输完成后,再发送给从节点去执行。主节点上会为每个从节点都维护一个复制缓冲区,来保证主从节点间的数据同步。
1.4 内存碎片
内存碎片主要是由于操作系统的内存分配机制和Redis内存分配器的分配策略所决定的。
内存分配器为了更好地管理和重复利用内存, 分配内存策略一般采用固定范围的内存块进行分配。例如当保存5KB对象时内存分配器可能会采用8KB的块存储, 而剩下的3KB空间变为了内存碎片不能再分配给其他对象存储。
关于内存碎片的问题,后面会有单独的一篇文章来详细的进行解释。
1.5 子进程内存消耗
除了上面所提到的4种内存消耗之外,还有一种也不能忽视,那就是子进程的内存消耗。
子进程内存消耗主要指执行AOF/RDB重写时Redis创建的子进程内存消耗。我们在学习Redis持久化的时候知道,在执行RDB快照和AOF重写时主进程会fork出一个子进程,由子进程完成快照和重写操作,虽然使用了写时复制的技术,子进程可以不用完全复制父进程的所有物理内存,但是仍然需要复制其内存页表,在此期间如果有写入操作则需要复制出一份副本出来。因此子进程同样会消耗一部分内存,其消耗的内存量取决于RDB和AOF期间的写入命令量。在执行RDB和AOF重写的时候为了防止内存溢出,会预留一部分内存。
2 内存消耗统计
关于分析Redis内存消耗的分析,我们可以使用info memory命令来获取内存相关的指标,读懂每个指标有助于我们更加熟练的分析Redis的内存使用情况,如下一份全量的Redis最新版本(6.2.1)的info memory命令的各项指标说明。
127.0.0.1:6379> info memory
used_memory:87795176                # Redis分配的内存总量(byte),包含redis进程内部的开销和数据占用的内存
used_memory_human:83.73M            # Redis分配的内存总量(mb)
used_memory_rss:222318592           # 向操作系统申请的内存大小(byte)
used_memory_rss_human:212.02M       # 向操作系统申请的内存大小(mb)
used_memory_peak:337032496          # redis的内存消耗峰值(byte)
used_memory_peak_human:321.42M      # redis的内存消耗峰值(mb)
used_memory_peak_perc:26.05%        # 使用内存与峰值内存的百分比(used_memory / used_memory_peak) *100%
used_memory_overhead:2010038        # Redis维护数据集的内部机制所需的内存开销,包括所有客户端输出缓冲区、查询缓冲区、AOF重写缓冲区和主从复制的backlog
used_memory_startup:1960232         # Redis启动完成使用的内存
used_memory_dataset:85785138        # 数据占用的内存(used_memory - used_memory_overhead)
used_memory_dataset_perc:99.94%     # 数据占用的内存大小百分比,(used_memory_dataset / (used_memory - used_memory_startup))*100%
allocator_allocated:88139168        # 分配器分配的内存
allocator_active:89964544           # 分配器活跃的内存
allocator_resident:389095424        # 分配器常驻的内存
total_system_memory:67118374912     # 主机内存总量(byte)
total_system_memory_human:62.51G    # 主机内存总量(mb)
used_memory_lua:37888               # Lua引擎存储占用的内存(byte)
used_memory_lua_human:37.00K        # Lua引擎存储占用的内存(mb)
used_memory_scripts:0               # Lua脚本所占用的内存(byte)
used_memory_scripts_human:0B				# Lua脚本所占用的内存(mb)
number_of_cached_scripts:0					# 缓存的Lua脚本数
maxmemory:0                         # 配置中设置的最大可使用内存值(byte),默认0,不限制
maxmemory_human:0B                  # 配置中设置的最大可使用内存值(mb)
maxmemory_policy:noeviction         # 当达到maxmemory时的淘汰策略
allocator_frag_ratio:1.02           # 分配器的碎片率
allocator_frag_bytes:1825376        # 分配器的碎片大小
allocator_rss_ratio:4.32            # 分配器常驻内存比例
allocator_rss_bytes:299130880       # 分配器的常驻内存大小
rss_overhead_ratio:0.57             # 常驻内存开销比例
rss_overhead_bytes:-166776832       # 常驻内存开销大小
mem_fragmentation_ratio:2.53        # 碎片率(used_memory_rss / used_memory),正常(1,1.6),大于比例说明内存碎片严重
mem_fragmentation_bytes:134564432   # 内存碎片大小
mem_not_counted_for_evict:0         # 被驱逐的内存
mem_replication_backlog:0           # redis复制积压缓冲区内存
mem_clients_slaves:0                # Redis节点客户端消耗内存
mem_clients_normal:49694            # Redis所有常规客户端消耗内存
mem_aof_buffer:0                    # AOF使用内存
mem_allocator:jemalloc-5.1.0        # 内存分配器
active_defrag_running:0             # 活动碎片整理是否处于活动状态(0没有,1正在运行)
lazyfree_pending_objects:0          # 0-不存在延迟释放的挂起对象
lazyfreed_objects:0					#	已经延迟释放的对象
3 总结
最后,我们用一张思维导图来看一看Redis的内存都去哪儿了

系列文章:
-----END-----
关注下方公众号,回复“Redis”,可得Redis相关学习资料
Redis内存——内存消耗(内存都去哪了?)的更多相关文章
- Java的内存管理与内存泄露
		
作为Internet最流行的编程语言之一,Java现正非常流行.我们的网络应用程序就主要采用Java语言开发,大体上分为客户端.服务器和数据库三个层次.在进入测试过程中,我们发现有一个程序模块系统内存 ...
 - 一文了解 Redis 内存监控和内存消耗
		
Redis 是一种内存数据库,将数据保存在内存中,读写效率要比传统的将数据保存在磁盘上的数据库要快很多.所以,监控 Redis 的内存消耗并了解 Redis 内存模型对高效并长期稳定使用 Redis ...
 - Linux内存都去哪了:(1)分析memblock在启动过程中对内存的影响
		
关键词:memblock.totalram_pages.meminfo.MemTotal.CMA等. 最近在做低成本方案,需要研究一整块RAM都用在哪里了? 最直观的的就是通过/proc/meminf ...
 - redis过期策略和内存淘汰机制
		
目录 常见的删除策略 redis使用的过期策略:定期删除+惰性删除 定期删除 惰性删除 为什么要采用定期删除+惰性删除2种策略呢? redis内存淘汰机制 常见的删除策略 1.定时删除:在设置键的过期 ...
 - # 深入理解Redis(二)——内存管理的建议与技巧
		
引语 随着使用Redis的深入,我们不可避免的需要深入了解优化Redis的内存,本章将重点讲解Redis的内存优化之道,同时推荐大家阅读memory-optimization一文. 想要高效的使用Re ...
 - Redis(三)内存模型
		
本文转载自编程迷思,原文链接 深入学习Redis(1):Redis内存模型 前言 Redis是目前最火爆的内存数据库之一,通过在内存中读写数据,大大提高了读写速度,可以说Redis是实现网站高并发不可 ...
 - Redis+Mysql模式和内存+硬盘模式的异同
		
http://www.open-open.com/lib/view/open1346029825942.html 学习任何新知识,都是一个循序渐进的过程,从刚开始的懵懂无知,到简单熟悉,然后突然的彻悟 ...
 - volatile关键字?MESI协议?指令重排?内存屏障?这都是啥玩意
		
一.摘要 三级缓存,MESI缓存一致性协议,指令重排,内存屏障,JMM,volatile.单拿一个出来,想必大家对这些概念应该有一定了解.但是这些东西有什么必然的联系,或者他们之间究竟有什么前世今生想 ...
 - 关于redis内存分析,内存优化
		
对于redis来说,什么是最重要的? 毋庸置疑,是内存. 一.reids 内存分析 redis内存使用情况:info memory 示例: 可以看到,当前节点内存碎片率为226893824/20952 ...
 
随机推荐
- 在ASP.NET Core中用HttpClient(五)——通过CancellationToken取消HTTP请求
			
用户向服务器发送HTTP请求应用程序页面是一种非常可能的情况.当我们的应用程序处理请求时,用户可以从该页面离开.在这种情况下,我们希望取消HTTP请求,因为响应对该用户不再重要.当然,这只是实际应用 ...
 - Fork/Join 框架
			
本文部分摘自<Java 并发编程的艺术> Fork/Join 框架概述 Fork/Join 框架是 Java7 提供的一个用于并行执行任务的框架,是把一个大任务分割成若干个小任务,最终汇总 ...
 - java例题_15 有小到大排序
			
1 /*15 [程序 15 排序] 2 题目:输入三个整数 x,y,z,请把这三个数由小到大输出. 3 程序分析:我们想办法把最小的数放到 x 上,先将 x 与 y 进行比较,如果 x>y 则将 ...
 - 走进springboot
			
SpringBoot基础 核心思想---自动装配---约定大于配置 开发环境:jdk1.8.maven.springboot.idea 一.快速构建一个springboot项目 1.1.进入sprin ...
 - 一本关于HTTP的恋爱日记
			
1991年 8月 我叫客户端,英文名字 client. 她叫服务端,英文名字 server. 这一年,我们出生了. 是的,我们都是90后. 我爱她,可是她却远在天边. 为了和她可以互诉衷肠,我同时发明 ...
 - sunny图表——NABCD分析
			
项目 内容 这个作业属于哪个课程 2021春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 团队选题 我在这个课程的目标是 初步获得软件工程师的能力 这个作业在哪个具体方面帮助我实现目标 选 ...
 - PAT B1033 旧键盘上的几个键又毁坏了,于是在输入一段文字时,对应得的字符就不会出现。
			
题中可用的字母包括大小写(给出的坏键的字母,全为大写),数字,"_" "," "." "-" "+" ...
 - Linux+MicroPython+esp8233 YES!
			
MicPython MicroPython是澳大利亚程序员和物理学家Damien George在2013年一次成功的众筹活动后最初创建的.MicroPython 和 CPython 在 Python ...
 - 《SQL必知必会》学习笔记整理
			
简介 本笔记目前已包含 <SQL必知必会>中的所有章节. 我在整理笔记时所考虑的是:在笔记记完后,当我需要查找某个知识点时,不需要到书中去找,只需查看笔记即可找到相关知识点.因此在整理笔记 ...
 - ServletConfig和ServletContext接口
			
ServletConfig 在web.xml文件中使用一个或多个init-param元素进行配置后,Tomcat初始化Servlet时,都会将该Servlet的配置信息封装到一个ServletConf ...