乐趣区

关于后端:Redis类型Type与编码Encoding

本文已收录至 GitHub,举荐浏览 👉 Java 随想录

微信公众号:Java 随想录

原创不易,重视版权。转载请注明原作者和原文链接

Redis 是一款开源的高性能 key-value 数据库,广泛应用于各种场景。在 Redis 中,数据类型(Type)和编码(Encoding) 是十分重要的概念。本篇博客将具体介绍 Redis 反对的数据类型以及相应的编码方式和底层实现原理。

要查看 Redis 某个 key 的外部编码,能够应用 Redis 自带的命令OBJECT ENCODING key

其中,key是你想要查问的键名。例如,如果你想要查问名为 mykey 的键的外部编码,能够执行以下命令:

127.0.0.1:6379> object encoding mykey  // 查看某个 Redis 键值的编码

redisObject

在 Redis 中,redisObject 是一个十分重要的数据结构,它用于保留字符串、列表、汇合、哈希表和有序汇合等类型的值。以下是对于 redisObject 构造体的定义:

typedef struct redisObject {
    unsigned type:4;
    unsigned encoding:4;
    unsigned lru:24; /* lru time (relative to server.lruclock) */
    int refcount;
    void *ptr;
} robj;

各个属性解析如下:

  • type:用于标识对象所属的类型,别离是 REDIS_STRINGREDIS_LISTREDIS_SETREDIS_ZSETREDIS_HASH 等。
  • encoding:用于标识对象外部的编码方式,如 REDIS_ENCODING_INTREDIS_ENCODING_HTREDIS_ENCODING_ZIPMAP 等。
  • lru:这个字段记录了对象被命令调用的工夫, 它是缓存淘汰策略(LRU)的一部分。
  • refcount:援用计数,当 refcount 缩小到 0 时,对象就能够被清理并回收内存。
  • ptr:一个指针,依据对象的类型和编码方式的不同,这个指针可能会指向各种不同的类型,比方整数、动静字符串、链表、字典等。

其中,redisObject 的 encoding 取值有如下几种:

#define OBJ_ENCODING_RAW 0        // 简略动静字符串,用于保留键值对的键和配置文件中的参数。#define OBJ_ENCODING_INT 1        // 整型值,用于优化小整数的内存应用。#define OBJ_ENCODING_HT 2         // 哈希表,用于存储一般哈希对象的字段和值。#define OBJ_ENCODING_ZIPMAP 3     // 缩字典,这是一种非凡类型的哈希表,用于优化小哈希对象的内存应用。#define OBJ_ENCODING_LINKEDLIST 4 // 双端链表,用于存储列表键。#define OBJ_ENCODING_ZIPLIST 5    // 压缩列表,用于优化小列表或者小哈希对象的内存应用。#define OBJ_ENCODING_INTSET 6     // 整数汇合,用于优化只蕴含整数元素的汇合的内存应用。#define OBJ_ENCODING_SKIPLIST 7   // 跳跃表和字典,用于存储有序汇合键。#define OBJ_ENCODING_EMBSTR 8     // 对于长度小于 44 字节的字符串,Redis 抉择应用此非凡的编码方式。#define OBJ_ENCODING_QUICKLIST 9  // 对于列表对象(list object)的一种编码方式。quicklist 是 ziplist 和双向链表的混合体。

Type 与 Encoding 介绍

Redis 反对五种次要的数据类型:字符串 (String)、列表(List)、汇合(Set)、有序汇合(Sorted Set) 和哈希(Hash)。

每种数据类型都有对应的编码方式,数据类型与编码方式总览如下:

数据类型 编码方式
字符串 int、embstr、raw
哈希表 ziplist、hashtable
列表 ziplist、linkedlist、quicklist
汇合 intset、hashtable
有序汇合 ziplist、skiplist

字符串

字符串是 Redis 中最根本的数据类型,通常用于存储文本或二进制数据。字符串在 Redis 中反对三种编码方式:

  • int:当字符串能够示意为整数时,Redis 会将其转换为整数,并采纳 int 编码方式存储。int 编码方式的长处是存储空间小,操作效率高。毛病是只能存储整数,不反对字符串操作。
  • embstr(embstr-encoded string):保留长度小于 44 字节的字符串,当一个字符串比拟短,采纳此编码方式存储,能够缩小内存占用。
  • raw(raw-encoded string):保留长度大于 44 字节的字符串,当一个字符串比拟长时,采纳此编码方式存储。

列表

