Redis中key值内存占用和性能损耗究竟有多大?

2026-04-19 20:053阅读0评论SEO问题
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计970个文字,预计阅读时间需要4分钟。

Redis中key值内存占用和性能损耗究竟有多大?

Redis中,当key的数量达到一千万时,存储value为20的key会占用较少内存。如果value值较大,则存储在内存中的key数量会增加。例如,若value值较大,当key数量达到一千万时,可能需要使用约865MB的内存。

一、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。

Redis中key值内存占用和性能损耗究竟有多大?

# 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按照时间来分拆)。

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

本文共计970个文字,预计阅读时间需要4分钟。

Redis中key值内存占用和性能损耗究竟有多大?

Redis中,当key的数量达到一千万时,存储value为20的key会占用较少内存。如果value值较大,则存储在内存中的key数量会增加。例如,若value值较大,当key数量达到一千万时,可能需要使用约865MB的内存。

一、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。

Redis中key值内存占用和性能损耗究竟有多大?

# 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按照时间来分拆)。

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