如何合理的使用redis内存

实验室清洁工 实验室清洁工     2022-11-30     444

关键词:

简述

众所周知,Redis 的性能之所以高,原因之一就是它的数据都存储在内存中,硬件服务器的内存资源相比于磁盘来说,还是比较昂贵,在成本与性能中我们该如何去权衡,那在使用 Redis 时,如何做到保证良好的性能并更节省内存呢?

内存模型

模型简介

Redis的数据存储,主要涉及到内存分配器(默认jemalloc),简单动态字符串(SDS),5种数据对象类型(字符串、哈希,列表,集合,有序集合),内部编码,redisobject,下面以set hello word操作,写入一条数据为例,做个简单的分析:

如何合理的使用Redis内存_redis

  • dictEntry:每个键值对都会有一个dictEntry结构体,里面存储了指向Key和Value的指针;next指向下一个dictEntry,与本Key-Value无关。
  • Key:Key ”hello” 并不是直接以字符串存储,而是存储在SDS结构中。
  • redisObject:Value 值“world”不是直接以字符串存储,是存储在redisObject中。我们常说的物种数据类型也都是都是通过redisObject来存储的;而redisObject中的type字段指明了Value对象的类型,ptr字段则指向对象所在的地址。不过可以看出,字符串对象虽然经过了redisObject的包装,但仍然需要通过SDS存储。
  • SDS:Redis没有直接使用C字符串(即以空字符’\\0’结尾的字符数组)作为默认的字符串表示,而是使用了SDS。SDS是简单动态字符串(Simple Dynamic String)的缩写。
  • Jemalloc:无论是DictEntry对象,还是redisObject、SDS对象,都需要内存分配器(如jemalloc)分配内存进行存储。以DictEntry对象为例,有3个指针组成,在64位机器下占24个字节,jemalloc会为它分配32字节大小的内存单元。

数据占用

jemalloc内存分配情况如下,在分配内存块时会分配大于实际值的2次n的值

数据类型

占用量

dictEntry

24字节,jemalloc会分配32字节的内存块

redisObject

16字节

key

key的长度+9,jemalloc分配>=该值的2n的值

value

value的长度+9,jemalloc分配>=该值的2n的值

key的个数

所有key的个数

bucket个数

大于key的个数的2n次方,例如key个数是2000,那么bucket=2048

指针大小

8byte

String

一个set命令会产生一下几个内存消耗的结构:

  • 1个dictEntry结构,24字节,负责保存当前的哈希对象;
  • 1个SDS结构,(key长度 + 9)字节,用作key字符串;
  • 1个SDS结构,(val长度 + 9)字节,用作key的values;
  • 1个redisObject结构,16字节,指向当前key下属的dict结构;
Hash

Hash结构在使用HTable数据类型时,value并不是指向一个SDS,是有一个Dict结构。Dict结构保存了Hash对象的键值对。一个hmset命令最终会产生以下几个消耗内存的结构:

如何合理的使用Redis内存_内存_02

  • 1个dictEntry结构,24字节,负责保存当前的哈希对象;
  • 1个SDS结构,(key长度 + 9)字节,用作key字符串;
  • 1个redisObject结构,16字节,指向当前key下属的dict结构;
  • 1个dict结构,88字节,负责保存哈希对象的键值对;
  • n个dictEntry结构,24×n字节,负责保存具体的field和value,n等于field个数;
  • n个redisObject结构,16×n字节,用作field对象;
  • n个redisObject结构,16×n字节,用作value对象;
  • n个SDS结构,(field长度 + 9)× n字节,用作field字符串;
  • n个SDS结构,(value长度 + 9)× n字节,用作value字符串;
SortedSet

一个zadd命令最终会产生以下几个消耗内存的结构:

如何合理的使用Redis内存_redis_03

  • 1个dictEntry结构,24字节,负责保存当前的有序集合对象;
  • 1个SDS结构,(key长度 + 9)字节,用作key字符串;
  • 1个redisObject结构,16字节,指向当前key下属的zset结构;
  • 1个zset结构,16字节,负责保存下属的dict和zskiplist结构;
  • 1个dict结构,88字节,负责保存集合元素中成员到分值的映射;
  • n个dictEntry结构,24×n字节,负责保存具体的成员和分值,n等于集合成员个数;
  • 1个zskiplist结构,32字节,负责保存跳跃表的相关信息;
  • 1个32层的zskiplistNode结构,24+16×32=536字节,用作跳跃表头结点;
  • n个zskiplistNode结构,(24+16×m)×n字节,用作跳跃表节点,m等于节点层数;
  • n个redisObject结构,16×n字节,用作集合中的成员对象;
  • n个SDS结构,(value长度 + 9)×n字节,用作成员字符串;
