redis底层数据结构之简单动态字符串(SDS)
简单动态字符串(simple dynamic string,SDS)
redis使用C语言编写的,但是redis的字符串却不是C语言中的字符串(以空字符'\0'结尾的字符数组),redis定义了一种简单动态字符串(simple dynamic string,SDS)的抽象类型,并将SDS作为redis的默认字符串
1 SDS结构
struct sdshdr {
int len;
int free;
char buf[];
}
其中:
len:记录buf数组中已使用字节的长度,等于buf[]中字符串的长度
free:记录buf数组中未使用字节的长度
buf[]:字节数组,用于保存字符串
2 SDS结构示意图
encoding = REDIS_ENCODING_INT 或 REDIS_ENCODING_EMBSTR 或 REDIS_ENCODING_RAW
分配了10Byte空间,占用了6Byte,未使用4Byte
保存空字符的1Byte不包含在len属性里,redis默认为空字符分配额外的1Byte,并把空字符添加到字符串末尾,这些操作都由SDS函数自动完成
示意图如下:

3 redis使用SDS的优点
1) 常数复杂度获取字符串长度
获取SDS字符串的长度只需要读取len属性,时间复杂度为O(1);而C语言中获取字符串的长度通常是经过遍历计数来实现的,时间复杂度为O(n)
2) 杜绝缓冲区溢出
C语言中使用strcat函数来进行字符串的拼接,一旦没有分配足够的内存空间,就会造成缓冲区溢出
而SDS在修改字符串时,首先根据len属性检查内存空间是否满足需求,如果不满足,会进行空间扩展然后在修改,所以不会出现缓冲区溢出
3) 减少修改字符串的内存重新分配次数
C语言不记录字符串的长度,修改字符串时必须要重新分配内存(先释放再申请),如果不重新分配内存,字符串长度增大时会造成内存缓冲区溢出,字符串长度减小时会造成内存泄露
而SDS修改字符串时使用空间预分配和惰性空间释放两种策略:
a) 空间预分配:对字符串进行空间扩展时,扩展的内存比实际需要的多(修改后的字符串小于1MB时,那么会分配与len属性相同大小的未使用空间;大于1MB时,会分配1MB的未使用空间),这样可以减少连续执行字符串增长操作所需的内存重分配次数
b) 惰性空间释放:对字符串进行缩短操作时,不会立即回收缩短后剩余的内存空间,而是使用free属性将剩余的内存空间记录下来,等待后续使用(当有需要时,也可以手动释放这些未使用的空间)
4) 二进制安全
C字符串是以空字符作为字符串结束的标识,而二进制文件(如图片等)内容可能包括空字符串,因此C字符串无法正确存取
而SDS不是以空字符作为字符串结束的标识,而是以len属性表示的长度来判断字符串是否结束
5) 兼容部分C字符串函数
虽然SDS是二进制安全的,但是一样遵从每个字符串都是以空字符串结尾的惯例,这样可以重用C语言库<string.h>中的一部分函数
redis底层数据结构之简单动态字符串(SDS)的更多相关文章
- 【redis】redis底层数据结构原理--简单动态字符串 链表 字典 跳跃表 整数集合 压缩列表等
redis有五种数据类型string.list.hash.set.zset(字符串.哈希.列表.集合.有序集合)并且自实现了简单动态字符串.双端链表.字典.压缩列表.整数集合.跳跃表等数据结构.red ...
- 图解Redis之数据结构篇——简单动态字符串SDS
图解Redis之数据结构篇--简单动态字符串SDS 前言 相信用过Redis的人都知道,Redis提供了一个逻辑上的对象系统构建了一个键值对数据库以供客户端用户使用.这个对象系统包括字符串对象 ...
- Redis数据结构之简单动态字符串SDS
Redis的底层数据结构非常多,其中包括SDS.ZipList.SkipList.LinkedList.HashTable.Intset等.如果你对Redis的理解还只停留在get.set的水平的话, ...
- redis 系列3 数据结构之简单动态字符串 SDS
一. SDS概述 Redis 没有直接使用C语言传统的字符串表示,而是自己构建了一种名为简单动态字符串(simple dynamic string, SDS)的抽象类型,并将SDS用作Redis的默 ...
- Redis 数据结构之简单动态字符串SDS
几个概念1:key对象 数据库存储键值对的键,总是一个字符串对象.2:value对象 数据库存储键值对的值,可以是字符串对象,list对象,hash对象,set对象,sorted set对象. ...
- Redis底层探秘(一):简单动态字符串(SDS)
redis是我们使用非常多的一种缓存技术,他的性能极高,读的速度是110000次/s,写的速度是81000次/s.这么高的性能背后,到底是怎么样的实现在支撑,这个系列的文章,我们一起去看看. redi ...
- 深入理解Redis 数据结构—简单动态字符串sds
Redis是用ANSI C语言编写的,它是一个高性能的key-value数据库,它可以作用在数据库.缓存和消息中间件.其中 Redis 键值对中的键都是 string 类型,而键值对中的值也是有 st ...
- 【Redis】简单动态字符串SDS
C语言字符串 char *str = "redis"; // 可以不显式的添加\0,由编译器添加 char *str = "redis\0"; // 也可以添加 ...
- Redis数据结构之简单动态字符串
Redis没有直接使用C语言传统的字符串表示(以空字符结尾的字符数组), 而是自己构建了一种名为简单动态字符串(simple dynamic string,SDS)的抽象类型, 并将SDS用作Redi ...
- Redis源码解析:01简单动态字符串SDS
Redis没有直接使用C字符串(以'\0'结尾的字符数组),而是构建了一种名为简单动态字符串( simple dynamic string, SDS)的抽象类型,并将SDS用作Redis的默认字符 ...
随机推荐
- 洛谷P6599 「EZEC-2」异或【题解】
题目大意 有\(T\)组数据,每组数据给定两个\(l,n\in\mathbb{N*}\),构造一个长为\(l\),每个元素不超过\(n\)的数组 令他为\(a\),要使 \[\sum_{i=1}^l\ ...
- Joplin修改笔记存储位置
默认存储路径 笔记的默认保存位置可以通过 工具 > 选项 > 通用选项 ,在最上方可以看到路径 使用Windows快捷方式启动 在Joplin的快捷方式上右击,选择属性,然后选择快捷方式选 ...
- MySQL中多种排名实现
一.数据库表结构以及数据 CREATE TABLE `forlan_score` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID', ...
- 文盘Rust -- rust 连接云上数仓 starwift
作者:京东云 贾世闻 最近想看看 rust 如何集成 clickhouse,又犯了好吃懒做的心理(不想自己建环境),刚好京东云发布了兼容ck 的云原生数仓 Starwfit,于是搞了个实例折腾一番. ...
- Redis 异步客户端选型及落地实践
作者:京东科技 王晨 Redis异步客户端选型及落地实践 可视化服务编排系统是能够通过线上可视化拖拽.配置的方式完成对接口的编排,可在线完成服务的调试.测试,实现业务需求的交付,详细内容可参考:htt ...
- JAVA虚拟机25---编译器,解释器,JAVA中的即时编译
https://www.cnblogs.com/somefuture/p/14272221.html 1.简介 编译器:是一种计算机程序,负责把一种编程语言编写的源码转换成另外一种计算机代码,后者往往 ...
- 谈谈Selenium中的三种切换之alert
谈谈Selenium中的三种切换之alert 一.如何识别 识别方法:alert中的确定.取消.输入框无法用inspector定位到,当然还有一些特例. alert分为三种 alert confirm ...
- P7_小程序的宿主环境
宿主环境简介 什么是宿主环境 宿主环境(host environment)指的是程序运行所必须的依赖环境.例如:Android 系统和 iOS 系统是两个不同的宿主环境.安卓版的微信 App 是不能在 ...
- .NET Core项目部署到Windows系统Docker
1.新建一个ASP.NET Core Web应用(模型-视图-控制器) 2. 项目启动Docker.Docker OS选择Windows 3.系统默认的dockerfile文件如下 #See http ...
- ubuntu20.04安装systemback
sudo add-apt-repository --remove ppa:nemh/systemback sudo apt-key adv --keyserver keyserver.ubuntu.c ...