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

相关推荐
Csvn1 小时前
Day 3:LIKE 与模式匹配 — 让查询学会"模糊搜索"
后端·sql
Hazenix2 小时前
Go 指南:一篇文章速通 Golang
开发语言·后端·golang
灯澜忆梦2 小时前
GO_复合类型---指针
开发语言·后端·golang
IT_陈寒2 小时前
SpringBoot自动装配坑了我一天,原来问题出在这
前端·人工智能·后端
星栈3 小时前
深度复盘:比 EventLoop 更隐蔽!Node 微任务堆积引发的线上接口雪崩事故
后端·node.js
名字还没想好☜4 小时前
Go slice 的 append 陷阱:共享底层数组导致的数据串改
开发语言·后端·golang·go·slice
诸神缄默不语4 小时前
FastAPI后端配置CORS中间件支持浏览器跨域访问
后端·fastapi
Fanta丶4 小时前
14.Activiti7 网关 排他网关ExclusiveGateway、并行网关ParallelGateway
后端
明月_清风4 小时前
robots.txt 完全指南:从入门到精通
后端·爬虫
jvmind_dev4 小时前
Java GC 实战指南(番外篇):被忽视的隐形杀手 —— Class Unloading 如何拖垮 GC
java·后端