Redis-简单动态字符串(SDS)

news2024/10/5 13:38:46

文章目录

    • 文章概要
    • SDS数据结构定义
    • SDS和C字符串的区别
    • 总结
    • 参考

文章概要

本篇文章,我们来学习Redis字符串的编码格式SDS编码,文章将将从以下几个方面介绍SDS:

  • SDS的底层数据结构定义
  • Redis是C写的,那SDS和C中的字符串的区别是什么

SDS数据结构定义

//redis/deps/sds.h
/* Note: sdshdr5 is never used, we just access the flags byte directly.
 * However is here to document the layout of type 5 SDS strings. */
struct __attribute__ ((__packed__)) hisdshdr5 {
    unsigned char flags; /* 3 lsb of type, and 5 msb of string length */
    char buf[];
};
struct __attribute__ ((__packed__)) hisdshdr8 {
    uint8_t len; /* used */
    uint8_t alloc; /* excluding the header and null terminator */
    unsigned char flags; /* 3 lsb of type, 5 unused bits */
    char buf[];
};
struct __attribute__ ((__packed__)) hisdshdr16 {
    uint16_t len; /* used */
    uint16_t alloc; /* excluding the header and null terminator */
    unsigned char flags; /* 3 lsb of type, 5 unused bits */
    char buf[];
};
struct __attribute__ ((__packed__)) hisdshdr32 {
    uint32_t len; /* used */
    uint32_t alloc; /* excluding the header and null terminator */
    unsigned char flags; /* 3 lsb of type, 5 unused bits */
    char buf[];
};
struct __attribute__ ((__packed__)) hisdshdr64 {
    uint64_t len; /* used */
    uint64_t alloc; /* excluding the header and null terminator */
    unsigned char flags; /* 3 lsb of type, 5 unused bits */
    char buf[];
};

以上代码来自Redis的源码,其中包含了redis关于sds字符串编码的定义。从源码中可以看出,redis定义了5种sds的编码,但是hisdshdr5 被声明是没有被使用的,它的定义个后面的四种也略显区别。根据注释的描述,该结构只是为了展示 5 型sds的布局结构,flags的低3位表示类型,高5位表示字符串的长度。

重点看后面的几种定义。

各个字段的含义

  • len 表示实际字符串的长度,比如我们存入一个"HELLO",len = 5
  • alloc 表示实际分配给buf的内存空间大小,但是不包括头和空结束符
  • flags 只使用低三位作为有效位,表示sds类型(因为有四种,所以要三位,0不算),高5位未使用
  • buf 存储字符串的字节数组(这里称之为字节数据,而不是字符数组)

在这里插入图片描述

SDS和C字符串的区别

常数时间复杂度获取字符串的长度
这一点是显而易见的,因为在结构体的内部维护了一个变量len来记录实际字符串的长度,而在C语言中, 我们不得不遍历字符串才能获取字符串的长度。

杜绝缓冲区溢出
首先在C语言中,我们如果想在一个字符串后面追加字符串时,如果预先知道该区域还有多少可用的空间,将很容易发生缓冲区溢出的错误。
举个例子:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
	int size = sizeof(char) * 7;
	char *dest = (char*)malloc(size);
	memset(dest, 0, size);
	const char *src = "HelloWorld";
	// 此时将发生缓冲区溢出,因为追加的字符串超出了dest所申请的内存
	char *result = strcat(dest, src);
	free(dest);
	return 0;
}

还有一种情况,假设一个字符串s1和另一个字符串s2相邻存储的,当我们向s1后面追加字符串时,将意外地修改s2的值。
对于SDS存储的字符串,当需要修改值时,相关的API会先检查该SDS所分配的空间是否满足此次修改,如果不满足,将自动执行扩容操作。所以对于SDS存储的字符串,杜绝了缓冲区溢出的可能性。

减少字符串修改时内存重分配的次数

在C语言中,字符串底层实际上是一个字符数组,数组的长度为字符串的长度+1,当对该字符串进行追加和缩减的时候,程序都要对其进行重新分配内存。内存分配涉及系统调用,会发生用户态和内核态的切换,如果大量的这种操作将严重影响程序的性能。
在Redis中,为了减少内存分配的次数,采用了两种内存空间分配的优化策略:

  • 空间预分配
  • 空间惰性删除

空间预分配技术用于优化字符串的增长操作,当程序为字符串分配空间时,不仅会为它分配字符串大小的空间,而且会分配一些未使用的空间,策略如下:

  • 如果修改后字符串的大小小于1MB,则此时未使用的空间和len的大小相等。也就是多分配一倍。
  • 和上面相对应的,如果修改后字符串的大小大于1MB,此时程序会为该SDS分配1MB的未使用空间。

