Redis(132) Redis的对象编码是什么?

Redis中的对象编码(Object Encoding)是指Redis内部用来表示不同数据类型的具体存储结构和方式。不同的编码方式有其特定的适用场景,以便在不同的使用情况下,能够在性能和内存利用方面做最佳平衡。

Redis支持的对象类型包括:字符串(String)、列表(List)、集合(Set)、有序集合(Sorted Set)和哈希(Hash)。每种对象类型都有多种编码方式。

字符串(String)

编码方式:

  • RAW:普通字符串。
  • EMBSTR:短字符串(长度小于等于39字节)采用这种编码方式。
  • INT:可以表示为64位整数的字符串。

代码实现示例:

c 复制代码
robj *createStringObject(char *ptr, size_t len) {
    robj *o = zmalloc(sizeof(robj));
    if (len <= 39) {
        o->type = OBJ_STRING;
        o->encoding = OBJ_ENCODING_EMBSTR;
        o->ptr = zmalloc(sizeof(struct sdshdr) + len + 1);
        struct sdshdr *sh = (void*)(o->ptr);
        sh->len = len;
        sh->alloc = len;
        sh->flags = SDS_TYPE_8;
        memcpy(sh->buf, ptr, len);
        sh->buf[len] = '\0';
    } else {
        o->type = OBJ_STRING;
        o->encoding = OBJ_ENCODING_RAW;
        o->ptr = sdsnewlen(ptr, len);
    }
    o->refcount = 1;
    return o;
}

列表(List)

编码方式:

  • ZIPLIST:适用于小型列表。
  • LINKEDLIST:适用于大型列表。

代码实现示例:

c 复制代码
robj *createListObject(void) {
    list *l = listCreate();
    robj *o = zmalloc(sizeof(robj));
    o->type = OBJ_LIST;
    o->encoding = OBJ_ENCODING_LINKEDLIST;
    o->ptr = l;
    o->refcount = 1;
    return o;
}

robj *createZiplistObject(void) {
    unsigned char *zl = ziplistNew();
    robj *o = zmalloc(sizeof(robj));
    o->type = OBJ_LIST;
    o->encoding = OBJ_ENCODING_ZIPLIST;
    o->ptr = zl;
    o->refcount = 1;
    return o;
}

集合(Set)

编码方式:

  • INTSET:适用于整数值集合。
  • HT(Hash Table):适用于大型集合,或包含非整数值的集合。

代码实现示例:

c 复制代码
robj *createSetObject(void) {
    dict *d = dictCreate(&setDictType, NULL);
    robj *o = zmalloc(sizeof(robj));
    o->type = OBJ_SET;
    o->encoding = OBJ_ENCODING_HT;
    o->ptr = d;
    o->refcount = 1;
    return o;
}

robj *createIntsetObject(void) {
    intset *is = intsetNew();
    robj *o = zmalloc(sizeof(robj));
    o->type = OBJ_SET;
    o->encoding = OBJ_ENCODING_INTSET;
    o->ptr = is;
    o->refcount = 1;
    return o;
}

有序集合(Sorted Set)

编码方式:

  • ZIPLIST:适用于小型有序集合。
  • SKIPLIST:适用于大型有序集合。

代码实现示例:

c 复制代码
robj *createZsetObject(void) {
    zset *zs = zmalloc(sizeof(zset));
    zs->dict = dictCreate(&zsetDictType, NULL);
    zs->zsl = zslCreate();
    robj *o = zmalloc(sizeof(robj));
    o->type = OBJ_ZSET;
    o->encoding = OBJ_ENCODING_SKIPLIST;
    o->ptr = zs;
    o->refcount = 1;
    return o;
}

robj *createZsetZiplistObject(void) {
    unsigned char *zl = ziplistNew();
    robj *o = zmalloc(sizeof(robj));
    o->type = OBJ_ZSET;
    o->encoding = OBJ_ENCODING_ZIPLIST;
    o->ptr = zl;
    o->refcount = 1;
    return o;
}

哈希(Hash)

编码方式:

  • ZIPLIST:适用于小型哈希。
  • HT(Hash Table):适用于大型哈希。

代码实现示例:

c 复制代码
robj *createHashObject(void) {
    dict *d = dictCreate(&hashDictType, NULL);
    robj *o = zmalloc(sizeof(robj));
    o->type = OBJ_HASH;
    o->encoding = OBJ_ENCODING_HT;
    o->ptr = d;
    o->refcount = 1;
    return o;
}

robj *createHashZiplistObject(void) {
    unsigned char *zl = ziplistNew();
    robj *o = zmalloc(sizeof(robj));
    o->type = OBJ_HASH;
    o->encoding = OBJ_ENCODING_ZIPLIST;
    o->ptr = zl;
    o->refcount = 1;
    return o;
}

对象的通用结构

Redis中的对象结构redisObject定义如下:

c 复制代码
typedef struct redisObject {
    unsigned type:4;
    unsigned encoding:4;
    unsigned lru:24; 
    int refcount;
    void *ptr;
} robj;

示例使用

下面是一个简单的示例,展示如何创建和使用不同类型的Redis对象:

c 复制代码
#include <stdio.h>
#include <string.h>
#include "zmalloc.h"
#include "intset.h"
#include "ziplist.h"
#include "dict.h"
#include "skiplist.h"
#include "robj.h" 

int main() {
    // 创建字符串对象
    robj *strObj = createStringObject("hello", 5);
    printf("String object: %s\n", (char*)strObj->ptr);

    // 创建整数集合对象
    intset *is = intsetNew();
    uint8_t success;
    is = intsetAdd(is, 100, &success);
    is = intsetAdd(is, 200, &success);

    robj *setObj = createIntsetObject();
    setObj->ptr = is;
    printf("Set object with 100 and 200 added.\n");

    // 创建压缩列表对象
    robj *ziplistObj = createZiplistObject();
    unsigned char *zl = ziplistObj->ptr;
    zl = ziplistPush(zl, (unsigned char*)"world", 5, ZIPLIST_TAIL);
    printf("Ziplist object: %s\n", ziplistIndex(zl, 0));

    return 0;
}

总结

Redis对象编码通过多种不同的存储和编码方式,为不同类型的数据提供了灵活高效的存储方案。每种编码方式都有其适用的场景和优点,合理选择合适的编码方式可以有效提升Redis的性能和内存利用率。

相关推荐
苏三说技术20 分钟前
Spring AI、LangChain4j、AgentScope、Embabel,哪个AI框架更好?
后端
烽学长31 分钟前
(附源码)基于Springboot+vue的图书阅读分享系统的设计与实现
java·spring boot·后端
isfox35 分钟前
Python 单例模式:一个类只能有一个实例,到底怎么实现?
后端
青山木1 小时前
RocketMQ 入门到原理(三):消息存储原理
java·后端·中间件·架构·rocketmq
小白男神1 小时前
MySQL进阶学习三(视图)
后端·mysql
猿人谷1 小时前
Jev:当 AI 不再生成 Token,而是直接做决策
后端·langchain·aigc
苍何1 小时前
WorkBuddy + 腾讯乐享,原来知识库还能这么用
后端
站大爷IP1 小时前
Python的生成器把我坑惨了,原来yield和return的区别这么大
后端
苍何1 小时前
一份来自大厂内部的《AI 原生实践避坑指南》
后端