Redis 内存优化方式

内存优化方式与参数

关闭 Redis 的虚拟内存[VM]功能,即 redis.conf 中 vm-enabled = no
设置 redis.conf 中 maxmemory ,用于告知 Redis 当使用了多少物理内存后拒绝继续写入的请求,可防止 Redis 性能降低甚至崩溃
可为指定的数据类型设置内存使用规则,从而提高对应数据类型的内存使用效率
Hash 在 redis.conf 中有以下两个属性,任意一个超出设定值,则会使用 HashMap 存值
hash-max-zipmap-entires 64 表示当 value 中的 map 数量在 64 个以下时,实际使用 zipmap 存储值
hash-max-zipmap-value 512 表示当 value 中的 map 每个成员值长度小于 512 字节时,实际使用 zipmap 存储值
List 在 redis.conf 中也有以下两个属性
list-max-ziplist-entires 64
list-max-ziplist-value 512
在 Redis 的源代码中有一行宏定义 REDIS-SHARED-INTEGERS = 10000 ,修改该值可以改变 Redis 存储数值类型的内存开销

------------转载------------------------------------

业务场景:Redis 作为目前主流的key-value 内存数据库,因为其高并发,存储查询速率快,我们很多的热点数据均会存储到Redis 中,如果数据量较大的话,昂贵的内存消耗也是一笔很大的支出,因此Redis 内存优化是很有必要的。

以下是笔者所在公司的Redis 服务的内存使用情况

上图可以看到:Redis内部的对象数高达:1,599,098,020(15亿),其内存使用高达 371G ,并且持续的增多,需要我们尽快优化,释放多余的空间。

目前存储的现状
  • 目前Redis 存储使用的数据类型为:string
  • key 的构成为: type:business_tag:user_id:item_id:item_detail_id
  • value 的组成为:
  {
    "expireTime": "253402271999000",
    "value": "test_test_test_test"
  }
主要优化手段如下
  • 存储结构变更 由string 变更为 hash

主要内存优化依据是:
Redis 内部Hash 数据结构的编码方式主要有两种:

  • OBJ_ENCODING_ZIPLIST(压缩列表)
  • OBJ_ENCODING_HT(哈希表)

Redis 内部会根据数量的情况自适应的选择这两种编码方式中 最优 的一种,这种操作完全对用户透明,选择压缩列表存储的依据主要是:

  • 数据条目较少(hash-max-ziplist-entries)即 Hash 的filed 较少 field 个数 默认小于 512
  • 数据值较少(hash-max-ziplist-value)即Hash的value 值较少 value 值的长度小于64

即默认存储为压缩列表存储的条件为

field_num < hash-max-ziplist-entries && value.length < hash-max-ziplist-value

综上所述:根据前面看到的业务场景,完全满足此种场景,这是选择由string存储变为 Hash存储的一个原因

OBJ_ENCODING_ZIPLIST 编码的主要思想是:空间换时间,适应于字段个数比较少,字段值也比较小的场景。
  • key的优化

为了全方位的对内存进行优化,那么key 以及 hash 的field 进行必要的压缩

  • 如果是字符串的话可以进行分段优化,针对数据进行16进制转换
  • 字符串使用简写方式

迁移后Redis 实例存储对比

为保证测试的准确性,私有服务器安装Redis 进行优化前与优化后内存空间测试
以下为整个测试过程:

  • docker 安装 Redis
docker pull redis

docker ps # 查询当前容器

docker exec -it ****** /bin/bash # 进入容器内部
redis-cli -a 123456 #打开Redis-cli连接Redis
info memory  # 查询安装完成后Redis 的内存使用情况

以上为Redis 服务搭建过程的简单记录

  • 数据存储测试(未优化前)

优化前 存储 1000000 string 类型数据如下:

-- string key
0:1:201155:100:545953888100
-- string value
{
  "value": "3.6230093077568726-0.3630194103106919100",
  "expireTime": "2147483647"
}


