返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >解析Redis数据结构之简单动态字符串sds
  • 664
分享到

解析Redis数据结构之简单动态字符串sds

2024-04-02 19:04:59 664人浏览 安东尼
摘要

Redis是用ANSI C语言编写的,它是一个高性能的key-value数据库,它可以作用在数据库、缓存和消息中间件。其中 Redis 键值对中的键都是 string 类型,而键值对

Redis是用ANSI C语言编写的,它是一个高性能的key-value数据库,它可以作用在数据库缓存和消息中间件。其中 Redis 键值对中的键都是 string 类型,而键值对中的值也是有 string 类型,在 Redis 中 string 类型运用还是很广泛的。本文主要介绍 string 的数据结构—— 简单动态字符串(Simple Dynamic String) 简称sds。

sds 实现

sds 的数据结构:


struct sdshdr {

     //buf 已占用的长度
     int len;

     // buf 剩余的可用的长度
     int free;
   
     // 保存字符串数据的地方
     char buf[]; 
}

结构 sdshdr 保存了 len、free 和 buf 三个属性,分别记录字符的已使用的长度,未使用的长度,以及实际保存字符串的数组
以下是一个新建的,保存 hello world 字符串的 sdshdr 结构:


struct sdshdr {
    len = 5;
    free = 0;
    buf = "hello\0"; 
}
  • free 属性值为0,表示这个sds没有分配未使用的空间。
  • len 属性值为5,表示这个sds保存了一个五字节长的字符串。
  • buf 属性是一个 char 类型的数组,数组的前五个字节分别保存了 'h'、'e'、'l'、'l'、'o' 五个字符,而最后一个字节保存了空字符'\0'。

sds 遵守 C 字符串以空字符串结尾的惯例,保存的空字符串一个字节空间不计算在 sds 的 len 属性里面。添加空字符串到字符串末尾等操作,都是由 sds 函数自动完成的,所以这个空字符对于使用者来说完全是透明的。

通过 len 属性,可以实现时间复杂度 O(1) 的长度计算。另外通过对 buf 分配一些额外的空间,并使用 free 记录未使用空间的长度,sdshdr 可以减少内存的重新分配。这是 sds 相对 c 字符串的一个优势。

为何 Redis 不用 C 语言表示字符串

Redis 是使用 C 语言开发的,而在使用最多的字符串上,Redis 没有使用 C 语言传统的字符串表示,而且使用自己构建的简单动态字符串(sds)。
在 C 语言中,字符串可以用一个 \0 结尾的 char 数组表示。比如 hello world 在 C 语言中就可以表示为"hello world\0"。数组一般初始化以后长度就已经固定了,不能支持字符串追加append和长度计算操作:

  • 每次计算字符串长度都要遍历一遍数组,所以时间复杂度是O(N)
  • 对字符串每次进行追加操作,需要对字符串进行一次内存分配

sds 优化追加字符操作

Redis 作为数据库,对于查询速度要求严格,数据修改也比较频繁,如果每次修改字符串都需要执行一次内存分配的话,都会占用大量的时间。所以 Redis 选择了 sds 而不是 C 字符串,sds 可以减少追加字符的内存分配。通过举例来说明,执行以下操作时,sds 内部的变化:


redis> set msg "hello world"
OK

redis> append msg " again"
(integer)18

redis> get msg
"hello world again"

首先 set 命令创建并保存hello world 到一个 sdshdr 中,这个 sdshdr 的值如下:


struct sdshdr {
     len = 11;
     free = 0;
     buf = "hello world\0";
}

当执行 append 命令时,相对应的 sdshdr 被更新,字符串 " again" 会被追加到原来的 "hello world" 之后:


struct sdshdr {
     len = 17;
     free = 17;
     buf = "hello world again\0                ";
}

当调用 set 命令创建 sdshdr 时,Redis 没有给 sdshdr 分配多余的空间,free 属性为0。而在执行 append 操作之后,Redis 为 buf 分配了多于所需空间一倍的大小。

