浅谈redis key值内存消耗以及性能影响

一、redis key数量为1千万时。

存储value为"0",比较小。如果value较大,则存储内存会增多

redis key数量为一千万时,使用了865M的内存。

# Keyspace
db0:keys=11100111,expires=0,avg_ttl=0
内存使用情况
# Memory
used_memory:907730088
used_memory_human:865.68M
used_memory_rss:979476480
used_memory_rss_human:934.10M
used_memory_peak:1258244232
used_memory_peak_human:1.17G
used_memory_peak_perc:72.14%
used_memory_overhead:580102896
used_memory_startup:765664
used_memory_dataset:327627192
used_memory_dataset_perc:36.12%
total_system_memory:8365256704
total_system_memory_human:7.79G
used_memory_lua:37888
used_memory_lua_human:37.00K

二、redis key数量为1千5百万时。

redis key数量为一千五百万时,使用了1.13G的内存。

# Keyspace
db0:keys=15100031,expires=0,avg_ttl=0
# Memory
used_memory:1211733288
used_memory_human:1.13G
used_memory_rss:1247817728
used_memory_rss_human:1.16G
used_memory_peak:1258244232
used_memory_peak_human:1.17G
used_memory_peak_perc:96.30%
used_memory_overhead:740104496
used_memory_startup:765664
used_memory_dataset:471628792
used_memory_dataset_perc:38.95%
total_system_memory:8365256704
total_system_memory_human:7.79G
used_memory_lua:37888
used_memory_lua_human:37.00K

三、redis key数量为一千五百万时压测

redis-benchmark -h 127.0.0.1 -p 6379 -c 1000 -n 10000 -t get -q
GET: 34364.26 requests per second

四、使用map将key值打散存储,小key为1千五百万

使用hset存储打散为1024个key时,存储大小为921M,比直接存储节省了200M。

# Memory
used_memory:966758968
used_memory_human:921.97M
used_memory_rss:1002913792
used_memory_rss_human:956.45M
used_memory_peak:1749456304
used_memory_peak_human:1.63G
used_memory_peak_perc:55.26%
used_memory_overhead:1929880
used_memory_startup:765664
used_memory_dataset:964829088
used_memory_dataset_perc:99.88%
total_system_memory:8365256704
total_system_memory_human:7.79G
used_memory_lua:37888
used_memory_lua_human:37.00K
# Keyspace
db0:keys=1024,expires=0,avg_ttl=0

五、使用hset存储打散为256个key

存储大小为1.09G,比直接存储小了80M。

used_memory:1170356864
used_memory_human:1.09G
used_memory_rss:1190223872
used_memory_rss_human:1.11G
used_memory_peak:1749456304
used_memory_peak_human:1.63G
used_memory_peak_perc:66.90%
used_memory_overhead:33759246
used_memory_startup:765664
used_memory_dataset:1136597618
used_memory_dataset_perc:97.18%
total_system_memory:8365256704
total_system_memory_human:7.79G

六、进行hget的压力测试

 redis-benchmark -h 127.0.0.1 -p 6379 -c 1000 -n 10000 -t hget myhash rand_int rand_int rand_int
====== myhash rand_int rand_int rand_int ======
 10000 requests completed in 0.22 seconds
 1000 parallel clients
 3 bytes payload
 keep alive: 1
46511.63 requests per second

七、总结

可见,当存储量特别大的时候,可以将key进行hash分散处理,可以减少存储内存。

并且当key的数量很大的时候,redis取值性能还是很高的。

补充:Redis 单key值过大 优化方式

Redis使用过程中经常会有各种大key的情况, 比如:

1: 单个简单的key存储的value很大

2: hash, set,zset,list 中存储过多的元素(以万为单位)

由于redis是单线程运行的,如果一次操作的value很大会对整个redis的响应时间造成负面影响,所以,业务上能拆则拆,下面举几个典型的分拆方案。

1、单个简单的key存储的value很大

1.1、 改对象需要每次都整存整取

可以尝试将对象分拆成几个key-value, 使用multiGet获取值,这样分拆的意义在于分拆单次操作的压力,将操作压力平摊到多个redis实例中,降低对单个redis的IO影响;

