Redis没有使用C语言字符串的形式,通过’\0’作为结尾,而是使用了简单动态字符串(simple dynamic string)。
当Redis使用的字符串不需要修改字符串的内容的时候,可以使用C语言提供的字符串,当需要修改内容的时候就使用的是简单动态字符串。Redis键值对的操作中,都是使用的简单动态字符串的方式。

这里可以把简单动态字符串理解成一个对象,这个对象的底层保存着一个字符串。

SDS定义

在sds.h/sdshdr结构体中定义了SDS的值

struct sdshdr {int len;int free;char buf[];
};

如果我们使用SDS定义一个SDS内容为“Redis”的对象,则组织结构如下图所示

  • free属性值为0,表示这个SDS没有分配任何没有使用的空间。
  • len属性的值是5,表示这个SDS保存了一个五字节长的字符串。
  • buf属性是一个char类型的数组,数组里面保存了字符串的值,并且以’\0’结束。

SDS和C字符串的区别和优势

常数时间复杂度获取字符串长度

C字符串获取字符串长度需要遍历,耗时。
SDS记录了长度,可以在O(1)的时间复杂度获取字符串长度。

杜绝缓冲区溢出

在C语言中使用strcat(dest, src)的时候,用户自身需要保证dest的空间要大于拼接之后的内存空间。但是很多时候由于疏忽导致内存溢出。SDS解决了这个问题,使用SDS的APIsdscat的时候,他会进行检测空间大小是否能够满足拼接之后的字符串大小。如果不能,他会重新开辟一个拼接后的大度的二倍的字符串空间。

减少修改字符串时带来的内存重分配次数

C语言中,使用strcat的时候,用户需要手动开辟空间,然后使用函数进行字符串的拼接。频繁的申请空间是一个耗时的操作。但是Redis是一个数据库,很可能会有频繁的改变数据的操作,所以Redis不能容忍这种问题的出现,于是SDS的结构体中,哟一个free的属性,这个是用来记录未使用的空间的,实现了空间的预分配和惰性空间释放两种优化策略。

  1. 空间预分配
    当使用SDS的一个API的时候,程序不仅会开辟足够容纳数据的空间,还会额外的开辟未使用的空间。
    额外的未使用的空间的开辟,由如下的方式进行决定:
    如果程序需要使用的SDS的len长度小于1M的话,程序会开辟和len长度一样大小的free空间。
    如果修改之后的len长度大于1M的话,程序会分配free为1M的空间。
    另外上面的两种方式还会多分配一个自己的空间,用于存放’\0’。
    补充一点:只要当需要扩充内存空间的时候,才需要开辟。

  2. 惰性空间释放
    当SDS需要使用API去释放空间的时候,这个时候原有字符串会修改,但是开辟的空间并没有释放掉,而是将字符串向前移动,用free记录未使用的空间大小。

二进制安全

SDS底层通过二进制的方式来保存数据。
Redis不仅可以保存文本数据,还可以保存二进制数据。
即使是文本数据,也是转化成二进制数据保存的。

兼容部分C字符串函数

虽然是通过二进制保存数据,但是为了能够兼容string的使用,保存了字符串的一些特性。

SDS API

SDS主要的API如下表

函数 作用 时间复杂度
sdsnew 创建一个包含C字符串的SDS O(N),N为给定的字符串的长度
sdsempty 创建一个不包含任何内容的空SDS O(1)
sdsfree 释放给定的SDS O(N),N为被释放的SDS的长度
sdslen 返回SDS的已经使用空间字节数 O(1),通过读取对象的len值直接获取
sdsavail 返回SDS未使用的空间字节数 O(1),通过读取对象的free的值获取
sdsdup 创建一个SDS的副本 O,N是给定的SDS的长度
stdclear 清空SDS保存的字符串内容 O(1),由于惰性空间释放,只改变了对象的len值
stscat 将给定C字符串拼接都SDS字符串的末尾 O(N),N为被拼接的字符串的长度
sdscatsds 将给定的SDS拼接到另一个SDS字符串的末尾 O,N为被拼接的SDS字符串的长度
sdscpy 将给定的C字符串复制到SDS里面,覆盖原有的字符串 O(N),N为被复制的C字符串的长度
sdsgrowzero 用空字符串将SDS扩展到给定长度 O(N),N为扩展新增的字节数
sdssrange 保留SDS给定区间的数据,不再全进的数据会被覆盖或者是清除 O(N),N为被保留数据的字节数
sdstrin 接受一个SDS和一个C字符串作为参数,从SDS左右两端移除所有在C字符串中出现过的字符串 O(M*N),M为SDS的长度,N为给定C字符串的长度
sdscmp 对比两个SDS字符串是否相同 O(N),N为两个SDS中较短的那个SDS的长度

