Redis 数据结构 之 SDS
SDS(simple dynamic string)
,简单动态字符串。s同时它被称为 Hacking String。hack 的地方就在 sds 保存了字符串的长度以及剩余空间。sds 的实现在 sds.c
中。
C语言字符串使用长度为n+1的字符数组来表示长度为n的字符串,并且字符数组的最后一个元素总是空字符'\0',这样的方式存储,时存在安全隐患的,并且它不能满足效率方面的需求。
因此Redis没有使用C原生的string
而是自己构建了SDS
。在Redis里,C语言字符串只用于一些无须对字符串值进行修改的地方,比如:日志。
在Redis中,包含字符串值的键值对都是使用SDS实现的,除此之外,SDS还被用于AOF缓冲区、客户端状态的输入缓冲区。
SDS定义
struct sdshdr{
//字节数组
char buf[];
//buf数组中已使用字节数量
int len;
//buf数组中未使用字节数量
int free;
}
如上图所示,len表示该SDS保存了一个6字节长度(不包含结束符)的字符串,free表示该SDS还有6个字节的未使用空间,buf是一个char类型的数组
,保存了该SDS所存储的字符串值。
高效
相比C语言字符串,使获取字符串长度时间复杂度降为O(1)
而C原生的获取长度为O(N)
遍历整个数组。
安全
同时SDS
杜绝缓冲区溢出,不会像C那样造成数组数据不安全,绝对不会越界。
当需要对SDS进行修改时,API会先检查SDS当前剩余空间是否满足修改之后所需的空间,如果不满足的话API会自动将SDS的空间扩展至足够用的空间然后才进行下一步操作,所以SDS不会出现缓冲区溢出问题。
减少内存分配
C语言字原生符串底层是使用一个n+1个字符长度的char类型数据实现的,所以每次增长或缩短一个原生字符串,程序都要对这个字符串数组进行一次内存重分配操作:
同时因为内存重分配涉及复杂的算法,并且可能需要执行系统调用,所以它通常是一个比较耗时的操作。Redis经常被用于速度要求严苛、数据被频繁修改的场合,如果每次修改字符串都需要执行一次内存重分配的话,那么对于性能会造成很大影响。
SDS 在分配了内存之后(往往空间会存在盈余,也就是空间的预分配),然后自己通过len 和 free 来维护已使用的和未使用的内存,不再依赖系统来重新划分,这样能有效的提升性能。
空间预分配
用于字符串增长操作,当字符串增长时,程序会先检查需不需要对SDS空间进行扩展,如果需要扩展,程序不仅会为SDS分配修改所必要的空间,还会为SDS分配额外的未使用空间,额外分配的未使用空间公式如下:
SDS空间 < 1MB
如果对SDS修改之后,SDS的长度(修改之后len属性的值)小于1MB,那么则分配和len属性同样大小的未使用空间,这时SDS的len属性和free属性的值相同。如:如果修改之后SDS的len将变为10字节,那么程序也会分配10字节的未使用空间,SDS的buf数组实际长度变为10 + 10 + 1 = 21(额外一个字节用于保存结束符\n)
SDS空间 > 1MB
如果对SDS修改之后,SDS的长度大于等于1MB,那么程序会分配1MB的未使用空间。如:修改之后的len将变为10MB,那么程序会分配1MB的未使用空间,SDS的bug数组长度为10MB + 1MB + 1byte
SDS空间 > 512MB
Game over~ 报错!
惰性空间释放
用于优化SDS的字符串收缩操作,当字符串收缩时,程序不会立即执行内存重分配来回收收缩后内存多出来的空间,而是使用free属性记录下来,以备将来使用。
通过空间预分配,Redis可以减少连续执行字符串增长操作所需的内存重分配次数,通过惰性空间释放,SDS避免了缩短字符串时所需的内存重分配操作,并为将来由可能的增长操作提供了优化。
Redis 数据结构 之 SDS的更多相关文章
- Redis数据结构之sds基本操作函数
本文及后续文章,Redis版本均是v3.2.8 本篇文章讲解sds基本操作函数,我们从源码角度来进一步理解. 一.sds创建函数和销毁 sds创建函数 /* Create a new sds stri ...
- Redis—数据结构之sds
Redis是一个Key Value数据库.Redis有5种数据类型:字符串.列表.哈希.集合.有序集合.而字符串的底层实现方法之一就是使用sds.以下描述中请读者注意区分sds是指简单动态字符串这一数 ...
- Redis数据结构:SDS
1. 简单动态字符串(simple dynamic string,SDS)是Redis的默认字符串表示结构,底层的string都是基于SDS实现.Redis基于C语言,并引用了部分C函数. 使用场景: ...
- redis数据结构存储SDS设计细节(redis的设计与实现笔记)
redis虽说是用C语言开发的,但是redis考虑了性能.安全性.效率性.功能等要,redis底层存储字符串实现,自己实现了名为简单动态字符串(Simple dynamic string)简称SDS的 ...
- redis数据结构之SDS
简介 redis源码虽然是C语言实现的,但是Redis没有直接采用C语言传统的字符串表示,而是构建了一种名叫简单动态字符串(simple dynamic string,SDS)的抽象类型,并将SDS用 ...
- Redis数据结构之robj
本文及后续文章,Redis版本均是v3.2.8 我们知道一个database内的这个映射关系是用一个dict来维护的.dict的key固定用一种数据结构来表达,这这数据结构就是动态字符串sds.而va ...
- Redis 的底层数据结构(SDS和链表)
Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库.缓存和消息中间件.可能几乎所有的线上项目都会使用到 Redis,无论你是做缓存.或是用作消息中间件,用起来很简单方便 ...
- 深入理解Redis 数据结构—简单动态字符串sds
Redis是用ANSI C语言编写的,它是一个高性能的key-value数据库,它可以作用在数据库.缓存和消息中间件.其中 Redis 键值对中的键都是 string 类型,而键值对中的值也是有 st ...
- Redis数据结构底层知识总结
Redis数据结构底层总结 本篇文章是基于作者黄建宏写的书Redis设计与实现而做的笔记 数据结构与对象 Redis中数据结构的底层实现包括以下对象: 对象 解释 简单动态字符串 字符串的底层实现 链 ...
随机推荐
- Multisim-74LS08\74LS02\74LS86逻辑功能仿真实验
一. 实验目的 了解TTL门电路的外观封装.引脚分布和使用方法. 掌握数字电路试验台.万用表和示波器的使用方法. 掌握TTL与门.或非门和异或门的逻辑功能. 认识门电路对信号的控制作用. 二.实验内容 ...
- 项目readme文件目录生成工具 treer
生成目录的工具呢有tree和treer,但是tree不知道怎么忽略node_modules文件夹, 而treer就简单了,下面就是基本的命令了 其中-i是指忽略xxx, -e是指导出 安装 npm i ...
- 【Java8新特性】面试官:谈谈Java8中的Stream API有哪些终止操作?
写在前面 如果你出去面试,面试官问了你关于Java8 Stream API的一些问题,比如:Java8中创建Stream流有哪几种方式?(可以参见:<[Java8新特性]面试官问我:Java8中 ...
- [SD心灵鸡汤]000.每月一则 - 索引
[SD心灵鸡汤]001.每月一则 - 2015.05 [SD心灵鸡汤]002.每月一则 - 2015.06 [SD心灵鸡汤]003.每月一则 - 2015.07 [SD心灵鸡汤]004.每月一则 - ...
- 接口(interface)的使用
类实现接口就具有接口的功能 实现可以多实现,实现多个接口 package cm.aff.abst; /* 接口(interface)是与类并行的一个概念 1. 接口可以看做是一个特殊的抽象类,是常量与 ...
- Beta冲刺 —— 5.31
这个作业属于哪个课程 软件工程 这个作业要求在哪里 Beta冲刺 这个作业的目标 Beta冲刺 作业正文 正文 github链接 项目地址 其他参考文献 无 一.会议内容 1.讨论并解决每个人存在的问 ...
- chrome和Firefox浏览器渲染页面的不同
一直很好奇chrome和firefox这两大浏览器的页面渲染有什么不同,今天自己写了些html代码来做了下检验. 先做html编码,代码如下: <!DOCTYPE html><htm ...
- Redis 入门到分布式 (五) Redis持久化的取舍和选择
个人博客网:https://wushaopei.github.io/ (你想要这里多有) Redis持久化的取舍和选择 持久化的作用 RDB AOF RDB和AOF的选择 一.持久化的作用 ...
- Jquery拓展方法
拓展JQuery一般有两个方法: 1.全局拓展 比如 $.ajax()就是全局函数 拓展方法: Jquery.extend(); 比如: $.extend({ hello:function(mynam ...
- java实现海盗比酒量
** 海盗比酒量** 有一群海盗(不多于20人),在船上比拼酒量.过程如下:打开一瓶酒,所有在场的人平分喝下,有几个人倒下了.再打开一瓶酒平分,又有倒下的,再次重复- 直到开了第4瓶酒,坐着的已经所剩 ...