几个概念
1:key对象 数据库存储键值对的键,总是一个字符串对象。
2:value对象 数据库存储键值对的值,可以是字符串对象,list对象,hash对象,set对象,sorted set对象。
     例如:
            set msg "hello world" 则redis在数据库中创建一个新的键值对,键和值都是一个字符串对象,底层实现都是一个sds对象。
            rpush fruits "apple" "banana" "cherry" 则redis在数据库中创建一个新的键值对,键是一个字符串对象,底层实现是一个sds对象;值是一个列表对象,列表对象包含了三个字符串对象,由三个sds对象实现。
3:sds (sample dynamic string)
    定义:
    struct sdshdr{
    //记录buf数组中已使用字节的数量
    //等于sds所保存字符串的长度
    int len;
    //记录buf数组中未使用的字节数量
    int free;
    //字节数组用来保存字符串
    char buf[];
    }
4:C语言的简单字符串的表示方式不能满足redis对字符串在安全性、效率以及功能上的要求,故引用sds字符串
    4.1 sds字符串获取字符串长度效率更高,时间复杂度为o(1),c字符串的为o(n),保证获取长度的工作不会成为redis的性能瓶颈。(更新sds长度工作是由sds的api在执行时自动完成的);
    4.2 杜绝缓冲区溢出 s1如果没有分配足够的内存空间,扩展时s1的数据就会溢出到下一个相邻的s2空间中,而sds的空间分配时,api会先检查sds的空间是否满足修改所需的要求,如果不满足,api会自动将sds空间扩展到执行修改所需的大小,然后在执行修改操作;
    4.3 减少修改字符串时带来的内存重新分配次数
         1) c字符串执行加长操作,如果忘记重新分配内存就会出现缓冲区溢出,如果执行缩短操作,如果忘了重新分配内存就会出现内存泄露,由于redis是数据库,对速度要求苛刻,如果数据频繁修改,使用c字符串就需要频繁执行内存分配,执行内存分配就会占据修改字符串的大部分时间,如果频繁发生,还会对性能造成影响,故redis使用sds字符串作为底层的实现。
        2) sds字符串 buf数组长度不一定等于字符数量加一,数组包含未使用字节,这个长度存储在free属性上
        3) 空间预分配:优化sds字符串增长操作,api对sds进行空间扩展的时候,程序不仅会为sds修改所需的空间,还会为sds分配额外的未使用空间 公式:扩展后小于1m,分配和len属性相同的未使用空间,大于等于1m分配1m的未使用空间。这样在执行扩展操作时,api会先检查未使用空间是否足够,如果足够就直接使用未使用空间,减少内存分配次数,基于这种策略,在执行n次修改操作时,重新分配内存次数从n次降为最多n次。
        4) 惰性空间释放:优化字符串缩短操作,在进行缩短操作时,程序不会立即重新分配内存回收缩短后多余出来的字节,而是使用free属性记录起来,等待将来使用,如果有增长操作可以直接使用。当然sds也提供了释放sds未使用空间的api,所以不必担心惰性释放带来的内存浪费问题。
    4.4 二进制安全 c字符串中必须符合某种编码,出来字符串末尾,不能包含空字符,所以c字符串只能保存文本数据,不能存储图片、音频、视频等二进制数据,sds的api会以二进制的方式处理buf数组里的数据。使得redis可以保存任意格式的二进制。
    4.5 兼容部分c函数 sds遵循空字符结尾的惯例,api会将sds保存数据的末尾设置为空字符,并且会在buf分配空间时多分配一个字节,这样可以让保存文本数据的sds重用string.h库定义的一些函数。

小结:
c字符串获取长度复杂度o(n),sds为o(1)
api不安全可能造成缓冲区溢出,api安全不会造成缓冲区溢出
修改字符串长度n次会执行n次内存分配,最多n次
只能保存文本数据,可以保存文本或二进制数据
可使用所有string.h库函数,只能使用部分函数

