Redis入门到通关之数据结构解析-动态字符串SDS

2024-04-23 08:52

本文主要是介绍Redis入门到通关之数据结构解析-动态字符串SDS,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • Redis数据结构-动态字符串
  • 动态扩容举例
  • 二进制安全
  • SDS优点
  • 与C语言中的字符串的区别


在这里插入图片描述

欢迎来到 请回答1024 的博客

🍓🍓🍓欢迎来到 请回答1024的博客

关于博主: 我是 请回答1024,一个追求数学与计算的边界、时间与空间的平衡,0与1的延伸的后端开发者。

博客特色: 在我的博客中,开设了如下专栏(点击可以进入专栏奥~): Java、MySQL、Redis、Spring、SpringBoot、SpringCloud、RabbitMQ、微服务、分布式 等相关技术专栏。期待与您一起,探索编程世界中的发现和创新之旅。

🍎🍎🍎我的主页 : https://reply1024.blog.csdn.net

敬请期待定期更新、见解和教程!让我们一起踏上这段编码冒险之旅!

数学与计算的边界 时间与空间的平衡 0与1的延伸


Redis数据结构-动态字符串

我们都知道 Redis 中保存的Key是字符串,value 往往是字符串或者字符串的集合。可见字符串是 Redis 中最常用的一种数据结构。

不过 Redis 没有直接使用C语言中的字符串,因为C语言字符串存在很多问题:

  • 获取字符串长度的需要通过运算

  • 非二进制安全

  • 不可修改

Redis 构建了一种新的字符串结构,称为简单动态字符串(Simple Dynamic String),简称 SDS
例如,我们执行命令:

set name 技术

那么 Redis 将在底层创建两个 SDS,其中一个是包含“name”的 SDS,另一个是包含“技术”的 SDS。

Redis 是 C 语言实现的,其中 SDS 是一个结构体,源码如下:

在这里插入图片描述

#include <stdio.h>
#include <stdlib.h>
#include <string.h>typedef struct sds {int len;         // 记录字符串的长度int free;        // 记录未使用的字节数char buf[];      // 字符串的实际存储空间
} sds;// 创建一个新的 sds
sds *sds_new(int init_len) {sds *s = malloc(sizeof(sds) + init_len + 1);if (!s) return NULL;s->len = 0;s->free = init_len;s->buf[0] = '\0';return s;
}// 释放 sds
void sds_free(sds *s) {if (s) free(s);
}// 追加字符串到 sds
sds *sds_append(sds *s, const char *append) {int append_len = strlen(append);if (s->free < append_len) {s = realloc(s, sizeof(sds) + s->len + append_len + 1);if (!s) return NULL;s->free = append_len;}memcpy(s->buf + s->len, append, append_len);s->len += append_len;s->free -= append_len;s->buf[s->len] = '\0';return s;
}// 打印 sds
void sds_print(const sds *s) {printf("Length: %d\n", s->len);printf("Free: %d\n", s->free);printf("String: %s\n", s->buf);
}int main() {sds *str = sds_new(10);if (!str) {printf("Error: Unable to create SDS.\n");return 1;}str = sds_append(str, "Hello, ");if (!str) {printf("Error: Unable to append to SDS.\n");return 1;}str = sds_append(str, "world!");if (!str) {printf("Error: Unable to append to SDS.\n");return 1;}sds_print(str);sds_free(str);return 0;
}

例如,一个包含字符串“name”的sds结构如下:

在这里插入图片描述


动态扩容举例

SDS 之所以叫做动态字符串,是因为它具备动态扩容的能力,例如一个内容为“hi”的SDS:

在这里插入图片描述

假如我们要给SDS追加一段字符串“,Amy”,这里首先会申请新内存空间:

  • 如果新字符串小于1M,则新空间为扩展后字符串长度的两倍+1;

  • 如果新字符串大于1M,则新空间为扩展后字符串长度+1M+1。称为内存预分配
    在这里插入图片描述

二进制安全

  • Redis 可以存储各种数据类型,那么二进制数据肯定也不例外。但二进制数据并不是规则的字符串格式,可能会包含一些特殊的字符,比如 ‘\0’ 等。
  • 前面我们提到过,C 中字符串遇到 ‘\0’ 会结束,那 ‘\0’ 之后的数据就读取不上了。但在 SDS 中,是根据 len 长度来判断字符串结束的。
  • 如此, 二进制安全的问题就解决了。

SDS优点

SDS 优点:

  1. 获取字符串长度的时间复杂度为O(1)
  2. 支持动态扩容, 减少内存分配次数
  3. 二进制安全

与C语言中的字符串的区别

