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

Redis中,C字符串只会作为字符串字面量(string literal)用在一些无需对字符串值进行修改的地方,例如打印日志等场景。

结构

struct SDS<T> {
T capacity; // 数组容量
T len; // 数组长度
bytes flags; // 特殊标识位
bytes[] content; // 字节数组,存储字符串
};
  • capacity:分配给字节数组的长度

  • len:字节数组存储内容的实际长度

Redis规定字符串长度不能超过512M

绝大部分情况下,认为不会对字符串进行append操作,所以创建字符串时lencapacity一样长,即不分配冗余空间。

SDS对比C字符串

  • 获取字符串长度时间复杂度为O(1):直接使用len属性

  • 有效杜绝缓冲区溢出:APPEND操作先分配空间,再执行拼接

  • 减少修改字符串可能带来的内存重分配次数:空间预分配,动态扩容提供冗余空间

  • 二进制安全:SDS使用len的值而不是空字符来判断字符是否结束,所以字节数组可以用来保存一系列二进制数据

  • 兼容部分C字符串函数

扩容策略

Redis的字符串扩容策略主要根据字符串长度len来区分。

len小于1M时,采用加倍策略,即保留100%的冗余空间。

len超过1M之后,为避免加倍后的冗余空间过大而导致浪费,每次扩容只分配1M冗余空间。

embstrraw

Redis的字符串有两种存储方式:

  • embstr:将RedisObject对象头和SDS对象连续存在一起,使用malloc方法一次性分配

  • raw:使用两次malloc,两个对象头在内存地址上不连续

不同存储形式的转换:

  • 对于SDS字符串,如果长度小于等于39个,则使用embstr形式存储,否则使用raw形式存储

    •   

      >>> set a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
      >>> STRLEN a >>> OBJECT ENCODING a
      "embstr"

      >>> set b aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
      >>> STRLEN b >>> OBJECT ENCODING b
      "raw"
  • 对于embstr,该字符串实际上是只读的,对该对象执行任何修改命令后时,Redis会先将对象编码转为raw,然后执行修改命令

    •   

      >>> set a hello
      >>> OBJECT ENCODING a
      "embstr"
      >>> APPEND a world
      >>> OBJECT ENCODING a
      "raw"

Redis数据结构之字符串-SDS的更多相关文章

  1. 峰Redis学习(3)Redis 数据结构(字符串、哈希)

    第一节:Redis 数据类型介绍 五种数据类型: 字符串(String) 字符串列表(list) 有序字符串集合(sorted set) 哈希(hash) 字符串集合(set)   第二节:Redis ...

  2. Redis 数据结构之字符串的那些骚操作

    Redis 字符串底层用的是 sds 结构,该结构同 c 语言的字符串相比,其优点是可以节省内存分配的次数,还可以... 这样写是不是读起来很无聊?这些都是别人咀嚼过后,经过一轮两轮三轮的再次咀嚼,吐 ...

  3. Redis自定义动态字符串(sds)模块(一)

    Redis开发者在开发过程中没有使用系统的原始字符串,而是使用了自定义的sds字符串,这个模块的编写是在文件:sds.h和sds.c文件中.Redis自定义的这个字符串好像也不是很复杂,远不像ngin ...

  4. 如何使用RedisTemplate访问Redis数据结构之字符串操作

    Redis 数据结构简介 Redis 可以存储键与5种不同数据结构类型之间的映射,这5种数据结构类型分别为String(字符串).List(列表).Set(集合).Hash(散列)和 Zset(有序集 ...

  5. Redis自定义动态字符串(sds)模块(二)

    sds模块的具体实现: 1.sdsnewlen 根据参数生成一个sds字符串 sds sdsnewlen(const void *init, size_t initlen) { struct sdsh ...

  6. Redis数据结构之字符串

    学习阶段分成两个部分,一个是redis客户端,一个是java客户端操作 一:在redis客户端操作 1.先删除里面的几个key 2.set与get与getset 3.数值的增减 值递增1,或者减一 如 ...

  7. redis 5.0.7 源码阅读——动态字符串sds

    redis中动态字符串sds相关的文件为:sds.h与sds.c 一.数据结构 redis中定义了自己的数据类型"sds",用于描述 char*,与一些数据结构 typedef c ...

  8. 【Redis笔记(四)】 Redis数据结构 - list链表

    原创作品,转载请标明:http://blog.csdn.net/Xiejingfa/article/details/50573605 经过前面的介绍,我们学习了Redis中string字符串.hash ...

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

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

随机推荐

  1. gitlab搭建使用

    1.安装gitlab __环境准备__ [root@gitlab ~]# cat /etc/redhat-release CentOS Linux release 7.2.1511 (Core) [r ...

  2. jmeter beanshell postprocessor 使用

    String newtoken=bsh.args[0];print(newtoken);${__setProperty(newtoken,${token},)}; String newcompanyI ...

  3. spring boot MVC

    1 spring boot的用途 第一,spring boot可以用来开发mvc web应用. 第二,spring boot可以用来开发rest api. 第三,spring boot也可以用来开发w ...

  4. [Java Performance] 线程及同步的性能之线程池/ThreadPoolExecutors/ForkJoinPool

    线程池和ThreadPoolExecutors   虽然在程序中可以直接使用Thread类型来进行线程操作,但是更多的情况是使用线程池,尤其是在Java EE应用服务器中,一般会使用若干个线程池来处理 ...

  5. 制作 macOS High Sierra U盘

    制作 macOS High Sierra U盘USB启动安装盘方法教程 (全新安装 Mac 系统) 随着苹果 macOS High Sierra 正式版发布,很多使用 Mac 电脑的同学都已升级到最新 ...

  6. mysql8的坑

    plugin caching_sha2_password could not be loaded 我在mac上用Sequel Pro连数据库的时候,会报出以上错误,这是应为8.0.11把身份认证插件改 ...

  7. esxi主机用命令行强行关闭通过前端界面无法关闭的ESXI虚拟机

    环境:esxi5.1-esxi6.5 背景:如果esxi下面某一台vm死机了,并且esxi的控制台卡死不能用,为了不影响同一个esx下其他的vm正常使用,那么我们只能用命令行来单独重启此vm,保证一定 ...

  8. JavaScript翻转字符串方法

    先把字符串转化成数组String.prototype.split(),再借助数组的reverse方法翻转数组顺序(Array.prototype.reverse()),然后把数组转化成字符串. 使用的 ...

  9. Android开发——回调(Callback)

    1. 回调函数的定义: 在A类中定义了一个方法,这个方法中用到了一个接口和该接口中的抽象方法,但是抽象方法没有具体的实现,需要B类去实现,B类实现该方法后,它本身不会去调用该方法,而是传递给A类,供A ...

  10. Sql批量修改语句

    修改某个数字类型字段 SET @num = 10000000000001; #定义初始化变量参数 UPDATE ckys_me #更新的表 SET openid = (@num := @num+1) ...