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的性能和内存利用率。

相关推荐
Honmaple1 分钟前
OpenClaw 实战经验总结
后端
golang学习记19 分钟前
Go 嵌入结构体方法访问全解析:从基础到进阶陷阱
后端
NAGNIP36 分钟前
程序员效率翻倍的快捷键大全!
前端·后端·程序员
qq_2562470544 分钟前
从“人工智障”到“神经网络”:一口气看懂 AI 的核心原理
后端
无心水44 分钟前
分布式定时任务与SELECT FOR UPDATE:从致命陷阱到优雅解决方案(实战案例+架构演进)
服务器·人工智能·分布式·后端·spring·架构·wpf
用户400188309371 小时前
手搓本地 RAG:我用 Python 和 Spring Boot 给 AI 装上了“实时代码监控”
后端
用户3414081991251 小时前
/dev/binder 详解
后端
Gopher_HBo1 小时前
Go进阶之recover
后端
程序员布吉岛1 小时前
写了 10 年 MyBatis,一直以为“去 XML”=写注解,直到看到了这个项目
后端
却尘1 小时前
一篇小白也能看懂的 Go 字符串拼接 & Builder & cap 全家桶
后端·go