SDS(Simple Dynamic String)是Redis使用的一种字符串表示方式,与C语言中的字符串有一些显著的区别:

  • 动态调整大小:SDS是动态分配内存的,可以根据需要动态增加或减少其大小,而C语言中的字符串通常是静态分配的,大小在创建时就确定了,后续无法直接调整大小。

  • 二进制安全:SDS允许存储任意二进制数据,而C语言中的字符串通常以NULL结尾,因此不适合存储包含NULL字符的二进制数据。

  • 惰性空间释放:SDS采用惰性空间释放策略,即当SDS的内容被截断或缩短时,并不立即释放多余的内存,而是等待下一次需要扩展空间时才释放。这种策略可以减少频繁的内存分配和释放操作,提高性能。而C语言中的字符串在缩短时无法自动释放多余的内存,需要手动管理内存。

  • 长度存储:SDS在内部存储了字符串的长度信息,这样可以在O(1)时间内获取字符串的长度,而C语言中的字符串需要遍历整个字符串才能确定长度。

SDS是一种更加灵活和高效的字符串表示方式,特别适合需要频繁修改和操作字符串的场景,而C语言中的字符串更适合于静态不变的情况。


在这里插入图片描述


这篇关于Redis入门到通关之数据结构解析-动态字符串SDS的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/928333

相关文章

Linux中shell解析脚本的通配符、元字符、转义符说明

《Linux中shell解析脚本的通配符、元字符、转义符说明》:本文主要介绍shell通配符、元字符、转义符以及shell解析脚本的过程,通配符用于路径扩展,元字符用于多命令分割,转义符用于将特殊... 目录一、linux shell通配符(wildcard)二、shell元字符(特殊字符 Meta)三、s

Java 字符数组转字符串的常用方法

《Java字符数组转字符串的常用方法》文章总结了在Java中将字符数组转换为字符串的几种常用方法,包括使用String构造函数、String.valueOf()方法、StringBuilder以及A... 目录1. 使用String构造函数1.1 基本转换方法1.2 注意事项2. 使用String.valu

Redis主从/哨兵机制原理分析

《Redis主从/哨兵机制原理分析》本文介绍了Redis的主从复制和哨兵机制,主从复制实现了数据的热备份和负载均衡,而哨兵机制可以监控Redis集群,实现自动故障转移,哨兵机制通过监控、下线、选举和故... 目录一、主从复制1.1 什么是主从复制1.2 主从复制的作用1.3 主从复制原理1.3.1 全量复制

Redis延迟队列的实现示例

《Redis延迟队列的实现示例》Redis延迟队列是一种使用Redis实现的消息队列,本文主要介绍了Redis延迟队列的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习... 目录一、什么是 Redis 延迟队列二、实现原理三、Java 代码示例四、注意事项五、使用 Redi

Redis缓存问题与缓存更新机制详解

《Redis缓存问题与缓存更新机制详解》本文主要介绍了缓存问题及其解决方案,包括缓存穿透、缓存击穿、缓存雪崩等问题的成因以及相应的预防和解决方法,同时,还详细探讨了缓存更新机制,包括不同情况下的缓存更... 目录一、缓存问题1.1 缓存穿透1.1.1 问题来源1.1.2 解决方案1.2 缓存击穿1.2.1

redis-cli命令行工具的使用小结

《redis-cli命令行工具的使用小结》redis-cli是Redis的命令行客户端,支持多种参数用于连接、操作和管理Redis数据库,本文给大家介绍redis-cli命令行工具的使用小结,感兴趣的... 目录基本连接参数基本连接方式连接远程服务器带密码连接操作与格式参数-r参数重复执行命令-i参数指定命

深入理解Redis大key的危害及解决方案

《深入理解Redis大key的危害及解决方案》本文主要介绍了深入理解Redis大key的危害及解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着... 目录一、背景二、什么是大key三、大key评价标准四、大key 产生的原因与场景五、大key影响与危

VUE动态绑定class类的三种常用方式及适用场景详解

《VUE动态绑定class类的三种常用方式及适用场景详解》文章介绍了在实际开发中动态绑定class的三种常见情况及其解决方案,包括根据不同的返回值渲染不同的class样式、给模块添加基础样式以及根据设... 目录前言1.动态选择class样式(对象添加:情景一)2.动态添加一个class样式(字符串添加:情

Redis主从复制的原理分析

《Redis主从复制的原理分析》Redis主从复制通过将数据镜像到多个从节点,实现高可用性和扩展性,主从复制包括初次全量同步和增量同步两个阶段,为优化复制性能,可以采用AOF持久化、调整复制超时时间、... 目录Redis主从复制的原理主从复制概述配置主从复制数据同步过程复制一致性与延迟故障转移机制监控与维

python修改字符串值的三种方法

《python修改字符串值的三种方法》本文主要介绍了python修改字符串值的三种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学... 目录第一种方法:第二种方法:第三种方法:在python中,字符串对象是不可变类型,所以我们没办法直接