几个概念
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. gradle打包分编译环境

    gradle打包分测试.开发.生产环境 buildTypes { debug { signingConfig signingConfigs.myConfig buildConfigField(&quo ...

  2. HDU 4891 The Great Pan

    模拟题. #include<map> #include<set> #include<ctime> #include<cmath> #include< ...

  3. 洛谷——P1724 东风谷早苗

    P1724 东风谷早苗 题目描述 在幻想乡,东风谷早苗是以高达控闻名的高中生宅巫女.某一天,早苗终于入手了最新款的钢达姆模型.作为最新的钢达姆,当然有了与以往不同的功能了,那就是它能够自动行走,厉害吧 ...

  4. 【BZOJ 3881】【COCI 2015】Divljak

    http://www.lydsy.com/JudgeOnline/problem.php?id=3881 好难的一道题啊qwq 一开始我想对T建AC自动机,根本不可做. 正解是对S建AC自动机. fa ...

  5. bzoj 3203: [Sdoi2013]保护出题人 凸包

    题目大意: http://www.lydsy.com/JudgeOnline/problem.php?id=3203 题解 首先我们考虑对一大波僵尸来袭的情况进行分析 假设来袭的僵尸是\(\{ a_1 ...

  6. BZOJ 3171 [Tjoi2013]循环格(费用流)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3171 [题目大意] 一个循环格就是一个矩阵,其中所有元素为箭头,指向相邻四个格子. 每 ...

  7. 【动态规划】【斜率优化】CDOJ1689 分序列

    斜率优化裸题,模型可以看http://www.cnblogs.com/ka200812/archive/2012/08/03/2621345.html #include<cstdio> # ...

  8. python基础之类与对象,继承与派生

    类与对象 对象的本质也就是一个名称空间而已,用于存放自己独有的属性,而类中存放的是对象共有的属性. __init__会在调用类时自动触发 调用类时发生两件事: 1.创建一个空对象stu1 2.自动触发 ...

  9. [USACO13NOV]No Change

    题目大意: 你有k(k<=16)个硬币,每个硬币都有自己的面值. 现在你要给n件商品付钱,每件商品也有自己的价格. 然而老板是个奸商,他绝对不会给你找钱. 你每次付钱只能用一个硬币,但是你可以一 ...

  10. JDK源码学习笔记——LinkedHashMap

    HashMap有一个问题,就是迭代HashMap的顺序并不是HashMap放置的顺序,也就是无序. LinkedHashMap保证了元素迭代的顺序.该迭代顺序可以是插入顺序或者是访问顺序.通过维护一个 ...