1.2、该对象每次只需要存取部分数据

可以像第一种做法一样,分拆成几个key-value, 也可以将这个存储在一个hash中,每个field代表一个具体的属性,使用hget,hmget来获取部分的value,使用hset,hmset来更新部分属性

2、 hash, set,zset,list 中存储过多的元素

类似于场景一种的第一个做法,可以将这些元素分拆。

以hash为例,原先的正常存取流程是 hget(hashKey, field) ; hset(hashKey, field, value)

现在,固定一个桶的数量,比如 10000, 每次存取的时候,先在本地计算field的hash值,模除 10000, 确定了该field落在哪个key上。

newHashKey = hashKey + (*hash*(field) % 10000);
hset (newHashKey, field, value) ;
hget(newHashKey, field)

set, zset, list 也可以类似上述做法.

但有些不适合的场景,比如,要保证 lpop 的数据的确是最早push到list中去的,这个就需要一些附加的属性,或者是在 key的拼接上做一些工作(比如list按照时间来分拆)。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。如有错误或未考虑完全的地方,望不吝赐教。

(0)

相关推荐

  • 基于redis key占用内存量分析

    Redis的指令看不出哪一类型的key,占用了多少内存,不好分析redis内存开销大的情况下,各应用程序使用缓存的占比. 借助第3方工具进行分析 1.采用2个工具结合 redis-rdb-tools+sqlite 2.sqlite linux服务器都会自带,安装redis-rdb-tools 使用pip安装 pip install redis-rdb-tools 源码安装 git clone https://github.com/sripathikrishnan/redis-rdb-tools

  • 浅谈Redis的key和value大小限制

    今天研究了下将java bean序列化到redis中存储起来,突然脑袋灵光一闪,对象大小会不会超过redis限制?不管怎么着,还是搞清楚一下比较好,所以就去问了下百度,果然没多少人关心这个问题,没找到比较合适的答案,所以决定还是去官网找吧. 找到两句比较关键的话, 截图如下. 结论 redis的key和string类型value限制均为512MB. 补充知识:Redis获取所有键值 通过遍历获取目标键值: import redis redis = redis.Redis(host='192.24

  • Redis的KEYS 命令千万不能乱用

    KESY 命令 时间复杂度: O(N) , 假设Redis中的键名和给定的模式的长度有限的情况下,N为数据库中key的个数. Redis Keys 命令用于查找所有符合给定模式 pattern 的 key 尽管这个操作的时间复杂度是 O(N), 但是常量时间相当低.例如,在一个普通笔记本上跑Redis,扫描100万个key只要40毫秒. 命令格式 KEYS pattern Warning: 生产环境使用 KEYS 命令需要非常小心.在大的数据库上执行命令会影响性能.这个命令适合用来调试和特殊操作

  • 浅谈redis key值内存消耗以及性能影响

    一.redis key数量为1千万时. 存储value为"0",比较小.如果value较大,则存储内存会增多 redis key数量为一千万时,使用了865M的内存. # Keyspace db0:keys=11100111,expires=0,avg_ttl=0 内存使用情况 # Memory used_memory:907730088 used_memory_human:865.68M used_memory_rss:979476480 used_memory_rss_human:

  • 浅谈redis采用不同内存分配器tcmalloc和jemalloc

    我们知道Redis并没有自己实现内存池,没有在标准的系统内存分配器上再加上自己的东西.所以系统内存分配器的性能及碎片率会对Redis造成一些性能上的影响. 在Redis的 zmalloc.c 源码中,我们可以看到如下代码: /* Double expansion needed for stringification of macro values. */ #define __xstr(s) __str(s) #define __str(s) #s #if defined(USE_TCMALLOC

  • 浅谈Redis中的内存淘汰策略和过期键删除策略

    目录 8种淘汰策略 过期键的删除策略 总结 redis是我们现在最常用的一个工具,帮助我们建设系统的高可用,高性能. 而且我们都知道redis是一个完全基于内存的工具,这也是redis速度快的一个原因,当我们往redis中不断缓存数据的时候,其内存总有满的时候(而且内存是很贵的东西,尽量省着点用),所以尽可能把有用的数据,或者使用频繁的数据缓存在redis中,物尽其用. 那么如果正在使用的redis内存用完了,我们应该怎么取舍redis中已存在的数据和即将要存入的数据呢,我们要怎么处理呢? re

  • 浅谈Redis 中的过期删除策略和内存淘汰机制

    目录 前言 Redis 中 key 的过期删除策略 1.定时删除 2.惰性删除 3.定期删除 Redis 中过期删除策略 从库是否会脏读主库创建的过期键 内存淘汰机制 内存淘汰触发的最大内存 有哪些内存淘汰策略 内存淘汰算法 LRU LFU 为什么数据删除后内存占用还是很高 内存碎片如何产生 碎片率的意义 如何清理内存碎片 总结 参考 前言 Redis 中的 key 设置一个过期时间,在过期时间到的时候,Redis 是如何清除这个 key 的呢? 这来分析下 Redis 中的过期删除策略和内存淘

  • 浅谈Redis 中的过期删除策略和内存淘汰机制

    目录 前言 Redis 中 key 的过期删除策略 1.定时删除 2.惰性删除 3.定期删除 Redis 中过期删除策略 从库是否会脏读主库创建的过期键 内存淘汰机制 内存淘汰触发的最大内存 有哪些内存淘汰策略 内存淘汰算法 LRU LFU 为什么数据删除后内存占用还是很高 内存碎片如何产生 碎片率的意义 如何清理内存碎片 总结 参考 前言 Redis 中的 key 设置一个过期时间,在过期时间到的时候,Redis 是如何清除这个 key 的呢? 这来分析下 Redis 中的过期删除策略和内存淘

  • 浅谈Redis存储数据类型及存取值方法

    Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合) String存取值: 是 redis 最基本的类型 一个 key 对应一个 value.value其实不仅是String,也可以是数字.string 类型是二进制安全的.意思是 redis 的 string 可以包含任何数据.比如jpg图片或者序列化的对象.string 类型是 Redis 最基本的数据类型,string 类型的值最大能存储 512M

  • 浅谈Redis高并发缓存架构性能优化实战

    目录 场景1: 中小型公司Redis缓存架构以及线上问题实战 场景2: 大厂线上大规模商品缓存数据冷热分离实战 场景3: 基于DCL机制解决热点缓存并发重建问题实战 场景4: 突发性热点缓存重建导致系统压力暴增 场景5: 解决大规模缓存击穿导致线上数据库压力暴增 场景6: 黑客工资导致缓存穿透线上数据库宕机 场景7: 大V直播带货导致线上商品系统崩溃原因分析 场景8: Redis分布式锁解决缓存与数据库双写不一致问题实战 场景9: 大促压力暴增导致分布式锁串行争用问题优化 场景10: 利用多级缓

  • 浅谈Redis的异步机制

    目录 前言 一.Redis 的阻塞点 4 类交互对象和具体的操作之间的关系: 切片集群实例交互时的阻塞点 二.可以异步执行的阻塞点 三.异步的子线程机制 总结 前言 命令操作.系统配置.关键机制.硬件配置等会影响 Redis 的性能,不仅要知道具体的机制,尽可能避免性能异常的情况出现,还要提前准备好应对异常的方案. Redis 内部的阻塞式操作: CPU 核和 NUMA 架构的影响: Redis 关键系统配置: Redis 内存碎片: Redis 缓冲区. 一.Redis 的阻塞点 和 Redi

  • 浅谈Redis变慢的原因及排查方法

    目录 原因1:实例内存达到上限 原因2:开启内存大页 原因3:使用Swap 原因4:网络带宽过载 原因5:其他原因 原因1:实例内存达到上限 排查思路 如果你的 Redis 实例设置了内存上限 maxmemory,那么也有可能导致 Redis 变慢. 当我们把 Redis 当做纯缓存使用时,通常会给这个实例设置一个内存上限 maxmemory,然后设置一个数据淘汰策略.而当实例的内存达到了 maxmemory 后,你可能会发现,在此之后每次写入新数据,操作延迟变大了. 导致变慢的原因 当 Red

随机推荐