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

相关文章

使用Redis快速实现共享Session登录的详细步骤

《使用Redis快速实现共享Session登录的详细步骤》在Web开发中,Session通常用于存储用户的会话信息,允许用户在多个页面之间保持登录状态,Redis是一个开源的高性能键值数据库,广泛用于... 目录前言实现原理:步骤:使用Redis实现共享Session登录1. 引入Redis依赖2. 配置R

shell脚本批量导出redis key-value方式

《shell脚本批量导出rediskey-value方式》为避免keys全量扫描导致Redis卡顿,可先通过dump.rdb备份文件在本地恢复,再使用scan命令渐进导出key-value,通过CN... 目录1 背景2 详细步骤2.1 本地docker启动Redis2.2 shell批量导出脚本3 附录总

批量导入txt数据到的redis过程

《批量导入txt数据到的redis过程》用户通过将Redis命令逐行写入txt文件,利用管道模式运行客户端,成功执行批量删除以Product*匹配的Key操作,提高了数据清理效率... 目录批量导入txt数据到Redisjs把redis命令按一条 一行写到txt中管道命令运行redis客户端成功了批量删除k

深度解析Spring Security 中的 SecurityFilterChain核心功能

《深度解析SpringSecurity中的SecurityFilterChain核心功能》SecurityFilterChain通过组件化配置、类型安全路径匹配、多链协同三大特性,重构了Spri... 目录Spring Security 中的SecurityFilterChain深度解析一、Security

MySQL常用字符串函数示例和场景介绍

《MySQL常用字符串函数示例和场景介绍》MySQL提供了丰富的字符串函数帮助我们高效地对字符串进行处理、转换和分析,本文我将全面且深入地介绍MySQL常用的字符串函数,并结合具体示例和场景,帮你熟练... 目录一、字符串函数概述1.1 字符串函数的作用1.2 字符串函数分类二、字符串长度与统计函数2.1

Redis客户端连接机制的实现方案

《Redis客户端连接机制的实现方案》本文主要介绍了Redis客户端连接机制的实现方案,包括事件驱动模型、非阻塞I/O处理、连接池应用及配置优化,具有一定的参考价值,感兴趣的可以了解一下... 目录1. Redis连接模型概述2. 连接建立过程详解2.1 连php接初始化流程2.2 关键配置参数3. 最大连

全面解析Golang 中的 Gorilla CORS 中间件正确用法

《全面解析Golang中的GorillaCORS中间件正确用法》Golang中使用gorilla/mux路由器配合rs/cors中间件库可以优雅地解决这个问题,然而,很多人刚开始使用时会遇到配... 目录如何让 golang 中的 Gorilla CORS 中间件正确工作一、基础依赖二、错误用法(很多人一开

Spring WebClient从入门到精通

《SpringWebClient从入门到精通》本文详解SpringWebClient非阻塞响应式特性及优势,涵盖核心API、实战应用与性能优化,对比RestTemplate,为微服务通信提供高效解决... 目录一、WebClient 概述1.1 为什么选择 WebClient?1.2 WebClient 与

Mysql中设计数据表的过程解析

《Mysql中设计数据表的过程解析》数据库约束通过NOTNULL、UNIQUE、DEFAULT、主键和外键等规则保障数据完整性,自动校验数据,减少人工错误,提升数据一致性和业务逻辑严谨性,本文介绍My... 目录1.引言2.NOT NULL——制定某列不可以存储NULL值2.UNIQUE——保证某一列的每一

深度解析Nginx日志分析与499状态码问题解决

《深度解析Nginx日志分析与499状态码问题解决》在Web服务器运维和性能优化过程中,Nginx日志是排查问题的重要依据,本文将围绕Nginx日志分析、499状态码的成因、排查方法及解决方案展开讨论... 目录前言1. Nginx日志基础1.1 Nginx日志存放位置1.2 Nginx日志格式2. 499