关于又拍云:Redis-存储对象信息是用-Hash-还是-String

45次阅读

共计 2248 个字符,预计需要花费 6 分钟才能阅读完成。

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 在又拍云日志批处理中的实际

正文完
 0