List

一个rpush或者lpush命令最终会产生以下几个消耗内存的结构:

如何合理的使用Redis内存_合理_04

  • 1个dictEntry结构,24字节,负责保存当前的列表对象;
  • 1个SDS结构,(key长度 + 9)字节,用作key字符串;
  • 1个redisObject结构,16字节,指向当前key下属的list结构;
  • 1个list结构,48字节,负责管理链表节点;
  • n个listNode结构,24×n字节,n等于value个数;
  • n个redisObject结构,16×n字节,用作链表中的值对象;
  • n个SDS结构,(value长度 + 9)×n字节,用作值对象指向的字符串;

优化建议

合理的控制 key 的长度

在研发业务时,需要保证 key 在简单、清晰的前提下,尽可能把 key 定义得简短一些。随着key的数量级越大,Redis 就可以节省的内存越多

利用jemalloc特性进行优化

jemalloc分配内存时数值是不连续的,因此key/value字符串变化一个字节,可能会引起占用内存很大的变动;在设计时可以利用这一点。如果key的长度如果是8个字节,则SDS为17字节,jemalloc分配32字节;此时将key长度缩减为7个字节,则SDS为16字节,jemalloc分配16字节;则每个key所占用的空间都可以缩小一半。

选择合适的数据类型

String、Set 在存储 int 数据时,会采用整数编码存储。Hash、ZSet 在元素数量比较少时(可配置),会采用压缩列表(ziplist)存储,在存储比较多的数据时,才会转换为哈希表和跳表。可以节省更多空间。因此在可以使用长整型/整型代替字符串的场景下,尽量使用长整型/整型。

避免存储 bigkey

bigkey不仅会占用过多的内存,还会客户端在读书数据时,容易导致阻塞,造成性能瓶颈,对于bigkey,建议进行拆分,建议如下:

  • String:大小控制在 10KB 以下
  • List/Hash/Set/ZSet:元素数量控制在 1 万以下

把 Redis 当作缓存使用

你在使用 Redis 时,

  • 尽可能要把它当做缓存来使用,而不是持久化的数据,不然也会存在数据风险,在写入数据时,尽可能的设置过期时间,业务应用在redis查不多数据时,应从后端数据库查询并加载到redis中。
  • 尽可能的存放一些热点数据,对于不常用的数据,可以查询其他路径获取,如从对象型数据库中获取。

设置最大内存和合理的淘汰策略

Redis key 设置合理的过期时间,如果你的业务应用写入量很大,有了合理的过期时间,会将对应的数据过期掉,也可以抑制内存的快读增长

数据压缩后写入 Redis

开发在研发应用时,可以先将数据进行压缩,压缩后再写入redis,当然这会增加应用开发的复杂度和消耗过多的客户端cpu资源,需要结合业务特性进行权限 务应用中先将数据压缩,再写入到 Redis 中(例如采用 snappy、gzip 等压缩算法)。

监控内存碎片率

内存碎片率是一个重要的参数mem_fragmentation_ratio=used_memory_rss/used_memory

  • 如果内存碎片率过高(jemalloc 在 1.03 左右比较正常),说明内存碎片多,内存浪费严重。并可考虑堆Redis数据库进行切换,重启,在内存中对数据进行重排,减少内存碎片。
  • 如果内存碎片率小于 1,说明 Redis 内存不足,部分数据使用了虚拟内存(即 swap)。由于虚拟内存的存取速度比物理内存差很多(2-3 个数量级),此时 Redis 的访问速度可能会变得很慢。

深入学习redis:redis内存模型(代码片段)

...型(以3.0为例),包括Redis占用内存的情况及如何查询、不同的对 查看详情

写代码如何合理使用和优化我们的机器资源(cpu内存网络磁盘)

写代码脑子一定要绷紧一根弦,认知到我们所在的机器资源是有限的。机器资源有哪些?CPU、内存、网络、磁盘等,如果不做好保护控制工作,一旦某一资源满负荷,很容易导致出现线上问题。1CPU资源怎么限制* 计算算法优... 查看详情

redis——内存淘汰策略

...在内存中一直存在,直到我们明确删除它。3、过度或不合理的持久化无论RDB快照或者AOF日志,都会在内存和磁盘中反复操作,需要一定的内存空间。4、不及时清理过期缓存有时过期缓存依旧存在,主要和缓存清理方式有关:主... 查看详情

如何停止 redis 内存使用量随着连接数的增加而增加

】如何停止redis内存使用量随着连接数的增加而增加【英文标题】:HowcanIstopredismemoryusageincreasingwithconnectioncount【发布时间】:2020-11-0320:40:22【问题描述】:我们在AWS上通过elasticache运行redis,并且在运行大量刚读取的lambda函数时... 查看详情

