Redis核心原理之底层数据结构

本文深入解析Redis中的数据结构,包括RedisDB、RedisObject及其内部结构,如SDS、跳跃表、字典等,并介绍了不同数据类型如字符串、列表、哈希、集合、有序集合的底层实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Redis作为Key-Value存储系统,数据结构如下:

Redis没有表的概念,Redis实例所对应的db以编号区分,db本身就是key的命名空间。 

比如:user:1000作为key值,表示在user这个命名空间下id为1000的元素,类似于user表的id=1000的行。

RedisDB结构

  • Redis中存在“数据库”的概念,该结构由redis.h中的redisDb定义。
  • 当redis 服务器初始化时,会预先分配 16 个数据库
  • 所有数据库保存到结构 redisServer 的一个成员 redisServer.db 数组中
  • redisClient中存在一个名叫db的指针指向当前使用的数据库
  • RedisDB结构体源码:
    typedef struct redisDb {
        int id; //id是数据库序号,为0-15(默认Redis有16个数据库)
        long avg_ttl; //存储的数据库对象的平均ttl(time to live),用于统计
        dict *dict; //存储数据库所有的key-value
        dict *expires; //存储key的过期时间
        dict *blocking_keys;//blpop 存储阻塞key和客户端对象
        dict *ready_keys;//阻塞后push 响应阻塞客户端 存储阻塞后push的key和客户端对象
        dict *watched_keys;//存储watch监控的的key和客户端对象
    } redisDb;

RedisObject结构

Value是一个对象,包含字符串对象,列表对象,哈希对象,集合对象和有序集合对象

1、结构信息概览

typedef struct redisObject {
    unsigned type:4;//类型 对象类型
    unsigned encoding:4;//编码
    void *ptr;//指向底层实现数据结构的指针
    //...
    int refcount;//引用计数
    //...
    unsigned lru:LRU_BITS; //LRU_BITS为24bit 记录最后一次被命令程序访问的时间
    //...
}robj;

1.1、4位type

  • type 字段表示对象的类型,占 4 位;
  • REDIS_STRING(字符串)、REDIS_LIST (列表)、REDIS_HASH(哈希)、REDIS_SET(集合)、REDIS_ZSET(有序集合)。
  • 当我们执行 type 命令时,便是通过读取 RedisObject 的 type 字段获得对象的类型
    127.0.0.1:6379> type a1
    string

1.2、4位encoding

  • encoding 表示对象的内部编码,占 4 位
  • 每个对象有不同的实现编码
  • Redis 可以根据不同的使用场景来为对象设置不同的编码,大大提高了 Redis 的灵活性和效率。
  • 通过 object encoding 命令,可以查看对象采用的编码方式
    127.0.0.1:6379> object encoding a1
    "int"

1.3、24位LRU

  • lru 记录的是对象最后一次被命令程序访问的时间,( 4.0 版本占 24 位,2.6 版本占 22 位)。
  • 高16位存储一个分钟数级别的时间戳,低8位存储访问计数(lfu : 最近访问次数)
  • lru----> 高16位: 最后被访问的时间
  • lfu----->低8位:最近访问次数

1.4、refcount

  • refcount 记录的是该对象被引用的次数,类型为整型。
  • refcount 的作用,主要在于对象的引用计数和内存回收。
  • 当对象的refcount>1时,称为共享对象
  • Redis 为了节省内存,当有一些对象重复出现时,新的程序不会创建新的对象,而是仍然使用原来的对象。

1.5、ptr

ptr 指针指向具体的数据,比如:set hello world,ptr 指向包含字符串 world 的 SDS。

2、7种type

2.1、字符串对象

  • C语言: 字符数组 "\0"
  • Redis 使用了 SDS(Simple Dynamic String)。用于存储字符串和整型数据。

struct sdshdr{
    //记录buf数组中已使用字节的数量
    int len;
    //记录 buf 数组中未使用字节的数量
    int free;
    //字符数组,用于保存字符串
    char buf[];
}

buf[] 的长度=len+free+1 

SDS的优势:

  • SDS 在 C 字符串的基础上加入了 free 和 len 字段,获取字符串长度:SDS 是 O(1),C 字符串是O(n)。
  • SDS 由于记录了长度,在可能造成缓冲区溢出时会自动重新分配内存,杜绝了缓冲区溢出。
  • 可以存取二进制数据,以字符串长度len来作为结束标识

C: \0 空字符串 二进制数据包括空字符串,所以没有办法存取二进制数据
SDS :

  • 非二进制 \0
  • 二进制: 字符串长度 可以存二进制数据

使用场景:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

悠然予夏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值