Redis入门到通关之数据结构解析-IntSet

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: Redis入门到通关之数据结构解析-IntSet

概述


IntSetRedis中set集合的一种实现方式,基于 整数数组 来实现,并且具备长度可变、有序等特征。

结构如下:

// intset 结构体定义
typedef struct intset {
    uint32_t encoding;   // 编码方式,用于表示存储的整数类型
    uint32_t length;     // intset 中包含的元素个数
    int8_t contents[];   // 存储整数的数组
} intset;

其中的 encoding 包含三种模式,表示存储的整数大小不同:

为了方便查找,Redis 会将 intset 中所有的整数按照 升序 依次保存在contents数组中,结构如图:


IntSet升级


假如现在,数组中每个数字都在 int16_t 的范围内,因此采用的编码方式是 INTSET_ENC_INT16,每部分占用的字节大小为:

encoding:4字节

length:4字节

contents:2字节 * 3 = 6字节

我们向该其中添加一个数字:50000,这个数字超出了 int16_t 的范围,intset 会自动 升级 编码方式到合适的大小。

以当前案例来说流程如下:


  • 升级编码为 INTSET_ENC_INT32, 每个整数占4字节,并按照新的编码方式及元素个数扩容数组
  • 倒序 依次将数组中的元素拷贝到扩容后的正确位置
  • 将待添加的元素放入数组末尾
  • 最后,将 inset 的 encoding 属性改为 INTSET_ENC_INT32 ,将 length 属性改为4


简易源码


#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

// intset 结构体定义
typedef struct intset {
    uint32_t encoding;   // 编码方式,用于表示存储的整数类型
    uint32_t length;     // intset 中包含的元素个数
    int8_t contents[];   // 存储整数的数组
} intset;

// 创建一个新的 intset
intset *intset_new() {
    intset *is = malloc(sizeof(intset));
    if (!is) return NULL;
    is->encoding = 0;   // 初始编码方式为 0
    is->length = 0;
    return is;
}

// 添加整数到 intset
intset *intset_add(intset *is, int64_t value) {
    // 添加元素的逻辑实现省略
    return is;
}

// 检查整数是否存在于 intset
int intset_contains(const intset *is, int64_t value) {
    // 检查元素是否存在的逻辑实现省略
    return 0;
}

// 删除整数从 intset
intset *intset_remove(intset *is, int64_t value) {
    // 删除元素的逻辑实现省略
    return is;
}

// 打印 intset 中的元素
void intset_print(const intset *is) {
    printf("Intset Length: %d\n", is->length);
    printf("Intset Elements: ");
    for (int i = 0; i < is->length; ++i) {
        printf("%lld ", (long long)is->contents[i]);
    }
    printf("\n");
}

int main() {
    intset *is = intset_new();
    if (!is) {
        printf("Error: Unable to create intset.\n");
        return 1;
    }

    is = intset_add(is, 5);
    is = intset_add(is, 10);
    is = intset_add(is, 15);

    intset_print(is);

    // 检查元素是否存在
    if (intset_contains(is, 10)) {
        printf("Element 10 exists in the intset.\n");
    } else {
        printf("Element 10 does not exist in the intset.\n");
    }

    is = intset_remove(is, 10);
    intset_print(is);

    free(is);
    return 0;
}


总结


Intset可以看做是特殊的整数数组,具备一些特点:

  • Redis会确保Intset中的元素唯一、有序
  • 具备类型升级机制,可以节省内存空间
  • 底层采用二分查找方式来查询
相关文章
|
5天前
|
安全 网络安全 数据安全/隐私保护
Pikachu Unsafe Filedownload 通关解析
Pikachu Unsafe Filedownload 通关解析
|
5天前
|
安全 网络安全 数据安全/隐私保护
Pikachu Over Permission 通关解析
Pikachu Over Permission 通关解析
|
5天前
|
安全 网络安全 PHP
Pikachu 目录遍历通关解析
Pikachu 目录遍历通关解析
|
5天前
|
存储 安全 网络安全
Pikachu Unsafe Fileupload 通关解析
Pikachu Unsafe Fileupload 通关解析
|
5天前
|
存储 监控 安全
Pikachu PHP 反序列化通关解析
Pikachu PHP 反序列化通关解析
|
6天前
|
存储 安全 网络安全
Pikachu敏感信息泄露通关解析
Pikachu敏感信息泄露通关解析
|
6天前
|
SQL XML 安全
Pikachu SQL 注入通关解析
Pikachu SQL 注入通关解析
|
6天前
|
XML 安全 JavaScript
|
6天前
|
安全 网络安全 数据安全/隐私保护
Pikachu URL 重定向通关解析
Pikachu URL 重定向通关解析
|
6天前
|
安全 网络安全 数据安全/隐私保护

推荐镜像

更多