Redis 数据结构之简单动态字符串SDS的更多相关文章

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

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

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

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

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

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

  4. Redis核心原理-简单动态字符串SDS

    SDS简介 Redis是C语言编写的,但没有使用c语言的字符串结构,而是自己实现了一套简单动态字符串 simple dynamic string 简称SDS,SDS兼容C语言的字符串类型,原理类似Ja ...

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

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

  6. Redis底层探秘(一):简单动态字符串(SDS)

    redis是我们使用非常多的一种缓存技术,他的性能极高,读的速度是110000次/s,写的速度是81000次/s.这么高的性能背后,到底是怎么样的实现在支撑,这个系列的文章,我们一起去看看. redi ...

  7. 深入理解Redis 数据结构—简单动态字符串sds

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

  8. 【redis】redis底层数据结构原理--简单动态字符串 链表 字典 跳跃表 整数集合 压缩列表等

    redis有五种数据类型string.list.hash.set.zset(字符串.哈希.列表.集合.有序集合)并且自实现了简单动态字符串.双端链表.字典.压缩列表.整数集合.跳跃表等数据结构.red ...

  9. 【Redis】简单动态字符串SDS

    C语言字符串 char *str = "redis"; // 可以不显式的添加\0,由编译器添加 char *str = "redis\0"; // 也可以添加 ...

随机推荐

  1. codis 的dashboard服务无法启动 提示pid已经运行

    ps -rf|grep pid号 ,一直查询不到,进程并没有运行, 后来在Zookeeper中发现get /zk/codis/db_gdata/dashboard 这个中存在着pid,连接到zooke ...

  2. java中的object... args参数

    关于java方法中Object... args参数的含义 在阅读google发布的volley源码时,突然看到一个方法中存在这样的写法,如 :v(String format, Object... ar ...

  3. Luogu P4148 简单题(K-D Tree)

    题面 题解 因为强制在线,所以我们不能$cdq$分治,所以考虑用$KDT$,$KDT$维护一个矩阵,然后询问的时候如果当前矩形在询问区间内,直接记贡献,否则判断当前点是否在矩阵内,然后左右分别递归下去 ...

  4. 32、Flask实战第32天:优化json数据的返回

    接着上节,我们通过jsonify返回json数据非常方便 ... return jsonify({"code": 400, "message": message ...

  5. nodemon 基本配置与使用

    在开发环境下,往往需要一个工具来自动重启项目工程,之前接触过 python 的 supervisor,现在写 node 的时候发现 supervisior 在很多地方都有他的身影,node 也有一个 ...

  6. Codeforces 551 D. GukiZ and Binary Operations

    \(>Codeforces \space 551 D. GukiZ and Binary Operations<\) 题目大意 :给出 \(n, \ k\) 求有多少个长度为 \(n\) ...

  7. BZOJ 1260 [CQOI2007]涂色paint(区间DP)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1260 [题目大意] 假设你有一条长度为n的木版,初始时没有涂过任何颜色 每次你可以把一 ...

  8. 【拓扑排序】【bitset】Gym - 101128A - Promotions

    给你一张DAG,若选择u点,则必须先选择所有能到达其的点.问你在选择A个点的情况下,哪些点必选:选择B个点的情况下,哪些点必选:选择B个点的情况下,哪些点一定不选. 选择A个点的情况,必选的点是那些其 ...

  9. Activity(活动)的启动模式

    在实际项目中我们应该根据特定的需求为每个活动指定相应的启动模式.启动模式一共分为4种:standar.singleTop.singleTask和singleInstance.可以在AndroidMan ...

  10. opencv中SiftDescriptorExtractor所做的SIFT特征向量提取工作简单分析

    SiftDescriptorExtractor对应于SIFT算法中特征向量提取的工作,通过他对关键点周围邻域内的像素分块进行梯度运算,得到128维的特征向量.具体有如下几个操作: 0.首先,我们假设在 ...