「Nosql」Redis小记-内存解析&内存消耗篇

*博客搬家:初版发布于 2017/08/12 18:32    原博客地址:https://my.oschina.net/sunqinwen/blog/1507171

Redis内存消耗分析

注:本文默认读者已初步学会使用redis了。

首先我们通过info命令查看相关指标,其中几个memory的重要指标整理出来如下:

属性 解释
used_memory redis内部存储的所有数据的内存总占用量(自身内存+对象内存+缓冲内存)
used_memory_ress redis进程占用的总物理内存
mem_fragmentation_ratio used_memory_ress与used_memory的比值,即为内存碎片率
mem_allocator 内存分配器,默认为jemalloc

 

(1)碎片率的解释

 当内存碎片率>1时,说明redis进程占用物理内存的总量大于Redis实际存储数据(表1-1第一行)的内存占用量,溢出来的部分内存被内存碎片消耗,如果溢出部分过大,则说明内存碎片率严重。

② 相反的,如果碎片率<1时,则说明Redis存储的数据总量已经超出了redis进程占用内存的总量,造成这种情况是因为操作系统把Redis内存交换至硬盘导致(swap),由于硬盘读取速度远远慢与内存,因此这种情况下redis性能极差,可能出现僵死。

(2)redis内存消耗的几个来源

① 自身内存:redis启动后自身运行所需内存;

② 对象内存:内存占用最大的一部分,这里面存储的就是用户自身的数据(业务数据),数据以key-value类型存储,内存消耗可表示为:key内存+value内存。

③ 缓冲内存:主要由客户端缓冲区+复制积压缓冲区+AOF缓冲区组成,具体解释如下:

  • 客户端缓冲区指的是所有接入redis服务器的TCP连接的输入和输出缓冲,输入缓冲无法被控制,最大空间为1G,超过立即断开连接,输出缓冲通过client-output-buffer-limit控制。
  • 复制积压缓冲区指的是redis在2.8版本以后提供了一块可以重复利用的固定大小的缓冲区,用来实现部分复制功能,使用repl-backlog-size参数控制,默认1MB(主从结构下,主节点只存在一个该缓冲区,从节点共用,那时可以设置较大的缓冲区空间),该缓冲区可以避免全量复制。
  • AOF缓冲区用于存储在redis重写期间保存最近的写入命令,无法控制,通常取决于AOF重写时间以及写入命令量,一般情况下很小。

④ 内存碎片:redis默认的内存分配器是jemalloc,可选的还有glibc和tcmalloc;内存分配器为了更好的管理以及重复利用内存,分配策略一般采用固定范围的内存块进行分配;因此,我们在存储一块5kb的内容时,内存分配器可能会为我们分配8kb的块存储,剩下的3kb不能再次分配给其他对象存储,因而沦为了内存碎片;jemalloc对碎片化问题做了优化,一般来讲碎片化率保持在1.03左右。

可能造成内存碎片率过高的场景:

  • 频繁的更新操作,例如频繁对已存在的键做append、setrange等操作;
  • 大量过期键删除,键对象过期删除后释放的空间无法得到充分的利用,导致碎片率上升。

解决办法:

  • 数据对齐,尽量采用数字类型或固定长度的字符串(大部分业务场景不满足这种方式);
  • 重启,重启节点可以使内存重整理,利用高可用的结构(节点集群+主从结构),将碎片率过高的节点主节点转换为从节点,然后进行安全重启。

⑤子进程内存消耗:子进程内存消耗指的是执行AOF/RDB重写时redis创建的子进程内存消耗;redis执行fork操作产生的子进程内存占用量对外表现为与父进程相同,理论上需要一倍的物理内存来完成重写的操作。但是linux具备写时复制技术(copy-on-write),父子进程会共享相同的物理内存页,当父进程处理写请求时会对需要修改的页复制出一份副本来完成写操作,而子进程依然读取fork时整个父进程的内存快照,总结:

  • 子进程并不需要消耗一倍的父进程内存,实际消耗根据期间写入命令量决定,但依然要预留出一些内存防止溢出;
  • 需要设置sysctl vm.overcommit_memory=1允许内核可以分配所有的物理内存,防止redis进程执行fork时因剩余内存不足导致失败;
  • 排查当前系统是否支持开启THP,如果开启建议关闭,防止copy-on-write期间内存过度消耗。

原文地址:https://www.cnblogs.com/hama1993/p/10331884.html

时间: 2024-08-28 12:02:34

「Nosql」Redis小记-内存解析&内存消耗篇的相关文章

LibreOJ #2006. 「SCOI2015」小凸玩矩阵 二分答案+二分匹配