举个例子:

  1. 假设我们要存储一个字符串 “Redis”,此时将分配 11 Bytes = 5(len) + 5(free) + 1(null terminator)的空间
  2. 假设我们要存储的字符串为"…"(20MB),此时将分配 22 Bytes = 20(len) + 1(free) + 1(null terminator)

惰性空间释放策略,SDS避免了缩短字符串时所需的内存重分配操作,并为将来可能有的增长操作提供了优化。
具体来讲,当我们对现存的SDS字符串进行裁剪后,被裁剪的字符串所占用的空间不会被立即释放,当操作系统需要使用的时候才会释放。

二进制安全的
这一点比较容易理解,在C语言字符串是不允许有空字符的,否则程序将编译报错。所以C语言中的char性数组只能用来存储字符数据,无法存储图像、视频等二进制数据。
在Redis的SDS中,虽然也同样遵循在末尾使用’\0’来表示字符串结尾,但是在中间允许有空字符的存在,所以这也是为啥将SDS的buf称为字节数组。

总结

本篇文章分享了Redis的字符串编码结构SDS,了解了它的定义和内存分配策略。以及和C语言字符串的区别。希望你能从本篇文章中获取新的东西。

参考

《Redis设计与实现》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/857663.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

勒索软件野蛮生长,迷雾中企业何去何从

根据GRIT最新发布的勒索软件报告显示&#xff0c;今年二季度观测到的勒索软件事件数量明显多于一季度&#xff0c;而导致这一情况的三大原因分别为&#xff1a;漏洞的大规模利用、勒索软件工具技术的“民主化”以及新兴勒索软件组织的野蛮生长。 报告公布了2023年最活跃最多产的…

第9集丨Vue 江湖 —— 监测数据原理

目录 一、修改数据时的一个问题1.1 现象一1.2 现象二 二、Vue监测数据原理2.1 模拟一个数据监测2.2 数据劫持2.3 Vue.set()/vm.$set()2.4 基本原理2.4.1 如何监测对象中的数据?2.4.2 如何监测数组中的数据?2.4.3 修改数组中的某个元素 2.5 案例2.5.1 需求功能2.5.2 实现 一、…

【深度学习 video detect】Towards High Performance Video Object Detection for Mobiles

文章目录 摘要IntroductionRevisiting Video Object Detection BaselinePractice for Mobiles Model Architecture for MobilesLight Flow 摘要 尽管在桌面GPU上取得了视频目标检测的最近成功&#xff0c;但其架构对于移动设备来说仍然过于沉重。目前尚不清楚在非常有限的计算…

android studio 实用插件推荐

本文字数&#xff1a;&#xff1a;2352字 预计阅读时间&#xff1a;8分钟 背景 现在做安卓开发的同学基本都是用 Android Studio 了吧&#xff0c;它具有强大的开放性&#xff0c;可以让用户根据自己的需求开发或使用一些插件辅助自己搬砖&#xff0c;当然开发插件我们可能还没…

操作系统—调度算法

进程调度算法 进程调度算法也称CPU调度算法 调度发生时期 当进程从运行状态转到等待状态&#xff1b;当进程从运行状态转到就绪状态&#xff1b;当进程从等待状态转到就绪状态&#xff1b;当进程从运行状态转到终止状态&#xff1b; 其中发生在 1 和 4 两种情况下的调度称为…

工业无线技术应用-无线控制斗轮机启停、故障等开关信号

斗轮堆取料机是一种对散料进行连续堆取作业的高效装卸大型机械,被广泛使用于火力发电厂和炼焦厂的输煤系统中。目前对斗轮机的技改主要为将斗轮机的部分程控信号改为无线传输&#xff0c;取代卷筒电机和电缆的应用。 多数情况下都是利用无线通讯做媒介&#xff0c;让工作人员通…

Shopee买家通系统可全自动批量注册虾皮买家号

Shopee买家通系统可批量注册虾皮买家号&#xff0c;如果想要拥有大量虾皮买家号&#xff0c;完全可以试试&#xff0c; 不过在注册之前我们需要先准备好账号所需要的资料&#xff0c;比如邮箱、手机号、ip、收货地址等。不过想要账号能自动化&#xff0c;对于账号资料也是有一…

SSL证书DV和OV的区别?

SSL证书是在互联网通信中保护数据传输安全的一种加密工具。它能够确保客户端和服务器之间的通信得以加密&#xff0c;防止第三方窃听或篡改信息。在选择SSL证书时&#xff0c;常见的有DV证书和OV证书&#xff0c;它们在验证标准和信任级别上有所不同。那么SSL证书DV和OV的有哪些…

TEC2083BS-PD码转换器(解决博世矩阵控制PELCO派尔高球机的问题)

