头图

Redis stores object information using Hash or String

Redis internally uses a RedisObject object to represent all keys and values. The type in RedisObject represents the specific data type of a value object. It includes a string (String), a linked list (List), and a hash structure (Hash ), Set, Sorted set.

When we store object information in daily work, there are generally two methods, one is to store with Hash, and the other is to store with String. But it seems that there is no so-called best practice, so what data structure is actually better for storage?

First, briefly review the Hash and String structure of Redis.

String

The String data structure is a simple key-value type, and the value is actually not only a String, but also a number. String in Redis can represent many semantics:

  • String (bits)
  • Integer
  • Floating point

For these three types, Redis will complete the automatic conversion according to the specific scenario, and select the underlying bearer mode according to the needs. String is a string in Redis internal storage by default, which is referenced by RedisObject. When it encounters incr, decr and other operations, it will be converted into a numeric value for calculation. At this time, the encoding field of RedisObject is int.

In the storage process, we can use Json to serialize the user information into a string, and then store the serialized string in Redis for caching.

String 数据结构

Because Redis strings are dynamic strings and can be modified, the internal structure is similar to Java's ArrayList, which uses pre-allocation of redundant space to reduce frequent memory allocation. As shown in the figure above, the internal space capacity actually allocated for the current string is generally higher than the actual string length len.

Suppose the structure we want to store is:

{
  "name": "xiaowang",
  "age": "35"
}

If the name of this user information is changed to "xiaoli" at this time, and then stored in Redis, Redis does not need to reallocate space. And we only need to do Json serialization and deserialization when reading and storing data, which is more convenient.

Hash

Hash has a wide range of applications in many programming languages, and the same is true in Redis. In Redis, Hash is often used to cache some object information, such as user information, product information, configuration information, etc., so it is also called a dictionary. Redis dictionary uses Hash table as the underlying implementation. A Hash table can contain Multiple hash table nodes, and each hash table node stores a key-value pair in the dictionary. In fact, the bottom layer of Redis database also uses Hash table to store key-value pairs.

Redis's Hash is equivalent to Java's HashMap, and its internal structure is consistent with HashMap, that is, array + linked list structure. It's just that the reHash method is different.

Hash 数据结构

As mentioned earlier, String is suitable for storing user information, and the Hash structure can also store user information, but it is stored separately for each field, so you can obtain the information of some fields during query and save network traffic. However, the value of Redis Hash can only be a string. It is okay to store the example above. If the stored user information becomes:

{
  "name": "xiaowang",
  "age": 25,
  "clothes": {
    "shirt": "gray",
    "pants": "read"
  }
}

So how to store the "clothes" attribute becomes a question of whether to use String or Hash.

Comparison of the memory occupied by String and Hash

Since both data structures can store structure information. Which one is more suitable?

First, we use code to insert 10,000 pieces of data, and then use a visualization tool to see the memory usage.

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);

Look at Redis0 first:

Let's look at Redis1 again:

It can be seen that there is still a little gap, but the gap is not obvious.

Netizens discuss

Internet users also have the same question, because the length of the value is uncertain, so I don't know whether it is more efficient to use String or Hash to store it.

截图来源于 StackOverflow(Redis Strings vs Redis Hashes to represent Json: efficiency?)

Here I mainly translate the high-quality answers to this question for everyone:

suitable for String storage:

  • Need to access a large number of fields each time
  • When the stored structure has multiple levels of nesting

suitable for Hash storage:

  • In most cases only a small number of fields need to be accessed
  • You always know which fields are available to prevent you from not getting the data you want when using mget

to sum up

This article mainly introduces whether Redis uses Hash or String to store object information. It is recommended to use String storage in most cases. After all, it is much more convenient to store objects with multiple levels of nesting, and it takes up less space than Hash. When we need to store a particularly large object, and in most cases only need to access a small number of fields of the object, we can consider using Hash.

Recommended reading

Say goodbye to DNS hijacking, read DoH in one article

Flink's practice in batch processing of cloud logs


云叔
-- 隐于云端,静闻天籁 --

又拍云是专注CDN、云存储、小程序开发方案、 短视频开发方案、DDoS高防等产品的国内知名企业级云服务商。

5.8k 声望
4.6k 粉丝
0 条评论
推荐阅读
【实战分享】使用 Go 重构流式日志网关
流式日志网关的主要功能是提供 HTTP 接口,接收 CDN 边缘节点上报的各类日志(访问日志/报错日志/计费日志等),将日志作预处理并分流到多个的 Kafka 集群和 Topic 中。

云叔_又拍云

终于卷完了!Redis 打怪升级进阶成神之路(2023 最新版)!
是一种非关系型数据库服务,它能解决常规数据库的并发能力,比如传统的数据库的IO与性能的瓶颈,同样它是关系型数据库的一个补充,有着比较好的高效率与高性能。专注于key-value查询的redis、memcached、ttserver。

民工哥13阅读 1.1k

封面图
花了几个月时间把 MySQL 重新巩固了一遍,梳理了一篇几万字 “超硬核” 的保姆式学习教程!(持续更新中~)
MySQL 是最流行的关系型数据库管理系统,在 WEB 应用方面 MySQL 是最好的 RDBMS(Relational Database Management System:关系数据库管理系统)应用软件之一。

民工哥14阅读 2k

封面图
疫情已过,2023 我的前端面试记录
顺利入职。把我最近找工作的心得记录下来。工作交接确定 lastday整理手头工作,相关对接人、交接人放文档中工作交接过渡阶段。做好被咨询者,该拉人拉人,该拉群拉群平时沟通顺畅的同事如果没有 WX 可以加一个属...

linong11阅读 1.1k

思否 CTO 祁宁:社区问答是激荡高级智慧的头脑风暴
在祁宁家里,有一套完整的赛车模拟器,他甚至还请人到国外代购了最新的 VR 设备。作为沉浸式赛车游戏发烧友,除了享受速度与激情带来的愉悦感,祁宁在玩的过程中更多的是思考如何将技术能力进行产品化的问题。

万事ONES6阅读 13k评论 1

封面图
硬卷完了!MongoDB 打怪升级进阶成神之路( 2023 最新版 )!
前面我们学习:MySQL 打怪升级进阶成神之路、Redis 打怪升级进阶成神之路,然后我们还在继续 NoSQL 的卷王之路。从第一篇文章开始,我们逐步详细介绍了 MogoDB 基础概念、安装和最基本的CURD操作、索引和聚合、工...

民工哥7阅读 651

封面图
「刷起来」Go必看的进阶面试题详解
逃逸分析是Go语言中的一项重要优化技术,可以帮助程序减少内存分配和垃圾回收的开销,从而提高程序的性能。下面是一道涉及逃逸分析的面试题及其详解。

王中阳Go4阅读 2k评论 1

封面图

又拍云是专注CDN、云存储、小程序开发方案、 短视频开发方案、DDoS高防等产品的国内知名企业级云服务商。

5.8k 声望
4.6k 粉丝
宣传栏