iis服务器助手广告广告
返回顶部
首页 > 资讯 > 数据库 >Redis之SDS数据结构的使用
  • 155
分享到

Redis之SDS数据结构的使用

RedisSDS数据结构RedisSDS 2022-08-08 17:08:16 155人浏览 泡泡鱼
摘要

目录序言字符串char*字符串数组简单动态字符串SDS序言 Redis的几种基本数据结构有字符串(String)、哈希(Hash)、列表(List)、集合(Set)、有序集合(Sorted Set),这些是最常见的,也能

序言

Redis的几种基本数据结构有字符串(String)、哈希(Hash)、列表(List)、集合(Set)、有序集合(Sorted Set),这些是最常见的,也能在官网上查看到。

官网链接:Redis 教程_redis教程

字符串

前面也提到过字符串是设计了简单动态字符串SDS(Simple Dynamic String)结构来表示字符串。这种数据结构可以提升字符串的操作效率,并可以保存二进制数据。

先思考一个问题:

Redis是用C语言实现的,那么为什么没有复用C语言的字符串实现方法,而选用了SDS呢?

char*字符串数组

C语言实现字符串使用的是char*字符串数组,它是一块连续的内存空间,一次存放了字符串的每一个字符,并且最后一个字符是“\0”,用来标识字符串的结尾位置,如下图,

Redis之SDS数据结构的使用

连续的内存空间的所有字符串没有分隔符计算机就没办法区分字符串与字符串之间的位置。在C语言标准库中字符串的操作函数就会通过检查字符串数组中是否有“\0”来判断字符串是否结束。例如字符串操作函数strlen函数,它就是在遍历字符串数组中的每一个字符,并进行计数,直到检查到“\0”,它的时间复杂度是O(n)。流程如下,

Redis之SDS数据结构的使用

简单动态字符串SDS

SDS的数据结构里包含:字符串实际长度,字符串分配空间长度,SDS类型,字符数组,其中字符数组buf[]用来保存实际数据,如下图,

Redis之SDS数据结构的使用

再来看看类似的字符操作函数sdslen函数的源码(在sds.h文件中),直接根据SDS类型返回对应的字符串现有长度,避免了对字符串的遍历,时间复杂度变成了O(1),当然也会付出一点代价增加了空间复杂度。这都是设计人员让数据操作更加高效。源码如下,

static inline size_t sdslen(const sds s) {
    unsigned char flags = s[-1];
    switch(flags&SDS_TYPE_MASK) {
        case SDS_TYPE_5:
            return SDS_TYPE_5_LEN(flags);
        case SDS_TYPE_8:
            return SDS_HDR(8,s)->len;
        case SDS_TYPE_16:
            return SDS_HDR(16,s)->len;
        case SDS_TYPE_32:
            return SDS_HDR(32,s)->len;
        case SDS_TYPE_64:
            return SDS_HDR(64,s)->len;
    }
    return 0;
}

再来看一下字符串的拷贝源码,操作都使用了字符串的现有长度,拷贝后进行更新。

sds sdscpylen(sds s, const char *t, size_t len) {
    // 判断字符串数组分配的空间长度是不是小于字符串数组当前长度
    if (sdsalloc(s) < len) {
        // 根据要追加的长度len-sdslen(s)和现有长度,判断是否增加新的空间
        s = sdsMakeRoomFor(s,len-sdslen(s));
        if (s == NULL) return NULL;
    }
    // 将源字符串t中len长度的数据拷贝到目标字符串结尾
    memcpy(s, t, len);
    // 拷贝完后,在目标字符串结尾加上\0
    s[len] = '\0';
    // 设置字符串数组最新当前长度
    sdssetlen(s, len);
    return s;
}

SDS把目标字符串的空间检查和扩容封装在了sdsMakeRoomFor函数中,追加、打印、复制等操作都会调用该函数。可以看到该函数根据sds的信息进行动态扩容,源码如下,