TEC2083BS-PD码转换器 使用说明 1.设备概述 控制码转换器在安防工程中起着非常重要的角色&#xff0c;随着高速球型摄像机在安防工程中大范围的使用&#xff0c;而高速球厂家都因为某些原因很少使用博世、飞利浦的协议。为此&#xff0c;工程商经常会遇到博世协议和PELCO协议之…

【Oracle 数据库 SQL 语句 】积累1

Oracle 数据库 SQL 语句 1、分组之后再合计2、显示不为空的值 1、分组之后再合计 关键字&#xff1a; grouping sets &#xff08;&#xff08;分组字段1&#xff0c;分组字段2&#xff09;&#xff0c;&#xff08;&#xff09;&#xff09; select sylbdm ,count(sylbmc) a…

Vue [Day6]

路由进阶 路由模块的封装抽离 src/router/index.js import VueRouter from vue-router // 用绝对路径的方式来写目录 相当于src import Find from /views/Find import Friend from ../views/Friend import My from ../views/Myimport Vue from vue Vue.use(VueRouter)con…

Idea 反编译jar包

实际项目中&#xff0c;有时候会需要更改jar包源码来达到业务需求&#xff0c;本文章将介绍一下如何通过Idea来进行jar反编译 1、Idea安装decompiler插件 2、找到decompiler插件文件夹 decompiler插件文件夹路径为&#xff1a;idea安装路径/plugins/java-decompiler/lib 3、…

移动端的Flex布局

目录 引入 一、传统布局与flex布局 传统性 flex布局 二、felx的特点 三、flex布局父项的常见属性 四、flex布局子项的常见方向 总结 引入 flex 是 flexible Box的缩写&#xff0c;意为“弹性布局”&#xff0c;用来为盒状模型提供最大的灵活性&#xff0c;任何一个容器…

成像质量高精度标定高均匀光源积分球

随着航天遥感技术的发展&#xff0c;对遥感仪器的定标精度要求越来越高&#xff0c;这就需要高精度的工程应用定标光源。光学定标&#xff0c;在工程应用上是采用光学标准传递的方法对应用设备进行定标&#xff0c;而不是直接用原始标准对应用设备进行定标。其传递链路之一&…

树莓派安装ubuntu

ubuntu包下载 从ubuntu 官网下载镜像&#xff1a;https://cn.ubuntu.com/blog/build-raspberry-pi-desktop-ubuntu 按个人需求下载&#xff0c;可以首先使用 桌面版22.04 LTS版本&#xff1b; 烧录 从树莓派管官网下载image烧录工具&#xff1a;https://www.raspberrypi.c…

Improved Deep Metric Learning with Multi-class N-pair Loss Objective

Improved Deep Metric Learning with Multi-class N-pair Loss Objective 来源&#xff1a; NIPS’2016NEC Laboratories America 文章目录 Improved Deep Metric Learning with Multi-class N-pair Loss ObjectiveDistance Metric LearningDeep Metric Learning with Multip…

实战:使用Docker部署Hadoop集群

文章目录 Hadoop简介Hadoop优势Hadoop应用场景docker与docker-compose安装Hadoop集群搭建环境变量docker-compose环境文件树结构编排并运行容器运行wordcount例子 写在最后 Hadoop简介 Hadoop是一个由Apache基金会所开发的分布式系统基础架构。用户可以在不了解分布式底层细节…

ChatGLM2-6B在windows下的部署

2023-08-10 ChatGLM2-6B在windows下的部署 一、部署环境 1、Windows 10 专业版&#xff0c; 64位&#xff0c;版本号&#xff1a;22H2&#xff0c;内存&#xff1a;32GB 2、已安装CUDA11.3 3、已安装Anaconda3 64bit版本 4、有显卡NVIDIA GeForce RTX 3060 Laptop GPU …

AI Deep Reinforcement Learning Autonomous Driving(深度强化学习自动驾驶)

AI Deep Reinforcement Learning Autonomous Driving&#xff08;深度强化学习自动驾驶&#xff09; 背景介绍研究背景研究目的及意义项目设计内容算法介绍马尔可夫链及马尔可夫决策过程强化学习神经网络 仿真平台OpenAI gymTorcs配置GTA5 参数选择行动空间奖励函数 环境及软件…

8.10CPI决战日来临,黄金会意外走高吗?

近期有哪些消息面影响黄金走势&#xff1f;黄金多空该如何研判&#xff1f; ​黄金消息面解析&#xff1a;周四(8月10日)亚市早盘&#xff0c;美元指数在102.50维持多头走势&#xff0c;黄金避险情绪消散&#xff0c;金价跌至1916美元&#xff0c;下破1900美元前景深化。周三黄…