由上图内存存储可知:未优化前 1000000 条 string 消耗内存:200.12M
执行完测试,将此前存入的数据删除

  • (1)数据存储测试(优化key value)

    • 压缩key的长度:将最后的无业务标识的字符串转换为:16进制
    • 压缩value 的长度:压缩value的数据


优化后 存储1000000数据使用内存:139.10M 相比较优化前优化内存:30%
偷偷窃喜下,如果进行此次优化:节省内存:115G

  • (2)数据存储测试(优化key value)

    • 压缩key的长度:将最后的无业务标识的字符串转换为:64 进制
    • 压缩value 的长度:压缩value的数据


此次优化变化不明显,仅仅降低了 不到1M ,疑惑脸。。。
于是乎对于key的长度不进行压缩,只对value值进行压缩进行测试结果如下:


由以上测试可得:1000000数据,内存使用率为 146.59M ,故此 16/64 进制对key的压缩影响并不明显。

  • (3)数据存储测试(优化key value)

    • 压缩key的长度:将最后的无业务标识的字符串转换为:64 进制
    • 压缩value 的长度:压缩value的数据,不在存储json,只存储,attr1:value,attr2:value2

以上优化后,存储1000000数据使用内存:123.86M,优化达到:38%

  • (4)数据存储测试(优化key value)

    • 压缩key的长度:将最后的无业务标识的字符串转换为:64 进制
    • 压缩value 的长度:压缩value的数据,不在存储json,只存储,attr1:value


经过第4次进行优化,内存的占用依旧与第三次相差很小,但是仍然在减少,此次内存占用为 123.71M,继续对value值做压缩

  • (5)数据存储测试(优化key value)

    • 压缩key的长度:将最后的无业务标识的字符串转换为:64 进制
    • 压缩value 的长度:压缩value的数据,只存储,attr1:value, exp(过期时间戳)压缩为64进制


经过第5次进行优化,内存占用达到了 116.27M ,优化达到:42%

  • 数据存储测试(优化key value的基础上进行 数据结构变更:变更为HASH)

见证奇迹的时刻到了,变更HASH 结构后,1000000数据内存占用 100.49M,优化50%

思考:

Redis 的内存优化,需要配合业务场景进行针对性的优化,并不是一味的已减少内存为主要的优化目标,我们也应该在空间和时间上找到一个平衡点进行恰当的优化,就那此次优化来说,虽然内存减少了 50% ,但是在实际应用中考虑到,该数据对于效率要求比较高,所以在进行编码解码过程中也存在时间的消耗,最终并不是采用内存优化度最大的那种方案。

原文地址:https://www.cnblogs.com/weigy/p/12677458.html

时间: 2024-11-06 07:23:15

Redis 内存优化方式的相关文章

如何用分布式缓存服务实现Redis内存优化

Redis是一种支持Key-Value等多种数据结构的存储系统,其数据特性是"ALL IN MEMORY",因此优化内存十分重要.在对Redis进行内存优化时,先要掌握Redis内存存储的特性比如字符串,压缩编码,整数集合等,再根据数据规模和所用命令需求去调整,从而达到空间和效率的最佳平衡. 但随着数据大幅增长,开发人员需要面对重新优化内存所带来开发和数据迁移的双重成本也越来越高.Redis所有的数据都在内存中,那么,我们是否可以通过简便高效的方式去实现Redis内存优化呢? 答案当然

redis内存优化、持久化以及主从复制

Redis 数据库内存优化参数的配置,每种持久化方式的利与弊以及主从复制的原理以及配置 一.常用内存优化手段与参数 redis的性能如何是完全依赖于内存的,所以我们需要知道如何来控制和节省内存. 首先最重要的一点是不要开启Redis的VM选项,即虚拟内存功能,这个本来是作为Redis存储超出物理内存数据的一种数据在内存与磁盘换入换出的一个持久化策略,但是其内存管理成本非常的高,所以要关闭VM功能,请检查你的redis.conf文件中 vm-enabled 为 no. 其次最好设置下redis.c

redis 内存优化