sds sdsMakeRoomFor(sds s, size_t addlen) {
    void *sh, *newsh;
    // 获取sds可用空间
    size_t avail = sdsavail(s);
    size_t len, newlen;
    char type, oldtype = s[-1] & SDS_TYPE_MASK;
    int hdrlen;
 
    // 如果可用空间大于等于要增加的空间,则直接返回
    if (avail >= addlen) return s;
    // sds长度
    len = sdslen(s);
    // sds指针
    sh = (char*)s-sdsHdrSize(oldtype);
    // 新字符串长度
    newlen = (len+addlen);
    // 如果新长度小于最大预分配长度,则进行两倍扩容
    if (newlen < SDS_MAX_PREALLOC)
        newlen *= 2;
    else
        newlen += SDS_MAX_PREALLOC;
    type = sdsReQtype(newlen);
    // SDS类型5转换为类型8
    if (type == SDS_TYPE_5) type = SDS_TYPE_8;
 
    hdrlen = sdsHdrSize(type);
    if (oldtype==type) {
        newsh = s_realloc(sh, hdrlen+newlen+1);
        if (newsh == NULL) return NULL;
        s = (char*)newsh+hdrlen;
    } else {
        
        newsh = s_malloc(hdrlen+newlen+1);
        if (newsh == NULL) return NULL;
        memcpy((char*)newsh+hdrlen, s, len+1);
        s_free(sh);
        s = (char*)newsh+hdrlen;
        s[-1] = type;
        sdssetlen(s, len);
    }
    sdssetalloc(s, newlen);
    return s;
}

 可以看到sdsMakeRoomFor函数中sdshdr5类型不再使用直接转换成了sdshdr8类型,它们是SDS设计的5种类型,分别表示sdshdr5sdshdr8sdshdr16sdshdr32sdshdr64,下面就看一下这几种类型的结构源码,如下图,

struct __attribute__ ((__packed__)) sdshdr5 {
    unsigned char flags; 
    char buf[];
};
struct __attribute__ ((__packed__)) sdshdr8 {
    uint8_t len; 
    uint8_t alloc; 
    unsigned char flags; 
    char buf[];
};
struct __attribute__ ((__packed__)) sdshdr16 {
    uint16_t len; 
    uint16_t alloc; 
    unsigned char flags; 
    char buf[];
};
struct __attribute__ ((__packed__)) sdshdr32 {
    uint32_t len; 
    uint32_t alloc; 
    unsigned char flags; 
    char buf[];
};
struct __attribute__ ((__packed__)) sdshdr64 {
    uint64_t len; 
    uint64_t alloc; 
    unsigned char flags; 
    char buf[];
};

sdshdr5已不再使用,所以在函数中做了处理,把sdshdr5类型转换为sdshdr8类型。前面也提到过SDS是紧凑型字符串数据结构,以sdshdr8为例,它是用的是uint8_t即8位无符号整型,会占用1字节的内存空间。SDS之所以设计不同的结构是为了能灵活保存不同大小的字符串,从而有效节省内存空间。

另外,__attribute__ ((__packed__))标志可以告诉编译器在编译以上数据结构时,不实用字节对齐的方式(不满8字节的整数倍,则会自动补齐),而是采用紧凑的方式分配内存。

到此这篇关于Redis之SDS数据结构的使用的文章就介绍到这了,更多相关Redis SDS数据结构内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

您可能感兴趣的文档:

--结束END--

本文标题: Redis之SDS数据结构的使用

