Redis原理:动态字符串SDS

news2024/10/7 0:51:42

(课程总结自b站黑马程序员课程)

一、引言

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

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

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

②非二进制安全:指‘/0’字符的读取问题。

③不可修改 Redis构建了一种新的字符串结构,称为简单动态字符串(Simple Dynamic String),简称SDS。

二、源码分析

struct __attribute__ ((__packed__)) sdshdr5 {
    unsigned char flags; /* 3 lsb of type, and 5 msb of string length */
    char buf[];
};
struct __attribute__ ((__packed__)) sdshdr8 {
    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__)) sdshdr16 {
    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__)) sdshdr32 {
    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__)) sdshdr64 {
    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[];
};

#define SDS_TYPE_5  0
#define SDS_TYPE_8  1
#define SDS_TYPE_16 2
#define SDS_TYPE_32 3
#define SDS_TYPE_64 4

以sdshdr8为例进行分析:

struct __attribute__ ((__packed__)) sdshdr8 {
    uint8_t len; //已使用字符串字节数,不包括结束标志
    uint8_t alloc; //申请总字节数,不包括结束标志
    unsigned char flags; //SDS头信息
    char buf[];
};

这个的uint8_t len记录的字节长度,8位二进制的最大值为255,也就是可以记录最大255字节数的字符串。c语言中char的占用的字节数为1,也就是sdshdr8可以记录长度为255的字符串。

三、结构分析

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

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

 

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

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

如果新字符串大于1M,则新空间为扩展后字符串长度+1M+1。称为内存预分配。

(申请分配内存需要Linux从用户态切换到内核态,这个过程需要运用的资源相当多,内存预分配可以在很大程度上节省资源分配)

四、优点 

①获取字符串长度的时间复杂度为O(1)。

②支持动态扩容。

③减少内存分配次数。

④二进制安全。

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

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

相关文章

FD2257H 带有嵌入式霍尔传感器的智能电机驱动器芯片

FD2257H 带有嵌入式霍尔传感器的智能电机驱动器芯片 特征 电机驱动器与高灵敏度霍尔效应传感器 h桥MOS驱动器 锁关闭保护和自动重启功能 “软开关“相切换技术减少振动和声噪音 热停机保护(TSD) 可在SIP-4L包 12V或24V DC电机/风扇系统 一般说明 FD2257H…

Day8:浅谈useMemo

「目标」: 持续输出!每日分享关于web前端常见知识、面试题、性能优化、新技术等方面的内容。 Day8-今日话题 useMemo 是 React 中一个有力的性能优化Hook。可从「用法」、「工作原理」、「作用」、「优缺点」、「使用场景」、「使用注意点」进行学习、复习。 拿vue作…

【LangChain系列 5】Prompt模版——特征库

原文地址:【LangChain系列 5】Prompt模版——特征库 本文速读: Feast Featureform 特征库(feature stores)是传统机器学习中的一个概念,本质上是数据,不同维度/属性的数据,而且可以保持同步更新,所以可以…

React中函数式组件与类组件有何不同?

Function Component 与 Class Component 有何不同 目录 Function Component 与 Class Component 有何不同 文章核心观点: 解释一下: 总结: 文章核心观点: Function components capture the rendered values.函数式组件捕获…

【PyQT5教程】-02-UI组件

1.按钮 QtWidgets模块提供了多种按钮类,让你可以轻松地创建各种类型的按钮 1.1 QPushButton(普通按钮) QPushButton是PyQt5中最常见的按钮类型之一,用于触发动作或执行操作。通过信号与槽机制,你可以将按钮的点击事…

性能测试 —— 生成html测试报告、参数化、jvm监控

1.生成HTML的测试报告 1.1配置 (1)找到jmeter 的安装目录,下的bin中的jmeter.properties(jmeter配置文件) (2) ctrl f ,搜索jmeter.save.saveservice.output_format,取消井号 并且 把等号后的xml改为csv,…

基于Intel优化的淡水养殖水质溯源方案

基于AI的淡水养殖水质溯源、优化系统方案 前言一、核心痛点及关键需求1.政策引导及产业升级2.紧跟时事及供给变化3.品牌打造,重拾消费者信赖4.特色生态新模式 二、方案设计1.水质溯源档案2.数字孪生系统3.基于intel AI 水质预测算法 三、实践案例1、方案简述2、数据…

聊聊低代码的全栈开发能力

一、前言 低代码的热度持续提升,最明显的举动就是资本真金白银的投资。 阿里推出“云钉一体”战略,为企业提供全生命周期的IT解决文案;腾讯将各个事业部的低代码平台进行整合,推出了OTeam平台。网易有数帆轻舟低代码平台&#xff…

