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

简介: 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中的元素唯一、有序
  • 具备类型升级机制,可以节省内存空间
  • 底层采用二分查找方式来查询
相关文章
|
9月前
|
存储 缓存 NoSQL
Redis常见面试题全解析
Redis面试高频考点全解析:从过期删除、内存淘汰策略,到缓存雪崩、击穿、穿透及BigKey问题,深入原理与实战解决方案,助你轻松应对技术挑战,提升系统性能与稳定性。(238字)
|
存储 缓存 NoSQL
Redis 服务器全方位介绍:从入门到核心原理
Redis是一款高性能内存键值数据库,支持字符串、哈希、列表等多种数据结构,广泛用于缓存、会话存储、排行榜及消息队列。其单线程事件循环架构保障高并发与低延迟,结合RDB和AOF持久化机制兼顾性能与数据安全。通过主从复制、哨兵及集群模式实现高可用与横向扩展,适用于现代应用的多样化场景。合理配置与优化可显著提升系统性能与稳定性。
893 0
|
10月前
|
消息中间件 缓存 NoSQL
Redis各类数据结构详细介绍及其在Go语言Gin框架下实践应用
这只是利用Go语言和Gin框架与Redis交互最基础部分展示;根据具体业务需求可能需要更复杂查询、事务处理或订阅发布功能实现更多高级特性应用场景。
523 86
|
10月前
|
存储 消息中间件 NoSQL
Redis数据结构:别小看这5把“瑞士军刀”,用好了性能飙升!
Redis提供5种基础数据结构及多种高级结构,如String、Hash、List、Set、ZSet,底层通过SDS、跳表等实现高效操作。灵活运用可解决缓存、计数、消息队列、排行榜等问题,结合Bitmap、HyperLogLog、GEO更可应对签到、UV统计、地理位置等场景,是高性能应用的核心利器。
|
10月前
|
存储 监控 NoSQL
Redis高可用架构全解析:从主从复制到集群方案
Redis高可用确保服务持续稳定,避免单点故障导致数据丢失或业务中断。通过主从复制实现数据冗余,哨兵模式支持自动故障转移,Cluster集群则提供分布式数据分片与水平扩展,三者层层递进,保障读写分离、容灾切换与大规模数据存储,构建高性能、高可靠的Redis架构体系。
|
10月前
|
存储 缓存 NoSQL
Redis持久化深度解析:数据安全与性能的平衡艺术
Redis持久化解决内存数据易失问题,提供RDB快照与AOF日志两种机制。RDB恢复快、性能高,但可能丢数据;AOF安全性高,最多丢1秒数据,支持多种写回策略,适合不同场景。Redis 4.0+支持混合持久化,兼顾速度与安全。根据业务需求选择合适方案,实现数据可靠与性能平衡。(238字)
|
10月前
|
存储 缓存 NoSQL
Redis基础命令与数据结构概览
Redis是一个功能强大的键值存储系统,提供了丰富的数据结构以及相应的操作命令来满足现代应用程序对于高速读写和灵活数据处理的需求。通过掌握这些基础命令,开发者能够高效地对Redis进行操作,实现数据存储和管理的高性能方案。
315 12
|
10月前
|
存储 消息中间件 NoSQL
【Redis】常用数据结构之List篇:从常用命令到典型使用场景
本文将系统探讨 Redis List 的核心特性、完整命令体系、底层存储实现以及典型实践场景,为读者构建从理论到应用的完整认知框架,助力开发者在实际业务中高效运用这一数据结构解决问题。
|
10月前
|
存储 缓存 NoSQL
【Redis】 常用数据结构之String篇:从SET/GET到INCR的超全教程
无论是需要快速缓存用户信息,还是实现高并发场景下的精准计数,深入理解String的特性与最佳实践,都是提升Redis使用效率的关键。接下来,让我们从基础命令开始,逐步揭开String数据结构的神秘面纱。
|
11月前
|
存储 缓存 人工智能
Redis六大常见命令详解:从set/get到过期策略的全方位解析
本文将通过结构化学习路径,帮助读者实现从命令语法掌握到工程化实践落地的能力跃迁,系统性提升 Redis 技术栈的应用水平。

热门文章

最新文章

推荐镜像

更多
  • DNS