列表是一系列有序的字符串汇合,能够增加、批改和删除元素。列表在 Redis 中反对三种编码方式:

  • ziplist:在 Redis3.2 版本之前,当 List 列表中每个字符串的长度都「小于 64 字节 」并且 List 列表中「 元素数量小于 512 个」时,List 对象应用 ziplist 编码,其余状况应用 linkedlist 编码。ziplist 是一种紧凑的、压缩的列表构造,能够节俭内存,实用于小型列表。
  • linkedlist:linkedlist 是一种链表构造,反对任意大小的列表。但其内存占用会随着列表长度的减少而减少。
  • quicklist:Redis 3.2 版本引入,quicklist 是一种由多个 ziplist 组成的列表构造,既能保障性能,又能节俭内存,实用于大型列表。

汇合

汇合是一系列无序的字符串汇合,反对增加、删除和查问元素。汇合在 Redis 中反对两种编码方式:

  • intset:当汇合中的元素都是整数时,Redis 会采纳 intset 编码方式存储。intset 编码方式的长处是存储空间小,操作效率高。
  • hashtable:当汇合中的元素蕴含字符串时,Redis 会采纳 hashtable 编码方式存储。hashtable 编码方式的长处是能够存储任意类型的元素,反对字符串操作。毛病是存储空间绝对较大,操作效率绝对较低。

有序汇合

有序汇合是一系列无序的字符串汇合,每个元素关联一个分数,能够依据分数排序。有序汇合在 Redis 中反对两种编码方式:

  • ziplist:当汇合中元素个数少于 128 个,并且每个元素的大小小于 64 字节时,应用此编码方式。这是因为 ziplist 在解决较小数据时,内存效率更高,性能更优。
  • skiplist:skiplist 是一种跳跃表构造,反对疾速查问和排序。实用于大型有序汇合。

哈希表

哈希表是一系列键值对汇合,每个键关联一个值。哈希表在 Redis 中反对两种编码方式:

  • ziplist:保留的所有键值的字符串长度小于 64 字节,并且键值对数量小于 512 个,Redis 会采纳 ziplist 编码方式存储。ziplist 编码方式的长处是存储空间小,操作效率高。毛病是不反对疾速的键查找操作。
  • hashtable:除上述条件之外,Redis 会采纳 hashtable 编码方式存储。hashtable 编码方式的长处是反对疾速的键查找操作,毛病是存储空间绝对较大,操作效率绝对较低。

Type 与 Encoding 底层原理

理解 Redis 反对的数据类型和编码方式后,咱们来看一下它们的底层实现原理。

编码转换

Redis 中的每个键值对都有一个类型标识,示意该键值对的数据类型。当咱们对一个键进行操作时,Redis 会依据该键以后的编码方式以及操作所需的编码方式,对键值对进行编码转换。

例如,当咱们向一个字符串中追加内容时,如果该字符串以后的编码方式为 raw,然而新的内容能够应用 embstr 编码方式存储,那么 Redis 会将该字符串的编码方式从 raw 转换为 embstr。

数据结构

除了编码方式外,Redis 还应用了许多经典的数据结构来实现各种数据类型。例如,Redis 的列表和哈希表都是采纳链表构造实现的。而有序汇合则采纳了跳跃表 (Skip List) 这种高效的数据结构。

这些数据结构都通过了精心设计和优化,以满足各种场景下的利用需要。例如,链表构造适宜频繁地增加和删除元素,而跳跃表构造则适宜排序和查找。

本篇博客介绍了 Redis 反对的五种次要数据类型以及相应的编码方式。

Redis 的数据类型和编码方式是为了在不同的场景下达到最佳的性能和内存占用。了解这些类型和编码机制,对于深入咱们对 Redis 的意识,优化其性能,以及施展其最大后劲是至关重要的。

尽管每个我的项目的需要和利用可能会有所不同,但通过精心抉择和应用适合的类型和编码,咱们都能够充分利用 Redis 为咱们的利用带来的高效,疾速和牢靠。

总之,Redis 的类型和编码是其外围性能的基石,了解这些能够帮忙咱们更好地应用 Redis,解决理论问题。当你下次面临须要决定应用哪种数据结构或编码方式的时候,心愿你能够记住明天的内容,并从中找到答案。感谢您抽出贵重的工夫浏览这篇文章,心愿它对您有所帮忙!


感激浏览,如果本篇文章有任何谬误和倡议,欢送给我留言斧正。

老铁们,关注我的微信公众号「Java 随想录」,专一分享 Java 技术干货,文章继续更新,能够关注公众号第一工夫浏览。

一起交流学习,期待与你共同进步!

退出移动版