Redis 存储结构体信息,选 hash 还是string?

Java技术栈

共 3203字,需浏览 7分钟

 ·

2022-01-09 22:15

点击关注公众号,Java干货及时送达

在讲到使用hash还是string存储的选择前,先了解Redis的hash和string结构。

以下资料引自老钱的Redis深度历险。

string

string和hash都是Redis的一种数据结构。string结构常用来缓存用户信息,通常将用户信息结构体使用JSON序列化成字符串,然后将序列化后的字符串存入Redis进行缓存。

String数据结构

Redis的字符串是动态字符串,可以修改,内部结构类似于Java的ArrayList,采用预分配冗余空间的方式来减少内存的频繁分配。

如上图锁实,内部为当前字符串实际分配的空间capacity,一般高于实际字符串长度len。使用的指令有set, get, mset, mget等

hash

Redis的hash相当于Java的HashMap,内部结构实现与HashMap一致,即数组+链表结构

hash数据结构

不过Redis的hash的值只能是字符串,rehash方式不一样,为了提高性能,Redis保留新旧两个hash结构,采用渐进式rehash策略,查询时会同事查询两个hash结构,在后续的定时任务中以及hash操作指令中,循序渐进将旧hash的内容迁移到xinhash中,直至完全取代旧hash。hash移除最后一个元素后会自动被删除,内存被回收。

前面说到string适合存储用户信息,而hash结构也可以存储用户信息,不过是对每个字段单独存储,因此可以在查询时获取部分字段的信息,节省网络流量。

因此就引出了这篇文章,存储结构体信息是用hash还是string?

以下信息出自StackOverflow  Redis strings vs Redis hashes to represent JSON: efficiency?

I want to store a JSON payload into redis. There's really 2 ways I can do this:

1. One using a simple string keys and values.

key:user, value:payload (the entire JSON blob which can be 100-200 KB)

SET user:1 payload

2. Using hashes

HSET user:1 username "someone"

HSET user:1 location "NY"

HSET user:1 bio "STRING WITH OVER 100 lines"

Keep in mind that if I use a hash, the value length isn'
t predictable. They're not all short such as the bio example above.

Which is more memory efficient? Using string keys and values, or using a hash?

该用户也是同样的疑问,因为值的长度是不确定的,所以不知道采用string还是hash存储更有效率最新面试题整理好了,大家可以在Java面试库小程序在线刷题。

这个问题底下有个开发者回答的非常好,这里翻译出来供大家一起学习讨论,如果有更好的方案,欢迎提出来 首先,答者建议参考redis官方的内存优化的文章:https://redis.io/topics/memory-optimization,用来理解官方的开发者是内存优化方面基于什么考虑。

之后,答者列出了四个方案并给出了各个方案的利弊

1. 存储整个对象,其中JSON序列化过的字符串作为key

INCR id:users
SET user:{id} '{"name":"Fred","age":25}'
SADD users {id}

2. 在hash中存储每个对象的属性

INCR id:users
HMSET user:{id} name "Fred" age 25
SADD users {id}

3. 将对象转化为JSON字符串,用hash结构存储

INCR id:users
HMSET users {id} '{"name":"Fred","age":25}'

这个方案可以仅用两个key,不需要很多key。但是没法对每个用户对象设置TTL(Time to Live,剩余生存时间),因为对象仅仅是hash中的一个字段,而不是全特性的key

4. 存储对象的每个属性作为单独的key

INCR id:users
SET user:{id}:name "Fred"
SET user:{id}:age 25
SADD users {id}

根据上面的文章,即redis内存优化,这个方案不推荐(除非对象的属性需要专门设置TTL或者别的设置)

总的来说,方案4是最不推荐的,方案1和方案2非常相似,也很常见。答者更推荐方案1,因为这个方案允许存储更复杂的对象(也就是说对象可以有很多层嵌套)。方案3通常用在对命名空间比较有要求的场景下,比如说不想要太多key,不关心TTL等参数。另外,Redis 系列面试题和答案全部整理好了,微信搜索Java技术栈,在后台发送:面试,可以在线阅读。

参考资料

《Redis深度历险》

https://juejin.im/book/5afc2e5f6fb9a07a9b362527/section/5afc2e5f51882542714ff291

https://stackoverflow.com/questions/16375188/redis-strings-vs-redis-hashes-to-represent-json-efficiency

原文链接:https://blog.csdn.net/u010145219/article/details/99427693

版权声明:本文为CSDN博主「布鲁斯1990」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。


微信官宣:一大波新年红包封面来了!
2021 年发生的 10 件技术大事!!
23 种设计模式实战(很全)
Logback 也爆雷了,惊爆了
炸了!Log4j2 再爆漏洞。。
劲爆!Java 协程要来了
重磅官宣:Redis 对象映射框架来了!!
推荐一款代码神器,代码量至少省一半!
程序员精通各种技术体系,45岁求职难!
重磅!Spring Boot 2.6 正式发布
Spring Boot 学习笔记,这个太全了!



关注Java技术栈看更多干货



获取 Spring Boot 实战笔记!
浏览 20
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报