Redis的高效可以说是轻量级的epoll模型和基于内存的读写共同组成的,关于epoll对于以前的select或者poll的性能优势这里不做介绍,本篇主要介绍领一个重点,Redis的内存分配原理。

获取内存信息命令:info memory

used_memory:  Redis分配器分配的内存总量,就是内部存储的所有数据内存占用量。        

used_memory_human:  以可读的格式返回used_memory。

used_memory_rss:  以操作系统同的角度显示Redis进程占用的物理内存总量。  

used_memory_rss_human:  以可读的格式返回used_memory_rss。

used_memory_peak:  内存使用的峰值。

used_memory_peak_human:  以可读的格式返回used_memory_peak。

total_system_memory:  系统可用内存总量。

total_system_memory_human:  以可读的格式返回total_system_memory。

used_memory_lua:  lua引擎消耗的内存总量。

used_memory_lua_human:  以可读的格式返回used_memory_lua。

maxmemory:  Redis最大可用内存。

maxmemory_human:  以可读的格式返回maxmemory。

maxmemory_policy:  达到最大可用内存时使用的淘汰策略。

mem_fragmentation_ratio:  used_memory_rss/used_memory比值,标识碎片率。

mem_allocator:  Redis使用的内存分配器,默认是jemalloc。

  重要指标:used_memory_rss和used_memory以及它们的比值mem_fragmentation_ratio。

  当mem_fragmentation_ratio>1时,说明used_memory_rss-used_memory多出的部分内存并没有用于数据存储,而是被内存碎片所消耗,如果两者相差很大,说明碎片率严重。

  当mem_fragmentation_ratio<1时,这种情况一般出现在操作系统把Redis内存交换(Swap)到硬盘导致,出现这种情况时要格外关注,由于硬盘速度远远慢于内存,Redis性能会变得很差,甚至僵死。

内存分配图:

自身内存:Redis运行自身使用的内存

对象内存:用户数据

缓冲内存:客户端缓冲、复制积压缓冲区、AOF缓冲区

  客户端缓冲:指的是所有接入到Redis服务器TCP连接的输入输出缓冲。输入缓冲无法控制,最大空间为1G,如果超过将断开连接。输出缓冲通过参数client-output-buffer-limit控制。输入输出缓冲区在大流量的场景中容易失控,造成Redis内存的不稳定,需要重点监控。

    普通客户端:除了复制和订阅的客户端之外的所有连接,Redis的配置项是:client-output-buffer-limit。Redis并没有对普通客户端的输出缓冲区做限制,一般普通客户端的内存消耗可以忽略不计,但是当有大量慢连接客户端接入时这部分内存消耗就不能忽略了,可以设置maxclients做限制。特别是当使用大量数据输出的命令且数据无法及时推送给客户端时,如monitor命令,容易造成Redis服务器内存突然飙升。

    从客户端:主节点会为每个从节点单独建立一条连接用于命令复制,配置项是:client-output-buffer-limit。当主从节点之间网络延迟较高或主节点挂载大量从节点时这部分内存消耗将占用很大一部分,建议主节点挂载的从节点不要多于2个,主从节点不要部署在较差的网络环境下,如异地跨机房环境,防止复制客户端连接缓慢造成溢出。

    订阅客户端:当使用发布订阅功能时,连接客户端使用单独的输出缓冲区,配置项为:client-output-buffer-limit,当订阅服务的消息生产快于消费速度时,输出缓冲区会产生积压造成输出缓冲区空间溢出。  

  复制积压缓冲区:Redis在2.8版本之后提供了一个可重用的固定大小缓冲区用于实现部分复制功能,根据repl-backlog-size参数控制,默认1MB。对于复制积压缓冲区整个主节点只有一个,所有的从节点共享此缓冲区,因此可以设置较大的缓冲区空间,如100MB,这部分内存投入是有价值的,可以有效避免全量复制。

  AOF缓冲区:这部分空间用于在Redis重写期间保存最近的写入命令。AOF缓冲区空间消耗用户无法控制,消耗的内存取决于AOF重写时间和写入命令量,这部分空间占用通常很小。

内存碎片:

  Redis默认的内存分配器采用jemalloc,在64位系统中将内存空间划分为:小、大、巨大三个范围。每个范围内又划分为多个小的内存块单位,如下所示:

  小:[8byte],[16byte,32byte,48byte,...,128byte],[192byte,428256byte,...,512byte],[768byte,1024byte,...,3840byte]

  大:[4KB,8KB,12KB,...,4072KB]

  巨大:[4MB,8MB,12MB,...]

  大量过期键删除,键对象过期删除后,释放的空间无法得到充分利用,导致碎片率上升。重启节点可以做到内存碎片重新整理,因此可以利用高可用架构,如Sentinel或Cluster,将碎片率过高的主节点转换为从节点,进行安全重启。

子进程内存消耗:

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

  Linux Kernel在2.6.38内核增加了Transparent Huge Pages(THP)机制,而有些Linux发行版即使内核达不到2.6.38也会默认加入并开启这个功能,如Redhat Enterprise Linux在6.0以上版本默认会引入THP。虽然开启THP可以降低fork子进程的速度,但之后copy-on-write期间复制内存页的单位从4KB变为2MB,如果父进程有大量写命令,会加重内存拷贝量,从而造成过度内存消耗。

  子进程内存消耗需要注意:

    Redis产生的子进程并不需要消耗1倍的父进程内存,实际消耗根据期间写入命令量决定,但是依然要预留出一些内存防止溢出。

    需要设置sysctl vm.overcommit_memory=1允许内核可以分配所有的物理内存,防止Redis进程执行fork时因系统剩余内存不足而失败。

    排查当前系统是否支持并开启THP,如果开启建议关闭,防止copy-on-write期间内存过度消耗。

