redis中的字符串是二进制安全的,传统C字符串以'\0'为结尾,只能用于保存纯文本,不能用于保存音频、视频等二进制文件,因为只要在中间遇到'\0'就被截断了。redis的sds模块所有api都使用二进制方式处理字符串,因此叫做字节数组更为贴切。

数据结构:一个带控制结构的字符串,内存中起始地址是一个控制结构,包含一个柔性数组用来保存字符串,结尾加'\0',使用的时候返回的是字符串起始地址,所以需要获取控制结构中内容的时候用指针减控制结构大小去获取控制结构的起始地址,由于工作在用户态,没法使用container_of,所以经常用a[-1]这样的方式手动去获取控制结构中的内容,通过使用__attribute__((packet))来保证手动算出的偏移没有问题。sds字节数组根据字符串二进制位数使用不同控制结构,包括5,8,16,32,64,其中5不使用,例如字符串位数在8到16之间,那么就使用sdshdr16,sds.h中提供的结构定义如下:

struct __attribute__ ((__packed__)) sdshdr5 {unsigned char flags; /* 3 lsb of type, and 5 msb of string length */char buf[];
};
struct __attribute__ ((__packed__)) sdshdr8 {uint8_t len; /* used */uint8_t alloc; /* excluding the header and null terminator */unsigned char flags; /* 3 lsb of type, 5 unused bits */char buf[];
};
struct __attribute__ ((__packed__)) sdshdr16 {uint16_t len; /* used */uint16_t alloc; /* excluding the header and null terminator */unsigned char flags; /* 3 lsb of type, 5 unused bits */char buf[];
};
struct __attribute__ ((__packed__)) sdshdr32 {uint32_t len; /* used */uint32_t alloc; /* excluding the header and null terminator */unsigned char flags; /* 3 lsb of type, 5 unused bits */char buf[];
};
struct __attribute__ ((__packed__)) sdshdr64 {uint64_t len; /* used */uint64_t alloc; /* excluding the header and null terminator */unsigned char flags; /* 3 lsb of type, 5 unused bits */char buf[];
};

每个结构中,len表示使用的长度,alloc是分配的内存的长度,包含头和\0,flags用3bits标识sds类型,buf是sds内存

sds模块源码在sds.h和sds.c中,sds.h中提供的api:

sdslen:获取一个sds的已经使用的长度

sdsavail:获取一个sds的可以使用的长度,是总长度减去已经使用的长度

sdssetlen:设置sds的已经使用的长度

sdsinclen:增加sds的已经使用的长度

sdsalloc:返回一个sds的分配的内存的长度

sdssetalloc:设置sds的分配的内存的长度

sds.c中提供的api:

sdsHdrSize:计算一个sds类型对应的结构体大小

sdsReqType:根据二进制字符串长度计算应该使用的sds类型

sdsnewlen:创建一个新的sds,会在最后生成一个隐式的\0

sdsempty:创建一个空的sds,因为二进制字符串是空的,因此创建出来的是sds8

sdsnew:根据一个C字符串创建一个对应的sds

sdsdup:复制一个sds

sdsfree:释放一个sds

sdsupdatelen:将sds的已经使用的长度修改成第一个'\0'结尾的字符串的长度,相当于从第一个\0截断

sdsclear:将sds的内存清零但不释放

sdsMakeRoomFor:给一个sds扩充空间以供以后使用

sdsRomoveFreeSpace:根据实际使用长度减少sds的分配内存

sdsAllocSize:返回一个sds的总长度,包括头,二进制字符串分配的内存长度和'\0'

sdsAllocPtr:返回一个sds的控制结构的起始地址

sdsIncrLen:增加一个sds的已经使用的长度,要求加完之后不能超过分配的内存长度

sdsgrowzero:给一个sds的已经使用长度增加到指定长度,并将增加部分内存清零

sdscatlen:在一个sds后面连接给定长度的二进制字符串

sdscat:在一个sds后面连接一个C字符串

sdscatsds:将一个sds的已经使用的内存连接到另一个sds中

sdscopylen:将一个给定长度的二进制字符串复制到sds,并更新已经使用的长度

sdscpy:将一个C字符串复制到sds

sdsll2str:将一个long long转换成C字符串格式

sdsull2str:将一个unsigned long long 转换成C字符串格式

sdsfromlonglong:使用long long制造一个sds

sdscatvprintf:将可变长格式化字符串连接到sds后面

sdscatprintf:是sdscatvprintf的包装

sdscatfmt:和sdscatvprintf功能一样,区别是不使用sprintf族函数,性能高

sdstrim:从sds的头和尾去掉所有和给定字符一致的内容,保留剩下的部分

sdsrange:将sds切片,提供起始和终止位置,可以是负数表示从结尾开始

sdstolower:将sds的所有字母变成小写,内部是tolower

sdstoupper:将sds的所有字母变成大写,内部是toupper

sdscmp:比较两个sds,内部是memcmp

sdssplitlen:将字符串用指定的分割器分割成若干部分,存入sds指针数组,并返回这个指针数组,是简单的字符串匹配,可以使用KMP优化