本文链接: https://www.lsjlt.com/news/33616.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Redis数据结构的动态字符串sds怎么使用
    本篇内容主要讲解“Redis数据结构的动态字符串sds怎么使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Redis数据结构的动态字符串sds怎么使用”吧!Redis是用ANSI C语言编写的...
    99+
    2023-06-21
  • 解析Redis数据结构之简单动态字符串sds
    Redis是用ANSI C语言编写的,它是一个高性能的key-value数据库,它可以作用在数据库、缓存和消息中间件。其中 Redis 键值对中的键都是 string 类型,而键值对...
    99+
    2024-04-02
  • Redis中内部数据结构sds的作用是什么
    Redis中内部数据结构sds的作用是什么,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。sds的数据结构定义我们知道,在C语言...
    99+
    2024-04-02
  • redis内部数据结构之SDS简单动态字符串的示例分析
    小编给大家分享一下redis内部数据结构之SDS简单动态字符串的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!前言rei...
    99+
    2024-04-02
  • Redis数据结构之链表与字典的使用
    今天我们来聊一聊Redis中的链表与字典,具体如下: 链表 关于链表的基础概念其实你在学习Redis之前一定积累了不少,所以本文将默认你已经掌握了链表相关的基础知识,而Redis的链...
    99+
    2024-04-02
  • Redis之常用数据结构哈希表
    目录1.哈希冲突2.链式哈希3.rehash4.渐进式 rehash5.rehash 触发条件哈希表是一种保存键值对(key-value)的数据结构 哈希表优点在于,它能以 O(1) 的复杂度快速查询数据。 怎么做到的呢...
    99+
    2023-04-11
    Redis常用数据结构-哈希表 数据结构之哈希表 Redis哈希表
  • redis数据库使用的数据结构类型
    redis 中共有 9 种数据结构类型:键值对:储存单个键值对字符串:存储文本、数字或二进制数据列表:存储有序键值对集合:存储不重复的值有序集合:存储带有分值的元素,按分值排序哈希表:存...
    99+
    2024-04-19
    redis 地理位置 键值对
  • Java数据结构之List的使用总结
    目录泛型什么是泛型泛型的分类泛型的定义简单演示泛型背后作用时期和背后的简单原理泛型类的使用泛型总结包装类基本数据类型和包装类直接的对应关系包装类的使用,装箱(boxing)和拆箱(u...
    99+
    2024-04-02
  • Pandas数据结构之Series的使用
    目录一. Series 简介二. 实例化 Series2.1 使用一维数组实例化2.2 使用字典实例化2.3 使用标量例化三.Series 简单使用3.1 为Series添加Name...
    99+
    2024-04-02
  • Redis数据结构之链表详解
    目录1 链表和链表节点的结构2 链表相关的API1 链表和链表节点的结构 1.1 节点结构 节点的结构大概长下边这个样子: 那么,把这些节点就连起来就成了这个样子: 1.2 链表...
    99+
    2024-04-02
  • redis数据结构之压缩列表
    目录压缩列表是列表键和哈希键的底层实现之一。当一个列表键只包含少量列表项,并且每个列表项要么就是小整数,要么就是长度比较短的字符串,redis就会使用压缩列表来做列表键的底层实现 当...
    99+
    2024-04-02
  • 数据结构之堆的具体使用
    目录堆的概念及结构定义堆堆的初始化插入数据判空删除堆顶的数据获取堆顶数据获取元素个数打印销毁堆Topk问题代码总结堆的概念及结构 定义堆 实现堆的功能首先要定义堆的结构体 typ...
    99+
    2024-04-02
  • Redis中5种数据结构的使用场景
    这篇文章给大家分享的是有关Redis中5种数据结构的使用场景的内容。小编觉得挺实用的,因此分享给大家做个参考。一起跟随小编过来看看吧。一、redis 数据结构使用场景原来看过 redisbook 这本书,对...
    99+
    2024-04-02
  • Redis数据结构之跳跃表是什么
    小编给大家分享一下Redis数据结构之跳跃表是什么,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!前言跳跃表是一种有序的数据结构,...
    99+
    2024-04-02
  • redis五种数据结构及使用场景
    redis 提供五种数据结构:字符串(存储简单数据)、哈希表(存储对象数据)、列表(存储消息队列)、集合(存储不重复元素)和有序集合(按评分存储排序元素)。 Redis 的五种数据结构...
    99+
    2024-04-19
    redis 键值对
  • Redis的数据结构及应用场景
    一. 谈谈对redis的理解,它的应用场景。Redis是一个key-value存储系统,它支持存储的value类型包括string字符串、list链表、set集合、sorted Set有序集合和hash哈希等数据类型。这些数据类型都支持pu...
    99+
    2023-06-02
  • Redis数据结构是怎样的
    这篇文章主要介绍“Redis数据结构是怎样的”,在日常操作中,相信很多人在Redis数据结构是怎样的问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Redis数据结构是怎样的”的疑惑有所帮助!接下来,请跟着小编...
    99+
    2023-06-27
  • Redis底层数据结构之dict、ziplist、quicklist详解
    目录1 Redis dict1.1 扩缩容的条件1.2 渐进式rehash操作2 Redis ziplist2.1 ziplist结构 2.2 entry结构3 Redis...
    99+
    2024-04-02
  • redis缓存用什么数据结构
    redis 缓存支持多种数据结构,包括:字符串、哈希表、列表、集合、有序集合、地理空间数据类型、hyperloglog 和位图。每种数据结构都针对特定应用场景进行了优化,从而提高了 re...
    99+
    2024-04-02
  • redis怎么看数据结构
    在 Redis 中,可以使用 `TYPE` 命令来查看键对应的数据结构类型。具体语法如下:```TYPE key```其中,`key...
    99+
    2023-08-24
    redis
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作