在redis中,C字符串(以'\0'结尾的字符数组)只用在一些无需对字符串值进行修改的地方,比如打印日志。其他情况,redis使用SDS - SimpleDynamicString 简单动态字符串,来做。

比如

127.0.0.1:> set testKey "testValue"
OK

键,是一个字符串对象,底层是一个保存着字符串"testKey"的SDS

值也是一个字符串对象,底层是一个保存着字符串"testValue"的SDS

SDS 定义

struct sdshdr {
// 记录buf数组中已使用的字节数,等同于字符串长度(不包括结尾的\0)
int len;
// 记录buf数组中未使用的字节数
int free;
// 实际保存字符串的字节数组
char buf[];
}

比如一个字符串"test":

  len = 4

  free = 0(这个不一定,初始时为0,后续说明)

  buf[] = 't'、'e'、's'、't'、'\0',注意结尾与C相同,也存在'\0',不记入字符串长度

这样做的优势

1. 常数复杂度获取字符串长度

  1. C字符串不记录长度,只能遍历,到\0得到长度,时间复杂度O(n),SDS可以直接记录len为长度,时间复杂度O(1)

2. 兼容部分C字符串的函数

  • 都遵循C字符串以\0结尾的方式,可以重用一部分C字符串函数库的方法

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

  • 通过每次增长或减短字符串时,设置free,使字符串预留出一部分空间,而不是每次都精确到字符串的长度。在频繁修改字符串的环境中可以减少内存重新分配的操作
  • 具体涉及到两种情况:变长、变短。
  • 变长:空间预分配

    • 如果修改后的字符串长度小于 1MB,则程序分配大小和len相同的未使用空间给free

      • 比如"test"修改为"testAgain",则len=9、free=9、buf[] 数组大小为 9+9+1(\0)=19字节
    • 如果修改后的字符串长度大于等于 1MB,则程序分配固定的 1MB给free

      • 比如一个0.7MB的字符串扩成了7MB,则len=7MB、free=1MB、buf[] 数组大小为 9MB + 9MB + 1B
    • 如果修改后的字符串长度能被len+free放下,则此次修改字符串就不需要重新分配空间了
  • 变短:惰性空间释放

    • 变短后的字符串,变短的长度被保存在free中,未来如果有变长操作,则可以直接使用。

      • 比如"test"修改为"t",则len=1、free=3、buf[] 数组大小为 1+3+1=5字节,与变短之前的4+0+1相同

同时SDS提供实时释放未使用空间的api

其他特点

SDS的api都是二进制安全的,所有SDS的api都会用处理二进制的方式处理buf[]中的数据,不会特殊处理。

比如一个字符串内容为"test\0andmore",其内容不会因为有\0而被截断

redis_简单动态字符串的更多相关文章

  1. Redis的简单动态字符串实现

    Redis 没有直接使用 C 语言传统的字符串表示(以空字符结尾的字符数组,以下简称 C 字符串), 而是自己构建了一种名为简单动态字符串(simple dynamic string,sds)的抽象类 ...

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

    Redis的底层数据结构非常多,其中包括SDS.ZipList.SkipList.LinkedList.HashTable.Intset等.如果你对Redis的理解还只停留在get.set的水平的话, ...

  3. 小白的Redis学习(一)-SDS简单动态字符串

    本文为读<Redis设计与实现>的记录.该书以Redis2.9讲解Redis相关内容.请注意版本差异. Redis使用C语言实现,他对C语言中的char类型数据进行封装,构建了一种简单动态 ...

  4. redis 系列3 数据结构之简单动态字符串 SDS

    一.  SDS概述 Redis 没有直接使用C语言传统的字符串表示,而是自己构建了一种名为简单动态字符串(simple dynamic string, SDS)的抽象类型,并将SDS用作Redis的默 ...

  5. 图解Redis之数据结构篇——简单动态字符串SDS

    图解Redis之数据结构篇--简单动态字符串SDS 前言     相信用过Redis的人都知道,Redis提供了一个逻辑上的对象系统构建了一个键值对数据库以供客户端用户使用.这个对象系统包括字符串对象 ...

  6. Redis中的简单动态字符串

    Redis没有直接使用C语言传统的字符串表示(以空字符结尾的字符数组,以下简称C字符串),而是自己构建了一种名为简单动态字符串(simple dynamic string,SDS)的抽象类型,并将SD ...

  7. Redis---SDS(简单动态字符串)

    Redis 没有直接使用 C 语言传统的字符串表示(以空字符结尾的字符数组,以下简称 C 字符串), 而是自己构建了一种名为简单动态字符串(simple dynamic string,SDS)的抽象类 ...

  8. Redis数据类型之SDS简单动态字符串

    一,简单的动态字符串 1,Redis自己构建了一种名为简单动态字符串的抽象类型,并将SDS用作Redis的默认字符串表示, 2,在redis的数据库里面,包含字符串值的键值对在底层都是由SDS实现的 ...

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

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

随机推荐

  1. 项目(八) Jenkins持续集成与构建

    Jenkins环境搭建 由于Jenkins是依赖于java的,所以先介绍java环境的搭建 1)使用官方的二进制包解压安装,官方二进制包的下载地址:http://www.oracle.com/tech ...

  2. 使用WebClient调用第三方接口

    需要调用一个第三方接口,传参返回数据 本来是很简单的一个需求,搞了一天没整好 首先在POSTMAN中测试没有问题,但是使用jquery ajax在前台就会涉及到跨域 虽然设置了 无论怎么写都会报错 C ...

  3. Windows+Apache+mod_wsgi+Flask部署方法

    环境:windows7 64bit 1.python版本3.6.5,32位 2.下载Apache,版本httpd-2.4.33-o102o-x86-vc14-r2,32位,vc14编译 3.下载mod ...

  4. Java框架spring 学习笔记(一):SpringBean、ApplicationContext 容器、BeanFactory容器

    Spring容器是Spring框架的核心,容器可以创建对象并创建的对象连接在一起,配置和管理他们的整个生命周期.Spring 容器使用依赖注入(DI)来作为管理应用程序的组件,被称为 Spring B ...

  5. python中list操作方法

    1,创建一个列表 只要把逗号分隔的不同的数据项使用方括号括起来即可.如下所示:复制代码 代码如下:list1 = ['physics', 'chemistry', 1997, 2000];list2 ...

  6. pandas,pd.ExcelWriter保存结果到已存在的excel文件中

    背景:pandas支持将DataFrame数据直接保存到excel中   保存的case如下: import pandas as pd with pd.ExcelWriter('a.xls') as ...

  7. 元组拆包 与 python拆包

    一.元组拆包(元组解包.迭代解包) 元组拆包可以应用到任何可迭代对象上(任何迭代对象),被可迭代对象中的元素数量必须要跟接受这些元素的元组的空档数一致.也可以使用用 * 来表示忽略多余的元素. 一般的 ...

  8. python--第二十天总结(Django的一些注意)

    关闭Django模板的自动转义 Django的模板中会对HTML标签和JS等语法标签进行自动转义,原因显而易见,这样是为了安全.但是有的时候我们可能不希望这些HTML元素 被转义,比如我们做一个内容管 ...

  9. 【Spring】SpringMVCの環境構築(簡)(Version3.1)

    ■Mavenでプロジェクトの新規 ■プロジェクトのイメージ ■必要なラブリア ■ソース ①pom.xml <?xml version="1.0" encoding=" ...

  10. python中的继承和多态

    继承 继承的表现方式: class Animal(): pass class Cat(Animal): #animal是cat的父类,也可以说是基类 pass print(Cat.__bases__) ...