在执行 append 命令之后,保存 "hello world again" 共需要17 + 1 个字节,但是程序为 sdshdr 分配了 17 + 17 + 1 = 35 个字节,而后续如果在对 sdshdr 进行追加操作,只要追加的长度不超过 free 属性值,那么就不需要对 buf 进行内存重分配。

比如执行以后命令并不会引起 buf 的内存重分配,因为新追加的字符串长度小于17:


redis> append msg  " again"
(integer) 23

对应的 sdshdr 结构如下:


struct sdshdr {
     len = 23;
     free = 11;
     buf = "hello world again again\0               ";
}

redis 内存分配可以查看源码 sds.s/sdsMakeRoomFor,sdsMakeRoomFor 函数描述了内存分配的策略,下面的该函数的伪代码:


// sdshdr:追加前的字符
// addlen:追加字符串
sds sdsMakeRoomFor(sdshdr, addlen) {
   
    // 多余空间大于追加空间,无序再分配内存,直接返回
    if (free >= addlen) return s;
    // 计算新字符的长度
    newlen = (len+addlen); 
   // 如果新字符的长度小于 SDS_MAX_PREALLOC,就分配两倍新字符空间
  //  如果新字符的长度大于 SDS_MAX_PREALLOC,就分配新字符空间 + SDS_MAX_PREALLOC 空间
    if (newlen < SDS_MAX_PREALLOC)
        newlen *= 2;
    else
        newlen += SDS_MAX_PREALLOC;
    // 分配内存
    newsh = zrealloc(sh, sizeof(struct sdshdr)+newlen+1);
    // 更新 free 属性
    newsh.free = newlen - len;
    return newsh;
}

而对于字符的缩短操作,Redis 保存缩短后的字符串,此时并不会进行内存重分配,而是使用 free 属性记录缩短的字符长度。

总结

Redis 的 string 类型为何使用sds而不是 C 字符串,因为sds有两点优势:

  • 计算字符长度,C 字符串复杂度O(n),而 sds 复杂度为 O(1)
  • 字符追加操作,C 字符串每次都需要对内存进行重分配,而 sds 每次会进行动态扩容,当添加字符小于空闲字符时,不会对内容进行分配,减少系统等待时间

参考

Redis 设计与实现

到此这篇关于深入理解Redis 数据结构—简单动态字符串sds的文章就介绍到这了,更多相关Redis 数据结构动态字符串sds内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: 解析Redis数据结构之简单动态字符串sds

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

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