sdsfreesplitres:释放sdssplitlen产生的指针数组和其中的sds的内存

sdscatrepr:处理包含转义字符的二进制字符串

is_hex_digit:判断char c是否是十六进制数,是根据ASCII码判断的

hex_digit_to_int:将一个十六进制字符转换成十进制

sdssplitargs:将一行内容读取到sds指针数组,解析配置文件时使用,每个配置项保存在一个sds中,此函数返回一个sds指针数组和其元素个数

sdsmapchars:将sds中出现在指定字符集中的字符用另一个字符集中的字符代替,要求两个字符集长度相等

sdsjoin:将若干C字符串用提供的分割器连接起来,产生一个sds

sdsjoinsds:和sdsjoin类似,连接的是若干sds

sds_malloc:分配内存

sds_realloc:重新分配内存

sds_free:释放内存

redis基础数据结构(一)可变长字符串sds相关推荐

  1. redis 基础数据结构实现

    参考文献 redis数据结构分析 Skip List(跳跃表)原理详解 redis 源码分析之内存布局 Redis 基础数据结构与对象 Redis设计与实现-第7章-压缩列表 在redis中构建了自己 ...

  2. Redis基础数据结构内部实现简单介绍

    5种基础数据结构 Redis有5种基础数据结构,分别是:String(字符串),list(列表),hash(字典),set(集合),zset(有序集合),这五种是我们开发种经常用的到的,是Redis种 ...

  3. JAVA day13,14 API、Object类、日期时间类(long,Date,Calendar,DateFormat)、String类(字符串,可变长字符串)、正则表达式、包装类

    1.API API(Application Programming Interface),应⽤程序编程接⼝.Java API是⼀本程序员的"字 典",是JDK提供给我们使⽤的类的说 ...

  4. Redis源码阅读笔记-动态字符串(SDS)结构

    2019独角兽企业重金招聘Python工程师标准>>> Redis中采用自定义的结构来保存字符串,在sds.h中: /* Note: sdshdr5 is never used, w ...

  5. redis 基础数据结构 之压缩列表

    redis基础数据结构 之 ziplist压缩链表 给新观众老爷的开场 ziplist是什么? ziplist的设计目的 ziplist的作用 ziplist的小瑕疵 ziplist 的空间布局 zl ...

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

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

  7. redis源码学习-03_动态字符串SDS

    概述 简单动态字符串(SDS, Simple Dynamic String)是 Redis 底层所使用的的字符串表示(而不是使用传统的 C 字符串). redis需要的不仅仅是一个字符串变量,而是一个 ...

  8. Redis基础数据结构

    Redis是一款完全免费的,高性能的key-value数据库,目前被大多数公司用来做缓存.Redis作为一个内存数据库,它的读写速度非常快:读速度可以达到110000次/s,写的速度是81000次/s ...

  9. Redis基础数据结构String:你知道String长度限制多少吗

    字符串String是Redis最简单最常用的数据结构,它的内部表示就是一个字符数组,如图所示.Redis所有的数据结构都是以唯一的key字符串作为名称,然后通过这个唯一key值来获取相应的value数 ...

最新文章

  1. grub-和grub-troubleshootting
  2. html5水调歌头代码,张惠言的五首《水调歌头》
  3. php怎么查自己的文件编码,php检测文件编码的方法示例
  4. .NET6 新功能和新生态
  5. dispose方法的使用
  6. 用Express搭建 blog (一)
  7. python有哪些好的学习资料或者博客
  8. 计算机网络(一)-- 物理层与数据链路层
  9. 华中科技大学计算机学院离散数学2,华中科技大学计算机学院2015离散数学二考试点评.pdf...
  10. 2013腾讯实习生面试经历
  11. 解决XP系统每次关机都自动重启问题
  12. 保养维修 | 万用表电流输入保险丝的自助测试和更换指导
  13. 百度年龄计算机在线使用,百度精准年龄计算器在线计算app
  14. IT外企那点儿事--也说跳槽
  15. 58 mysql 军规_58到家MySQL军规升级版(转)
  16. 【数据分析师---数据可视化】第二章:plotly绘图基础篇
  17. 【SLAM学习笔记】6-ORB_SLAM3关键源码分析④ Optimizer(一)单帧优化
  18. Mathematica-1: 导入txt数据绘图
  19. UCINET入门案例
  20. centos 7的firewalld防火墙配置IP伪装和端口转发(内附配置案例)

热门文章

  1. micropython入门 stm32_micropython(1):芯片 STM32 开发,也可以使用micropython开发,都很方便...
  2. 关于Catalan(卡特兰)数的理解
  3. 核芯国产最强锁相环PLL
  4. android按钮美化(入门)
  5. FastUnit超简单摘抄
  6. Dubbo-05 20190317
  7. java里面逗号分隔的字符串转list
  8. 新思科技网络安全研究中心分析手机中的生物识别数据泄露漏洞
  9. 计算机网络常见面试题(自答版)
  10. 你的微信昵称,可能正在出卖你