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. Mysql 生成随机数字

    其实思路很简单,利用MySQL现有的函数,然后进行加工处理,达到预期的结果.可以用到的MySQL函数为rand() ,以及 round() 函数. 具体为:select round(rand()*10 ...

  2. servlet配置url-pattern的匹配规则

    <servlet> <servlet-name>hello</servlet-name> <servlet-class>com.qf.servlet.H ...

  3. RLO文件名欺骗

    windows下面,支持一种特殊的unicode字符RLO,一个字符串中如果有这个字符的话,那么在windows下显示时,就会把RLO右侧的字符串逆序显示出来,原始字符串:abcd[RLO]efgh, ...

  4. Keepalived高可用服务

    Keepalived高可用服务 避免负载均衡服务出现单点问题 高可用服务原理 Keepalived的工作原理: Keepalived高可用对之间是通过VRRP通信的,因此,我从 VRRP开始了解起: ...

  5. 笔记68 Redis数据库

    一.Redis简介 REmote DIctionary Server(Redis) 是一个由Salvatore Sanfilippo写的key-value存储系统.Redis是一个开源的使用ANSI ...

  6. express 的路由学习

    使用步骤 - :获取路由中间件对象 `let router = express.Router();` - :配置路由规则 `router.请求方式(URL,fn事)` - fn中参数有req,res, ...

  7. thinkphp wechat

    该接口对应的文件为Com/Wechat.class.php, 主要用户接收微信推送过来的用户数据并自动回复. 注意:识别和分析用户发送的内容,并提供回复内容需要开发者更具实际情况自己实现,本接口值提供 ...

  8. ORACLE动态sql在存储过程中出现表或视图不存在的解决方法

    Oracle动态sql在存储过程中出现表或视图不存在的解决方法 CREATE OR REPLACE PROCEDURE P_test is strsql varchar2(2000); BEGIN   ...

  9. 概率——17icpc西安

    不知道为什么是这样子的.. #include<bits/stdc++.h> using namespace std; int m,n; int main(){ while(scanf(&q ...

  10. (转)OpenFire源码学习之十五:插件开发

    转:http://blog.csdn.net/huwenfeng_2011/article/details/43418493 Plugin接口规范 插件是openfire功能的增强表现,它的主要任务: ...