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

相关推荐
李慕婉学姐6 分钟前
【开题答辩过程】以《基于springboot的地铁综合服务管理系统的设计与实现》为例,不知道这个选题怎么做的,不知道这个选题怎么开题答辩的可以进来看看
java·spring boot·后端
期待のcode28 分钟前
Springboot配置属性绑定
java·spring boot·后端
海上彼尚34 分钟前
Go之路 - 6.go的指针
开发语言·后端·golang
LYFlied1 小时前
在AI时代,前端开发者如何构建全栈开发视野与核心竞争力
前端·人工智能·后端·ai·全栈
用户47949283569151 小时前
我只是给Typescript提个 typo PR,为什么还要签协议?
前端·后端·开源
Surpass余sheng军1 小时前
AI 时代下的网关技术选型
人工智能·经验分享·分布式·后端·学习·架构
JosieBook1 小时前
【Spring Boot】Spring Boot调用 WebService 接口的两种方式:动态调用 vs 静态调用 亲测有效
java·spring boot·后端
喵个咪2 小时前
开箱即用的 GoWind Admin|风行,企业级前后端一体中后台框架:基于 GORM 从零实现新服务
后端·go·orm
a努力。4 小时前
【基础数据篇】数据等价裁判:Comparer模式
java·后端
开心猴爷4 小时前
苹果App Store应用程序上架方式全面指南
后端