写点什么

Redis 类型 (Type) 与编码 (Encoding)

作者:码农BookSea
  • 2023-09-25
    浙江
  • 本文字数:3044 字

    阅读完需:约 10 分钟

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


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


字符串

字符串是 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 技术干货,文章持续更新,可以关注公众号第一时间阅读。


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

发布于: 刚刚阅读数: 2
用户头像

码农BookSea

关注

Java开发工程师 2021-12-26 加入

Java开发菜鸟工程师,写博客的初衷是为了沉淀我所学习,累积我所见闻,分享我所体验。希望和更多的人交流学习。

评论

发布
暂无评论
Redis类型(Type)与编码(Encoding)_redis_码农BookSea_InfoQ写作社区