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的默认字符 ...
随机推荐
- prettier+ts+eslint+vscode配置代码保存自动格式化,自动remove unsed declaration,delete no-unused-imports
每天都要开心(▽)哇: 以这个项目为案例 下面是项目的基本情况 What would you like to build? › App with Quasar CLI, let's go! Proje ...
- OpenMP 线程同步 Construct 实现原理以及源码分析(上)
OpenMP 线程同步 Construct 实现原理以及源码分析(上) 前言 在本篇文章当中主要给大家介绍在 OpenMP 当中使用的一些同步的 construct 的实现原理,如 master, s ...
- 重磅!瞄准 Web 3.0,谷歌云推出专为区块链服务的 Blockchain Node Engine!
[本文由Cloud Ace整理发布,谷歌云服务请访问Cloud Ace 官网] 区块链技术正在为世界各地的消费者和企业带来巨大的创新和价值创造.随着技术变得越来越主流,公司需要可扩展.安全和可持续的基 ...
- Linux防火墙部署与配置
Linux防火墙部署与配置 1. 实验概述 Linux作为网关,搭建小型局域网,在此基础上进行实验,了解Linux防火墙的构成.NAT和包过滤配置方法等. 2. 实验环境 网络大致结构如图2-1所示, ...
- 四、python解释器、环境变量和多版本共存
目录 一.python解释器 1.python发展方向 2.python解释器 1.历史 2.版本 3.下载 4.安装 5.使用 二.环境变量与多版本共存 环境变量设置 多版本共存 三.运行pytho ...
- HTTP协议拓展
本文详细介绍了 HTTPS 相较于 HTTP 更安全的原因,包括对称加密.非对称加密.完整性摘要.数字证书以及 SSL/TLS 握手等内容,图文并茂.理论与实战结合.建议收藏! 1. 不安全的 HTT ...
- BIO和NIO的基本用法和API讲解
1 BIO 可以理解为Blocking IO 是同步阻塞的IO,也就是说,当有多个请求过来的时候,请求会呈现为链状结构,遵循先进先出的原则 1.1 单线程版本 1.1.1 服务端 //服务端单线程处理 ...
- Vue25 mixin
1 简介 混入 (mixin) 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能.一个混入对象可以包含任意组件选项.当组件使用混入对象时,所有混入对象的选项将被"混合" ...
- docker05-dockerfile
1.dockerfile是什么 Dockerfile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本.可以理解为docker自己的语言编写的脚本. 2.Dockerfile内容基础 ...
- 关于联想对Jim博士的质疑
对Jim博士质疑的质疑 因为关注司马南,从他的空间里看到Jim博士和其龃龉,大致看了Jim博士头条里的文章,因为看到自己常用的EPICS,上午匆忙就写了上面的文. Jim博士是去年在头条上看到的,因为 ...