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中数据结构的底层实现包括以下对象: 对象 解释 简单动态字符串 字符串的底层实现 链 ...
随机推荐
- 四、Spring-面向切面编程
内容 面向切面编程基本原理 通过POJO创建切面 使用@AspectJ注解 为AspectJ切面注入依赖 关键词 横切关注点(cross-cutting concern) 继承 (inheritanc ...
- Python 每日一练(2)
引言 我又双叒叕的来啦,新博客的第二篇文章,这次是继之前公众号上每日一练的第二个,这次是专题实对于文件的一些处理的练习 主要有以下几类: 1.实现英文文章字频统计 2.统一剪裁某一指定目录下的所有图片 ...
- (八)Filter&ThreadLocal实现处理事务
ConnectionContext.java package com.aff.bookstore.web; import java.sql.Connection; public class Conne ...
- Linux实验
实验一 Linux系统安装与简单配置 一.实验目的 1.掌握Linux系统安装的分区准备. 2.掌握Linux系统的安装步骤. 3.掌握Linux系统分区的挂载和卸载. 4.掌握Linux系统的启动和 ...
- 01 . RabbitMQ简介及部署
RabbitMQ简介 MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法.应用程序通过读写出入队列的消息(针对应用程序的数据)来通信,而无需专用连接来链接它 ...
- 拨号vps,拨号vps是什么意思干什么用的,如何使用拨号vps
首先,拨号vps是动态IP的VPS.vps虚拟服务器.拨号服务器.有些业务,如刷单.投票等操作对ip地址有限制,不能过多的使用.而拨号VPS通过拨号上网,每拨号一次号,就变一次IP,完成ip地址的动态 ...
- Rocket - debug - TLDebugModuleInner - Hart Bus Access
https://mp.weixin.qq.com/s/deNMEyJ1idJDVoZwwo0A1A 简单介绍TLDebugModuleInner中核心总线访问(Hart Bus Access). 参考 ...
- jchdl - GSL实例 - LogicalLeft
https://mp.weixin.qq.com/s/WNm4bLWzZ0oWHWa7HQ6Y6w 逻辑左移,继承自Shifter类.只需要实现shift方法即可. 参考链接 https:// ...
- 一文带你了解js数据储存及深复制(深拷贝)与浅复制(浅拷贝)
背景 在日常开发中,偶尔会遇到需要复制对象的情况,需要进行对象的复制. 由于现在流行标题党,所以,一文带你了解js数据储存及深复制(深拷贝)与浅复制(浅拷贝) 理解 首先就需要理解 js 中的数据类型 ...
- Java实现 LeetCode 面试题13. 机器人的运动范围(DFS)
面试题13. 机器人的运动范围 地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] .一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左.右.上.下移动一格(不能移动 ...