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

相关推荐
用户268516121075623 分钟前
GMP 调度器深度学习笔记
后端·go
J_liaty33 分钟前
SpringBoot深度解析i18n国际化:配置文件+数据库动态实现(简/繁/英)
spring boot·后端·i18n
牧小七33 分钟前
springboot 配置访问上传图片
java·spring boot·后端
用户268516121075637 分钟前
GMP 三大核心结构体字段详解
后端·go
一路向北⁢40 分钟前
短信登录安全防护方案(Spring Boot)
spring boot·redis·后端·安全·sms·短信登录
古城小栈43 分钟前
Tokio:Rust 异步界的 “霸主”
开发语言·后端·rust
进击的丸子1 小时前
基于虹软Linux Pro SDK的多路RTSP流并发接入、解码与帧级处理实践
java·后端·github
techdashen1 小时前
Go 1.18+ slice 扩容机制详解
开发语言·后端·golang
浙江巨川-吉鹏1 小时前
【城市地表水位连续监测自动化系统】沃思智能
java·后端·struts·城市地表水位连续监测自动化系统·地表水位监测系统
fliter1 小时前
Go 1.18+ slice 扩容机制详解
后端