CentOS7无法连接网络 右上角网络图标消失

在使用 linux 的过程中,有时会出现网络图标消失的问题,这时系统会没有网络。 有些 linux 的网络连接由 NetworkManager 管理, 问题应由它解决。 先执行一下 systemctl restart NetworkManager 看有没有效果。 原因一 :NetworkMan…

Kafka3.1部署和Topic主题数据生产与消费

文章目录 前言一、Kafka3.1X版本在Windows11主机部署二、Kafk生产Topic主题数据1.kafka生产数据2.JAVA kafka客户端消费数据 总结 前言 本章节主要讲述Kafka3.1X版本在Windows11主机下部署以及JAVA对Kafka应用: 一、Kafka3.1X版本在Windows11主机部署 1.安装JDK配…

Spring Boot 集成MQTT代码示例

文章目录 1. 简介使用场景 2. 搭建MQTT测试环境服务1. 先创建映射目录2. 创建两个文件2.1. mosquitto.conf 3. 启动 MQTT服务 Docker 容器3.1. 配置用户名和密码3.1.1. 创建密码文件3.1.2. 修改配置文件,追加密码文件 3.2. 重启mosquitto 容器服务 3. 编写测试程序3…

2023--9-8 高斯消元解线性方程组

题目链接&#xff1a;高斯消元解线性方程组 #include <iostream> #include <algorithm> #include <cmath>using namespace std;const int N 110; const double eps 1e-8;int n; double a[N][N];int gauss() {int c, r;for(c 0, r 0; c < n; c){// 找到…

(其他) 剑指 Offer 64. 求1+2+…+n ——【Leetcode每日一题】

❓ 剑指 Offer 64. 求12…n 难度&#xff1a;中等 求 12...n &#xff0c;要求不能使用乘除法、for、while、if、else、switch、case 等关键字及 条件判断语句&#xff08;A?B:C&#xff09;。 示例 1&#xff1a; 输入: n 3 输出: 6 示例 2&#xff1a; 输入: n 9 输出:…

LeetCode(力扣)491. 递增子序列Python

LeetCode491. 递增子序列 题目链接代码 题目链接 https://leetcode.cn/problems/non-decreasing-subsequences/ 代码 class Solution:def backtracking(self, nums, index, result, path):if len(path) > 1:result.append(path[:])uset set()for i in range(index, len…

小程序实现摄像头拍照 + 水印绘制

文章标题 01 功能说明02 使用方式 & 效果图2.1 基础用法2.2 拍照 底部定点水印 预览2.3 拍照 整体背景水印 预览 03 全部代码3.1 页面布局 html3.2 业务核心 js3.3 基础样式 css 01 功能说明 需求&#xff1a;小程序端需要调用前置摄像头进行拍照&#xff0c;并且将拍…

当面试官问你离职原因的时候怎么回答比较好?

所有的前提都是建立在有一定的物质基础&#xff0c;当你的一日三餐都成了问题&#xff0c;都需要家庭支持的时候我希望你可以找一份工作&#xff0c;靠自己的本事养活自己从来不丢人&#xff0c;我觉得死要面子活受罪才是真的让你看不起。 所有的建议都是建立在我们是普通打工人…

如何用Jmeter编写脚本压测?

随着商业业务不断扩张&#xff0c;调用adsearch服务频率越来越高&#xff0c;所以这次想做个压测&#xff0c;了解目前多少并发量可以到达adsearch服务的界值。 这次选用的jmeter压测工具&#xff0c;压测思路如图&#xff1a; 一、日志入参 日志选取的adsearch 的 getads部分…

电工-什么是电流

什么是电流&#xff1f;电流计算公式和单位换算及电流方向讲解 前面了解到电路的基本组成是包括&#xff1a;电能、负载、导线构成的&#xff0c;而这电路就是电流流通的路径&#xff0c;那么什么是电流呢&#xff1f;下面就讲讲电流形成的基本概念以及电流计算公式、单位和方…

2023-9-8 求组合数(二)

题目链接&#xff1a;求组合数 II #include <iostream> #include <algorithm>using namespace std;typedef long long LL; const int mod 1e9 7; const int N 100010;// 阶乘&#xff0c;阶乘的逆 int fact[N], infact[N];LL qmi(int a, int k, int p) {int res…

HTTPS 之fiddler抓包--jmeter请求

一、浅谈HTTPS 我们都知道HTTP并非是安全传输&#xff0c;在HTTPS基础上使用SSL协议进行加密构成的HTTPS协议是相对安全的。目前越来越多的企业选择使用HTTPS协议与用户进行通信&#xff0c;如百度、谷歌等。HTTPS在传输数据之前需要客户端&#xff08;浏览器&#xff09;与服…