redis学习 -- 简单动态字符串相关推荐

  1. Redis之简单动态字符串sds

    转载:https://segmentfault.com/a/1190000012262739 redis在处理字符串的时候没有直接使用以'\0'结尾的C语言字符串,而是封装了一下C语言字符串并命名为s ...

  2. Redis数据结构——简单动态字符串-SDS

    1.SDS简介: redis没有使用C语言传统的字符串表示(以空字符结尾的字符数组),而是自己构建了一种名为简单动态字符串(SDS)的抽象类型,并将SDS用作redis的默认字符串表示. 除了用来保存 ...

  3. Redis数据结构——简单动态字符串

    1.简单动态字符串 redis没有直接用C语言传统的字符串(以空字符结尾的字符数组)表示,而是自己构建了一种名为简单动态字符串(SDS)的抽象类型,并将SDS用作redis的默认字符串表示. 在red ...

  4. Redis内部数据结构详解之简单动态字符串(sds)

    本文所引用的源码全部来自Redis2.8.2版本. Redis中简单动态字符串sds数据结构与API相关文件是:sds.h, sds.c. 转载请注明,本文出自:http://blog.csdn.ne ...

  5. Redis源码初探(1)简单动态字符串SDS

    前言 现在面试可太卷了,Redis基本是必问的知识点,为了在秋招中卷过其他人(虽然我未必参加秋招),本菜鸡决定从源码层面再次学习Redis,不过鉴于本菜鸡水平有限,且没有c语言基础,本文不会对源码过于 ...

  6. redis源码学习-03_动态字符串SDS

    概述 简单动态字符串(SDS, Simple Dynamic String)是 Redis 底层所使用的的字符串表示(而不是使用传统的 C 字符串). redis需要的不仅仅是一个字符串变量,而是一个 ...

  7. 【Redis系列2】Redis字符串对象之SDS(简单动态字符串)实现原理分析

    Redis字符串对象之SDS实现原理分析 前言 字符串对象 为什么Redis的字符串对象是二进制安全的 SDS空间分配策略 空间预分配 惰性空间释放 SDS和C语言字符串区别 SDS的底层存储对象 d ...

  8. 《Redis设计与实现》阅读笔记(二)--简单动态字符串

    简单动态字符串 Redis只在一些无需对字符串进行修改的地方使用C字符串,大部分时候使用简单动态字符串(simple dynamic string, SDS),字符串的抽象类型.二进制安全,可以存放任 ...

  9. Redis简单动态字符串

    简单动态字符串 Simple Dynamic String是Redis内部自己定义的一种数据类型 在Redis内部, 任何包含字符串的键值对都是由SDS实现的 SDS还被用于缓冲区, 比如AOF缓冲区 ...

最新文章

  1. 在阿里云Kubernetes容器服务上打造TensorFlow实验室
  2. nginx 将请求全部指向到一个页面
  3. 我又来定计划了~2015-8至年底
  4. matlab gui打开fig文件,求助gui打开word文件及打开fig格式图片
  5. 2014年acm亚洲区域赛·鞍山站
  6. Linux设备驱动模型4——平台总线实践
  7. js中元素(图片)切换和隐藏显示问题
  8. UI素材|让设计有愉悦的体验,app交互动效的重要性!
  9. vim配置c语言开发环境变量,gcc配置和vim编程
  10. Jupyter更改主题和字体及远程访问
  11. 既然现在处理器性能过剩,为什么PC用起来不流畅?
  12. 微信公众号、小程序项目开发模板源码
  13. 4K标准---电视显示标准(ITU-R BT.2020)
  14. html动态生成表格源码,JavaScript动态生成表格的示例
  15. 搞写商业计划书的要点
  16. 数据时代建设医疗数据,主要有哪些意义?
  17. 微云php解析源码,微云网盘外链php源码 - 兼容并蓄 - 零零星星 - php - 外链 - 微云 - 源码 - HHTjim'S 部落格...
  18. php幸运大抽奖,幸运大转盘-jQuery+PHP实现的抽奖程序-完善中
  19. 【Excel】引用人民银行同期贷款利率(基准利率)和LPR利率的利息计算器(多项目)
  20. 肖像转素描:AI小素的前世今生

热门文章

  1. MongoDB(一):安装
  2. 导入drupal中文语言包
  3. mysql 去重con_python 爬虫 实现增量去重和定时爬取实例
  4. kmp求前缀和后缀的最大重复部分
  5. java多线程w3c_Java创建多线程的三种方式
  6. Java快速创建大量对象_3分钟 快速理解JVM创建对象的步骤!
  7. 微型计算机有什么电路组成,第二章 微型计算机的基本电路组成
  8. linux 内核调试信息在哪里,Linux kernel debug技巧----开启DEBUG选项
  9. Python OpenCV分水岭算法分割和提取重叠或有衔接的图像中的对象
  10. SIFT和SURF的替换算法——ORB (Oriented FAST and Rotated BRIEF 快速定向和旋转)