redis一些问题

...高效支持fork操作的虚拟化技术控制Redis实际最大可用内存合理配置Linux内存分配策略vm.overcommit_memory=1默认这个值为 查看详情

源码讲解redis中内存优化的数据结构是如何设计的(代码片段)

...串ziplist设计intset设计共享对象Redis作为内存数据库,如何高效地使用内存非常重要。为了提升内存的使用率,主要采取数据结构优化设计及使用以及内存数据按照规则淘汰。内存数据按照淘汰规则主要通过Redis的内存替换... 查看详情

你如何使用 redis-benchmark 工具来填满一个 redis 集群内存?

】你如何使用redis-benchmark工具来填满一个redis集群内存?【英文标题】:Howdoyouuseredis-benchmarkutiltofilluparedisclustermemory?【发布时间】:2021-12-2219:43:00【问题描述】:所以基本上我在AWS(Elasticache集群模式)中部署了一个redis集群,... 查看详情

理解redis的内存(代码片段)

...感觉我都可以买个1T的硬盘了。。。这就是差距。so,如何合理高效的利用Redis内存就变得非常的重要了。首先我们应该知道Redis的内存主要消耗在什么地方,其次是如何管理内存,最后才是怎么做Redis的内存优化。这... 查看详情

如何合理地给windows系统加虚拟内存

背景介绍事情是这样子的,我目前使用的windows电脑很卡,然后C盘容量只有10个G左右空余,这是我不能忍受的。问题定位我瞄了下C盘中有一个pagefile.sys文件大概有十几个G,然后C盘又是运行的系统盘,所以容量不够的话自然是会... 查看详情

redis的主要功能

...这应该是Redis最主要的功能了,也是大型网站必备机制,合理地使用缓存不仅可以加快数据的访问速度,而且能够有效地降低后端数据源的压力。共享Session:对于一些依赖session功能的服务来说,如果需要从单机变成集群的话,... 查看详情

redis内存使用优化与存储

...型之前,我们先通过一张图了解下Redis内部内存管理中是如何描述这些不同数据类型的:  首先Redis内部使用一个redisObject对象来表示所有的key和value,redisObject最主要的信息如上图所示:type代表一个value对象具体是何种数据... 查看详情

redis过期删除策略和内存淘汰策略(代码片段)

...试题二、Redis内存满了怎么办2.1结论三、redis里写的数据如何删除的?3.1三种不同的删除策略3.1.1立即删除3.1.2惰性删除3.1.3定期删除3.3.4总结四、redis缓存淘汰策略4.1有哪些4.2你平时用哪一种五、总结一、面试题生产上你们你... 查看详情

linksla智能运维技术派-redis的监控

...令数:ops网络流量正常情况下,redis连接客户端的数量会有合理的上限和下限。如果它太低,则上游连接可能已丢失;如果它太高,则大量并发客户端连接可能会使服务器处理请求的能力超过上限,我们可以配置异常检测算法来监... 查看详情

asp.netcore中如何使用缓存(代码片段)

...非常多,也很多编程平台都将其作为分布式缓存的首选。如何安装Redis:方式一:Chocolatey是Windows平台下一款优秀的软件包管理工具(类似于NPM),该工具安装教程:ChocolateySoftware|InstallingChocolatey。最简单的安装Redis的方法就是使... 查看详情

redis异常记录

...索来进行排查;原因可能是value过大,key数量过多或长度不合理,触发redis慢操作的指令很多,内存不够等等MISCONFRedisisConfiguredtosaveRDBsnapshots,butiscurrentlynotabletopersistondisk.Commandsthatmaymodifythedatasetaredisable.PleaseCheckredislogsfordetailabouttheerrorca... 查看详情

redis中的数据占用内存大小分析

...redis服务器规格,以及对于是否需要进行程序优化来设计合理的存储结构都会有很大帮助,下面给大家介绍两款工具rdr和redis-rdb-tools,可以很好的满足我们的需要详细使用参考官方仓库:https://github.com/xueqiu/rdrrdr提供了linux/OSX/Wind... 查看详情

win7系统如何高效使用内存

...拟内存中(其实在硬盘上),而不会使物理内存使用殆尽。如何正确设置虚拟内存?  经验二、学会监视内存  高效的使用内存还需要学会监视内存的使用量,在Windows7系统中提供了强大的任务管理器,你可以在任务管理器中的... 查看详情

面试题1:redis的内存淘汰机制

...内存是有限的,但是如果当redis的内存使用超过上限,该如何定制淘汰算法?   当redis内存已经满了,下一条数据进来该怎么办?题目分析   首先我们应该先明确此题的主要考察点是redis的内存淘汰机制。我... 查看详情