最近做的一个系统大量使用redis,我们将大量的用户信息存放在redis中,内存一申请就是几百G,体量也是相当庞大.所以我们也在不断的想方法优化减少redis的内存使用,把我们的优化实践也分享出来. 采用Hash代替<K,V>键值对存储 因为是存放用户维度的数据,用户id(uid)往往会作为key,而一个用户会有多个信息,比如年龄,生日等等,比较容易想到的存储结构会采用Hash,将一个用户的多个信息作为hash里的不同field来存放 善用Hash,List,ZSet的ziplist压缩特性

最常见的Android内存优化方式及防止泄漏造成OOM总结篇

前言 内存优化目的就是让我们在开发中怎么有效的避免我们的应用出现内存泄漏的问题.内存泄漏大家都不陌生了,简单粗俗的讲,就是该被释放的对象没有释放,一直被某个或某些实例所持有却不再被使用导致 GC 不能回收.既然说到内存泄漏和优化,就不得不先简单了解一下内存分配策略,然后再举常见泄漏例子和解决方法,最后做一下总结,这样更直观全面了解Android内存方面处理. 内存分配 内存分配策略有三种,分别是静态.栈式和堆式.对应的的内存空间主要分别是静态存储区(也称方法区).栈区和堆区.如下: 静态存储区:

redis内存优化方法

先来认识2个redis配置参数 hash-max-ziplist-entries : hash内部编码压缩列表的最大值,默认512 hash-max-zipmap-value : hash内部编码压缩列表单个key的最大值,默认64字节. 这是hash的配置,list,set,zset也有类似的配置参数. 先说结论:总结redis节约内存的方法. 1,使用对象共享池优化小整数对象. 2,数据优先使用整数,比字符串更节省空间. 3,操作优化.尽量避免字符串的追加操作,因为字符串存在预分配机制.追加

redis的内存优化【转】

Redis所有的数据都在内存中,而内存又是非常宝贵的资源.对于如何优化内存使用一直是Redis用户非常关注的问题.本文让我们深入到Redis细节中,学习内存优化的技巧.分为如下几个部分: 一.redisObject对象 二.缩减键值对象 三.共享对象池 四.字符串优化 五.编码优化 六.控制key的数量 一. redisObject对象 Redis存储的所有值对象在内部定义为redisObject结构体,内部结构如下图所示. Redis存储的数据都使用redisObject来封装,包括strin

Redis系列--内存淘汰机制(含单机版内存优化建议)

https://blog.csdn.net/Jack__Frost/article/details/72478400?locationNum=13&fps=1 每台redis的服务器的内存都是有限的,而且也不是所有的内存都用来存储信息.而且redis的实现并没有在内存这块做太多的优化,所以实现者为了防止内存过于饱和,采取了一些措施来管控内存. 文章结构:(1)内存策略:(2)内存释放机制原理:(3)项目中如何合理应用淘汰策略:(4)单机版Redis内存优化注意点. 一.内存策略:先来吃份官方文档

redis 如何做内存优化?

edis所有的数据都在内存中,而内存又是非常宝贵的资源.对于如何优化内存使用一直是Redis用户非常关注的问题.本文让我们深入到Redis细节中,学习内存优化的技巧.分为如下几个部分: 一.redisObject对象 二.缩减键值对象 三.共享对象池 四.字符串优化 五.编码优化 六.控制key的数量 一. redisObject对象 Redis存储的所有值对象在内部定义为redisObject结构体,内部结构如下图所示. Redis存储的数据都使用redisObject来封装,包括string

redis参数优化

redis内存管理方式,支持tcmalloc,jemalloc,malloc三种内存分配,memcache使用slabs,malloc等内存分配方式. 简单点,就是redis,是边用边申请,使用现场申请内存的方式来存储数据,并且很少使用free-list等方式来优化内存分配: memcache使用预分配的内存池的方式,使用slab和大小不同的chunk来管理内存,Item根据大小选择合适的chunk存储,内存池的方式可以省去申请/释放内存的开销 优化的参数: 1.设置下redis.conf中的m