#2006. 「SCOI2015」小凸玩矩阵 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 小凸和小方是好朋友,小方给小凸一个 N×M N \times MN×M(N≤M N \leq MN≤M)的矩阵 A AA,要求小凸从其中选出 N NN 个数,其中任意两个数字不能在同一行或同一列,现小凸想知道选出来的 N NN 个数中第 K KK 大的数字的最小值是多少. 输入格式 第一行给出三个整数

—Libre#2009. 「SCOI2015」小凸玩密室

#2009. 「SCOI2015」小凸玩密室 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 小凸和小方相约玩密室逃脱,这个密室是一棵有 n nn 个节点的完全二叉树,每个节点有一个灯泡.点亮所有灯泡即可逃出密室.每个灯泡有个权值 Ai A_iA?i??,每条边也有个权值 bi b_ib?i??. 点亮第 1 11 个灯泡不需要花费,之后每点亮一个新的灯泡 V VV 的花费,等于上一个被点亮的

redis源码解析之内存管理

zmalloc.h的内容如下: 1 void *zmalloc(size_t size); 2 void *zcalloc(size_t size); 3 void *zrealloc(void *ptr, size_t size); 4 void zfree(void *ptr); 5 char *zstrdup(const char *s); 6 size_t zmalloc_used_memory(void); 7 void zmalloc_enable_thread_safeness(v

JavaScript 引擎「V8」发布 8.0 版本,内存占用量大幅下降

上周,JavaScript 引擎「V8」的开发团队在该项目官方网站上正式宣布推出最新的 8.0 版本.这次更新的重点主要集中在错误修复及性能改善上,正式的版本将在数周后随着谷歌 Chrome 80 稳定版一起发布. V8 是谷歌公司推出的开源高性能 JavaScript 引擎,主要用于提升 Web 浏览器内部 JavaScript 脚本执行的性能.V8 通过 C++ 语言编写,主要用在 Chrome 浏览器以及 Node.js 上,实现了对 ECMAScript 与 WebAssembly 的支

Java当中的内存分配以及值传递问题内存解析

首先必须说明作为Java程序员对于内存只要有大致的了解就可以了,如果你对Java当中的某一个知识点在不需要分析内存分配过程的情况下可以掌握,那就大可不必去研究内存.如果你对知识点已经掌握,那么你应该把更多的精力放在对业务逻辑的分析与设计上,这样的话你才可能这一行业走的更远. 好了废话不多说了,下面我带着大家先来简单的看一下Java当中所涉及的内存分配,接着我会以讲解Java当中的值传递问题,分析在代码执行的过程当中内存的状态. 一.Java当中所涉及到的内存分类 Java当中你知道这5种内存就够

redis 源代码分析(一) 内存管理

一,redis内存管理介绍 redis是一个基于内存的key-value的数据库,其内存管理是很重要的,为了屏蔽不同平台之间的差异,以及统计内存占用量等,redis对内存分配函数进行了一层封装,程序中统一使用zmalloc,zfree一系列函数,其相应的源代码在src/zmalloc.h和src/zmalloc.c两个文件里,源代码点这里. 二,redis内存管理源代码分析 redis封装是为了屏蔽底层平台的差异,同一时候方便自己实现相关的函数,我们能够通过src/zmalloc.h 文件里的相

block 解析 - 内存

回顾 上一篇 我们了解到了用__block修饰的变量,可以在block内部修改,__block变量其实对应一个结构体 struct __Block_byref__para1_0 { void *__isa; __Block_byref__para1_0 *__forwarding; int __flags; int __size; char *_para1; }; block结构体相应的也有一个成员引用,这样会增加对局部变量的 _para1引用,在Block销毁的时候引用就释放掉了 struct

类的对象内存解析

对于声明一个类实例化后,用实例化的对象调用属性时的内存解析: Animal a1=new Animal();//类的实例化,实例化出一个a1对象 a1.name="花花": a1.age=3; Animal a2=new Animal(); Animal a3=a1;//相当于把a1的首地址赋值给a3,其实a11和a3公用的一个空间.

03_2_JAVA中的面向对象与内存解析

03_2_JAVA中的面向对象与内存解析 1. 成员变量 成员变量可以是Java语言中任何一种数据类型(包括基本数据类型和引用数据类型) 在定义成员变量时可以对其初始化,如果不对其初始化,Java使用默认的初始值. 如下列表: 成员变量类型 取值 byte 0 short 0 int 0 long 0L char '\u0000' float 0.0F double 0.0D boolean false 所有引用类型 null 成员变量的作用范围为整个类体. 2. 引用 Java语言中除基本类型