您当前的位置: 首页 >  redis

恐龙弟旺仔

暂无认证

  • 2浏览

    0关注

    282博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Redis内存模型

恐龙弟旺仔 发布时间:2018-02-02 16:45:34 ,浏览量:2

五:理解内存
    1.内存消耗
        1)对象内存
            redis所有数据均采用keyValue数据类型,每次创建键值对时,至少创建两个类型对象:key对象和value对象,对象内存=sizeof(keys)+sizeof(values)
            key对象均为字符串,value对象包括:string、hash、list、set、zset。每种value对象类型根据使用规模不同,占用内存不同
        2)缓冲内存
            主要包括:客户端缓冲、复制挤压缓冲、AOF缓冲
            * 客户端缓冲(所有接入到redis服务器TCP连接的输入输出缓冲区。输入缓冲无法控制,最大为1G,超过将断开连接;输出缓冲通过参数client-output-buffer-limit控制,具体值如下:)
        3)内存碎片
            redis默认的内存分配器是 jemalloc,可选的分配器还有:glibc、tcmalloc
            内存分配器为了更好的管理和重复利用内存,分配内存策略一般采用固定范围的内存块进行分配。
            jemalloc在64位操作系统中将内存空间划分为:小、大、巨大三个范围,每个范围又划分多个小的内存块单位
            * 小:[8byte][16byte][32byte]...
            * 大:[4KB] [8KB][12KB]...
            * 巨:[4MB][8MB][12MB]...
            例:当保存5KB的对象时,会采用8KB的块存储,而剩下的3KB空间就成了空间碎片而不能再分配给其他对象
            易出现碎片的场景:
            * 频繁做更新操作 (例如对已存在的key频繁做append操作)
            * 大量过期键删除 (键对象删除后,释放的空间无法得到充分利用)
            碎片空间解决方案:
            * 数据对齐 (数据计量采用数字类型或者固定长度字符串)
            * 安全重启 (重启节点可以将内存碎片重新整理)
         4)子进程内存消耗
            主要是指执行AOF/RDB重写时redis创建的子进程内存消耗。
            redis执行fork操作产生的子进程内存占用量对外表现为与父进程相同,理论上需要一倍的物理内存来完成重写操作。但linux的写时复制技术,父子进程会共享相同的物理内存页
            子进程内存消耗总结:
            * redis产生的子进程并不需要消耗1倍的父进程内存,实际消耗根据期间写入命令量来决定,但是依然需要预留出一些内存防止溢出
            * 需要设置sysct1 vm.overcommit_memrory=1 允许内核可以分配所有的物理内存,防止redis执行fork时因系统剩余内存不足而失败
            * 排查当前系统是否支持并开启THP,如果开启建议关闭            
    2.内存管理
        redis主要通过控制内存上线和回收策略实现内存管理
          1)设置内存上限
            * 设置configure 设置redis.conf里的maxmemory
            * 动态设置 config set maxmemory xxGB
    
        2)内存回收策略
            * 删除过期key对象
            * 内存溢出控制策略删除key对象
            内存溢出控制策略如下:
            可以在redis.conf中设置,也可以使用 config set maxmemory-policy {policy}来设置
    3.内存优化
        1)redisObject
            redis存储的所有值对象在内部定义为redisObject,该值对象具体属性有:
            降低redis内存最直接的方式就是:缩减key和value的长度       
2)缩减键值对象
            尽量去掉不必要的属性字段
        3)共享对象池
            redis内部维护[0-9999]的整数对象池,当value属于这个值范围,可以使用使用对象池中的数据。
        4)字符串优化
            * 字符串结构:redis自实现了字符串结构,包括三个属性(int len:已用字节长度 int free:未用字节长度 char buf[]:字节数组)
            * 特点:O(1)时间复杂度;可用于保存字节数组,支持安全的二进制数据存储; 内部实现空间预分配机制,降低内存再分配次数;惰性删除,字符串缩减后的空间不释放,作为预分配空间保留
            * 预分配机制:由于存在预分配,数据大量追加后会造成内存碎片率上升
            * 字符串重构:json这样的数据可以考虑使用hash来存储
        5)编码优化
            控制编码类型,多用具有压缩功能的编码类型
        6)控制键的数量
            不要把redis当做单纯的key-value来使用,适当的可以考虑使用其他类型来存储,控制键的数量,降低内存使用
关注
打赏
1655041699
查看更多评论
立即登录/注册

微信扫码登录

0.0926s