Redis 外部应用一个 RedisObject 对象来示意所有的 key 和 value,RedisObject 中的 type,则是代表一个 value 对象具体是何种数据类型,它蕴含字符串(String)、链表(List)、哈希构造(Hash)、汇合(Set)、有序汇合(Sorted set)。
日常工作中咱们存储对象信息的时候,个别有两种做法,一种是用 Hash 存储,另一种是 String 存储。但如同并没有所谓的最佳实际,那么实际上到底用什么数据结构存储更好呢?
首先简略回顾下,Redis 的 Hash 和 String 构造。
String
String 数据结构是简略的 key-value 类型,value 其实不仅是 String,也能够是数字。Redis 中的 String 能够示意很多语义:
- 字符串(bits)
- 整数
- 浮点数
这三种类型,Redis 会依据具体的场景实现主动转换,并且依据须要选取底层的承载形式。String 在 Redis 外部存储默认就是一个字符串,被 RedisObject 所援用,当遇到 incr、decr 等操作时会转成数值型进行计算,此时 RedisObject 的 encoding 字段为 int。
在存储过程中,咱们能够将用户信息应用 Json 序列化成字符串,而后将序列化后的字符串存入 Redis 进行缓存。
因为 Redis 的字符串是动静字符串,能够批改,内部结构相似于 Java 的 ArrayList,采纳预调配冗余空间的形式来缩小内存的频繁调配。如上图所示,外部为以后字符串理论调配的空间 capacity,个别高于理论字符串长度 len。
假如咱们要存储的构造是:
{
"name": "xiaowang",
"age": "35"
}
如果此时将此用户信息的 name 改为“xiaoli”,再存到 Redis 中,Redis 是不须要重新分配空间的。而且咱们在读取和存储数据的时候只须要对做 Json 序列化与反序列化,比拟不便。
Hash
Hash 在很多编程语言中都有着很宽泛的利用,而在 Redis 中也是如此。在 Redis 中,Hash 经常用来缓存一些对象信息,如用户信息、商品信息、配置信息等,因而也被称为字典(dictionary),Redis 的字典应用 Hash table 作为底层实现,一个 Hash table 外面能够有多个哈希表节点,而每个哈希表节点保留了字典中的一个键值对。实际上,Redis 数据库底层也是采纳 Hash table 来存储键值对的。
Redis 的 Hash 相当于 Java 的 HashMap,内部结构实现与 HashMap 统一,即数组 + 链表构造。只是 reHash 形式不一样。
后面说到 String 适宜存储用户信息,而 Hash 构造也能够存储用户信息,不过是对每个字段独自存储,因而能够在查问时获取局部字段的信息,节俭网络流量。不过 Redis 的 Hash 的值只能是字符串,存储下面的那个例子还好,如果存储的用户信息变为:
{
"name": "xiaowang",
"age": 25,
"clothes": {
"shirt": "gray",
"pants": "read"
}
}
那么该如何存储 ”clothes” 属性又变成了该用 String 还是 Hash 的问题。
String 和 Hash 占用内存的比拟
既然两种数据结构都能够存储构造体信息。到底哪种更加适合呢?
首先咱们用代码先插入 10000 条数据,而后用可视化工具来看看内存的占用状况。
const Redis = require("ioRedis");
const Redis0 = new Redis({port: 6370});
const Redis1 = new Redis({port: 6371});
const user = {
name: 'name12345',
age: 16,
avatar: 'https://dss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=256767015,24101428&fm=26&gp=0.jpg',
phone: '13111111111',
email: '1111111@11.email',
lastLogon: '2021-04-28 10:00:00',
}
async function main() {for (let i = 0; i < 10000; i++) {await Redis0.set(`String:user:${i}`, Json.Stringify(user));
await Redis1.hmset(`Hash:user:${i}`, user);
}
}
main().then(process.exit);
先看 Redis0:
再来看看 Redis1:
能够看到还是有点差距的,然而差距并不显著。
网友探讨
网上的用户也有同样的疑难,因为值的长度是不确定的,所以不晓得采纳 String 还是 Hash 存储更有效率。
这里我次要给大家翻译下该问题下优质的答案:
适宜用 String 存储的状况:
- 每次须要拜访大量的字段
- 存储的构造具备多层嵌套的时候
适宜用 Hash 存储的状况:
- 在大多数状况中只须要拜访大量字段
- 本人始终晓得哪些字段可用,避免应用 mget 时获取不到想要的数据
总结
本文次要介绍了 Redis 存储对象信息是用 Hash 还是 String,倡议是大部分状况下应用 String 存储就好,毕竟在存储具备多层嵌套的对象时不便很多,占用的空间也比 Hash 小。当咱们须要存储一个特地大的对象时,而且在大多数状况中只须要拜访该对象大量的字段时,能够思考应用 Hash。
举荐浏览
辞别 DNS 劫持,一文读懂 DoH
Flink 在又拍云日志批处理中的实际