猜你喜欢
  • 解析Redis数据结构之简单动态字符串sds
    Redis是用ANSI C语言编写的,它是一个高性能的key-value数据库,它可以作用在数据库、缓存和消息中间件。其中 Redis 键值对中的键都是 string 类型,而键值对...
    99+
    2024-04-02
  • redis内部数据结构之SDS简单动态字符串详解
    前言 reids 没有直接使用C语言传统的字符串表示(以空字符结尾的字符数组)而是构建了一种名为简单动态字符串的抽象类型,并为redis的默认字符串表示,因为C字符串不能满足redis对字符串的安全性、效率...
    99+
    2022-06-04
    数据结构 字符串 详解
  • redis内部数据结构之SDS简单动态字符串的示例分析
    小编给大家分享一下redis内部数据结构之SDS简单动态字符串的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!前言rei...
    99+
    2024-04-02
  • Redis中SDS简单动态字符串详解
    Redis 是内存数据库,高效使用内存对 Redis 的实现来说非常重要。 看一下,Redis 中针对字符串结构针对内存使用效率做的设计优化。 一、SDS的结构  C语言没有string类型,本质是char[...
    99+
    2023-04-12
    redis sds 介绍 redis sds原理 Redis的SDS结构
  • Redis数据结构的动态字符串sds怎么使用
    本篇内容主要讲解“Redis数据结构的动态字符串sds怎么使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Redis数据结构的动态字符串sds怎么使用”吧!Redis是用ANSI C语言编写的...
    99+
    2023-06-21
  • Redis中SDS简单动态字符串问题怎么解决
    这篇文章主要介绍“Redis中SDS简单动态字符串问题怎么解决”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Redis中SDS简单动态字符串问题怎么解决”文章能帮助大家解决问题。一、SDS的结构&n...
    99+
    2023-07-06
  • 简单动态字符串(simple dynamic string)SDS
    Redis 没有直接使用C语言传统的字符串表示,而是自己构建了一种名为简单动态字符串(simple dynamic string SDS)的抽象类型,并将SDS用作Redis 的默认字符串表示:10.143.128.165:6379>...
    99+
    2023-06-02
  • Redis 字符串实现:简单动态字符串-SDS与C字符串的区别
    2.1 SDS的定义 struct { //buf中已使用的字节数,等于SDS所保存字符串的长度 int len; //buf中未使用的字节长度 int free; //字节数组,用于保存...
    99+
    2020-09-07
    Redis 字符串实现:简单动态字符串-SDS与C字符串的区别
  • 几分钟教你掌握Redis简单动态字符串SDS
    目录正文redisLog(REDIS_WARNING,"Redis is now ready to exit, bye bye...");与C字符串的区别获取字符...
    99+
    2023-01-28
    Redis动态字符串SDS Redis SDS
  • 详解redis数据结构之sds
    详解redis数据结构之sds 字符串在redis中使用非常广泛,在redis中,所有的数据都保存在字典(Map)中,而字典的键就是字符串类型,并且对于很大一部分字典值数据也是又字符串组成的。以下是sd...
    99+
    2022-06-04
    数据结构 详解 redis
  • Java数据结构之字符串怎么用
    这篇文章主要介绍“Java数据结构之字符串怎么用”,在日常操作中,相信很多人在Java数据结构之字符串怎么用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java数据结构之字符串怎么用”的疑惑有所帮助!接下来...
    99+
    2023-06-30
  • C语言数据结构与算法之字符串详解
    目录串的定义串的比较 串的抽象数据类型串的初始化相关定义初始化定长类初始化串的堆式顺序存储结构(Heap)初始化堆字符串 赋值操作比较两个堆字符串的大小 串的定义...
    99+
    2024-04-02
  • Python数据类型详解之字符串、数字实例分析
    这篇文章主要介绍“Python数据类型详解之字符串、数字实例分析”,在日常操作中,相信很多人在Python数据类型详解之字符串、数字实例分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Python数据类型详...
    99+
    2023-06-30
  • 从零开始学Python:第九课-常用数据结构之字符串
    接着上期的Python教程讲,视频教程你们私我要的,整理出来了:Python 900集全套视频教程(全家桶)https://pan.baidu.com/s/1cU5lDWq9gh0cQ7hCnXUiGA,你们好好学。第二次世界大战促使了现代...
    99+
    2023-06-01
  • Java链表数据结构及其简单使用方法解析
    目录认识链表结构单向链表双向链表加深对链表结构的理解实现单向和双向链表的反转实现把链表中给定的值都删除小结认识链表结构 单向链表 单链表在内存中的表示: 可以看到,一个链表的节点包...
    99+
    2024-04-02
  • Java数据结构与算法系列精讲之字符串暴力匹配
    概述 从今天开始, 小白我将带大家开启 Java 数据结构 & 算法的新篇章. 字符串匹配 字符串匹配 (String Matching) 指的是判断一个字符串是否包含另一...
    99+
    2024-04-02
  • C语言数据结构之单向链表详解分析
    链表的概念:链表是一种动态存储分布的数据结构,由若干个同一结构类型的结点依次串连而成。 链表分为单向链表和双向链表。 链表变量一般用指针head表示,用来存放链表首结点的地址。 每个...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作