下一篇会介绍Redis不同类型对象的存储和管理

Redis深入学习笔记(六)Redis内存分配的更多相关文章

  1. <c和指针>学习笔记5动态内存分配和预处理器

    1 动态内存 比如声明数组得时候,我们需要提前预估数组长度,分配大了浪费,少了就更不好操作了.从而引入动态分配,需要的时候再分配. (1)malloc和free void *malloc(size_t ...

  2. Redis学习笔记六:持久化实验(AOF,RDB)

    作者:Grey 原文地址:Redis学习笔记六:持久化实验(AOF,RDB) Redis几种持久化方案介绍和对比 AOF方式:https://blog.csdn.net/ctwctw/article/ ...

  3. Redis:学习笔记-01

    Redis:学习笔记-01 该部分内容,参考了 bilibili 上讲解 Redis 中,观看数最多的课程 Redis最新超详细版教程通俗易懂,来自 UP主 遇见狂神说 1. Redis入门 2.1 ...

  4. SpringBoot学习笔记:Redis缓存

    SpringBoot学习笔记:Redis缓存 关于Redis Redis是一个使用ANSI C语言编写的免费开源.支持网络.可基于内存亦可以持久化的日志型.键值数据库.其支持多种存储类型,包括Stri ...

  5. Redis:学习笔记-04

    Redis:学习笔记-04 该部分内容,参考了 bilibili 上讲解 Redis 中,观看数最多的课程 Redis最新超详细版教程通俗易懂,来自 UP主 遇见狂神说 10. Redis主从复制 1 ...

  6. Redis:学习笔记-03

    Redis:学习笔记-03 该部分内容,参考了 bilibili 上讲解 Redis 中,观看数最多的课程 Redis最新超详细版教程通俗易懂,来自 UP主 遇见狂神说 7. Redis配置文件 启动 ...

  7. Redis in Action : Redis 实战学习笔记

    1 1 1 Redis in Action : Redis  实战学习笔记 1 http://redis.io/ https://github.com/antirez/redis https://ww ...

  8. Redis:学习笔记-02

    Redis:学习笔记-02 该部分内容,参考了 bilibili 上讲解 Redis 中,观看数最多的课程 Redis最新超详细版教程通俗易懂,来自 UP主 遇见狂神说 4. 事物 Redis 事务本 ...

  9. java之jvm学习笔记六-十二(实践写自己的安全管理器)(jar包的代码认证和签名) (实践对jar包的代码签名) (策略文件)(策略和保护域) (访问控制器) (访问控制器的栈校验机制) (jvm基本结构)

    java之jvm学习笔记六(实践写自己的安全管理器) 安全管理器SecurityManager里设计的内容实在是非常的庞大,它的核心方法就是checkPerssiom这个方法里又调用 AccessCo ...

  10. # go微服务框架kratos学习笔记六(kratos 服务发现 discovery)

    目录 go微服务框架kratos学习笔记六(kratos 服务发现 discovery) http api register 服务注册 fetch 获取实例 fetchs 批量获取实例 polls 批 ...

随机推荐

  1. OO第三次博客总结

    一. 规格发展历史 从20世纪60年代开始,就存在着许多不同的形式规格说明语言和软件开发方法.在形式规格说明领域一些最主要的发展过程列举如下: 1969-1972 C.A.R Hoare撰写了&quo ...

  2. Feign get接口传输对象引发一场追寻

    一个报错引发的追寻之路: Feign get接口传输对象,调用方接口代码: @FeignClient(name = "manage") public interface Acces ...

  3. ubuntu下使用opencv问题以及解决方案

    CMakeFiles/hw5_1_node.dir/computeORB.o: In function `cv::String::~String()':/usr/local/include/openc ...

  4. Vue慕课网音乐项目随手记--node代理及数据抓取

    1.抓取数据 链接   https://y.qq.com/portal/playlist.html Parameters 通过上图能看到,qq音乐通过设置了refer和host来保护接口. 那么怎么才 ...

  5. BarCodeUtile

    package com.rscode.credits.util; import java.awt.image.BufferedImage; import java.io.ByteArrayOutput ...

  6. .net core+Spring Cloud学习之路 一

    文章开头唠叨两句. 2019年了,而自己参加工作也两年有余了,用一个词来概括这两年多的生活,就是:“碌碌无为”. 也不能说一点收获都没有,但是很少.2019来了,我立志要打破现状,改变自己,突破自我. ...

  7. Linux 的终端及设置

    Linux 的终端及设置 终端是一种字符型设备,有多种类型,通常使用tty 来简称各种类型的终端设备.终端特殊设备文件一般有以下几种: /dev/ttySn 串行端口终端 (Serial Port T ...

  8. sdk(输入驱动物体 驱动属性 被驱动物体 被驱动属性 驱动数值 一键搞定驱动),当你的目标体很多展开会卡的时候使用这个

    import  maya.cmds  as  mc def   sdksomething( sdk_obj="",                    sdkAttr=" ...

  9. 【模板】字符串匹配的三种做法(Hash、KMP、STL)

    题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 输入输出格式 输入格式: 第一行为一个字符串,即为s1 第二行为一个字符串,即为s2 输出格式: 1行 ...

  10. swiper内容滚动

    <html> <head> <meta charset="UTF-8"> <meta name="viewport" ...