Redis數據結構——Redis簡單動態字符串SDS

定義

眾所周知,Redis是由C語言寫的。
對于字符串類型的數據存儲,Redis并沒有直接使用C語言中的字符串。
而是自己構建了一個結構體,叫做“簡單動態字符串”,簡稱SDS,比C語言中的字符串更加靈活。

SDS的結構體是這樣的:

struct{int len; // 數組中已使用的字節的數量,即真實的內容長度 int free; // 數組中未使用的字節的數量,即還可以繼續存儲的內容的長度 char buff[]; // 字節數組,用來保存字符串 
};

在C語言中,總是使用長度是N+1的字符數組來保存長度為N的字符串,并且字符數組的最后一個是’\0’結束符,在SDS中,一次申請的字符串的長度比真實的長,所以才會有free這個屬性

SDS與C語言字符串相比,優點是:

  • O(1)復雜度獲取字符串長度
  • 防止了內存溢出
  • 減少內存分配的次數
  • 二進制安全

獲取字符串長度

對于C字符串來說,獲取一個字符串的真實長度,需要遍歷字符串,這就是O(N)的時間復雜度。
而在SDS中,用一個len屬性保存字符串的真實長度,每次對字符串的修改,都會維護這個len屬性
因此對于SDS來說,獲取字符串的真實長度的時間復雜度是O(1),這確保了獲取字符串長度的操作不會成為Redis字符串的性能瓶頸

內存溢出問題

在C字符串中,如果要對字符串進行修改操作,如果忘記了給字符串重新分配足夠的空間,就會導致內存溢出問題。在C語言中,并沒有內存溢出相關的檢查機制,因此可能會導致不可預測的問題產生。

通過SDS的API來操作字符串時,會先檢查SDS的空間是否滿足修改的要求,如果不滿足的話,會自動將SDS的空間擴展至要求的大小,然后執行字符串操作,所以使用SDS來操作字符串,不用擔心內存溢出問題。

減少內存分配的次數

對于C語言字符串,因為總是有一個長度為N+1的字符數組來保存一個長度為N的字符串。
所以,如果對C字符串進行操作:

  • 如果進行字符串的長度增長的操作,比如追加字符append,那么在執行這個操作前,需要先為字符串分配新的內存空間,然后才能執行操作。如果忘記了重新分配內存,會導致內存溢出問題。
  • 如果進行字符串長度的減少操作,比如刪除某個字符,那么在執行這個操作之后,需要釋放掉不再使用的內存空間。如果忘記了釋放內存,會導致內存泄漏問題。

而對于SDS來說,不存在這些問題,通過兩個機制來解決以上問題

  • 空間預分配
  • 惰性空間釋放

1. 空間預分配

空間預分配機制,用來優化SDS字符串的增長操作。
我們認為初始化賦值和拼接操作都是對于SDS的擴容操作。
當SDS來擴容一個字符串時,系統不僅會為SDS分配所需的內存空間大小,還會分配額外的未使用空間,即系統分配給SDS的空間大小比真實的字符串長度要大。
至于,額外的空間有多大,有以下規則:

  • 當擴容后的SDS的長度小于1MB,那么程序分配的額外空間就是len的大小,即與真實的字符串的空間大小相同。例如,擴容后,SDS的len的長度是20,那么額外的空間也是20,總共的SDS的空間是40字節。
  • 如果擴容后的SDS的長度大于等于1MB,那么程序會分配1MB的額外空間。

通過空間預分配策略,可以減少字符串增長操作的內存分配次數。
當進行字符串增長操作時,會先檢查free的空間大小是否夠增加的長度,如果夠,那么直接在真實的數組上操作,無需再進行內存分配操作,并維護free和len的值。
如果不夠,那么就會進行擴容操作,擴容機制上面說過了。

2. 惰性空間釋放

惰性空間釋放用來優化字符串的縮短操作。
當SDS縮短一個字符串時,還是直接在原始的數組上操作,并維護len和free的值。
縮短完成后,程序并不會立即回收釋放后的內存,而是使用free屬性記錄下來,方便下次的字符串長度增加時使用。

二進制安全

C字符串中的字符必須符號某種編碼,例如,當編碼格式是ASCII時,除了末尾的空字符’\0’外,字符串內容中不可以出現空字符,否則程序在讀取字符串時,會誤以為這是字符串的結尾。
這樣的限制使得,C字符串只能保存文本數據,而不能保存圖片、音頻等二進制數據。
而SDS會以二進制的方式來處理存放到buff數組中的數據,程序不會對其中的數據進行限制、過濾等額外操作
這就是我們稱SDS是字節數組的原因——Redis不是用buff數組來保存字符,而是保存一系列的二進制數據

SDS不是使用空字符’\0’來判斷字符串的結尾,而是使用len屬性來判斷字符串是否結尾
如"Redis\0String",C字符串的函數會把’\0’當做結束符來處理,而忽略到后面的"String"。而SDS的buf字節數組不是在保存字符,而是一系列二進制數組,SDS API都會以二進制的方式來處理buf數組里的數據,使用len屬性的值而不是空字符來判斷字符串是否結束。

參考文章

Redis數據結構——簡單動態字符串SDS - 隨心所于 - 博客園
《Redis設計與實現》

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/38346.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/38346.shtml
英文地址,請注明出處:http://en.pswp.cn/news/38346.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Python-OpenCV中的圖像處理-視頻分析

Python-OpenCV中的圖像處理-視頻分析 視頻分析Meanshift算法Camshift算法光流 視頻分析 學習使用 Meanshift 和 Camshift 算法在視頻中找到并跟蹤目標對象: Meanshift算法 Meanshift 算法的基本原理是和很簡單的。假設我們有一堆點(比如直方 圖反向投影得到的點&…

ASR 語音識別接口封裝和分析

這個文檔主要是介紹一下我自己封裝了 6 家廠商的短語音識別和實時流語音識別接口的一個包,以及對這些接口的一個對比。分別是,阿里,快商通,百度,騰訊,科大,字節。 zxmfke/asrfactory (github.c…

ubuntu 安裝 cuda

ubuntu 安裝 cuda 初環境與設備在官網找安裝方式 本篇文章將介紹ubuntu 安裝 CUDA Toolkit CUDA Toolkit 是由 NVIDIA(英偉達)公司開發的一個軟件工具包,用于支持并優化 GPU(圖形處理器)上的并行計算和高性能計算。它…

解析TCP/IP協議的分層模型

了解ISO模型:構建通信的藍圖 為了促進網絡應用的普及,國際標準化組織(ISO)引入了開放式系統互聯(Open System Interconnect,OSI)模型。這個模型包括了七個層次,從底層的物理連接到頂…

一、Dubbo 簡介與架構

一、Dubbo 簡介與架構 1.1 應用架構演進過程 單體應用:JEE、MVC分布式應用:SOA、微服務化 1.2 Dubbo 簡介一種分布式 RPC 框架,對專業知識(序列化/反序列化、網絡、多線程、設計模式、性能優化等)進行了更高層的抽象和…

ArcGIS Maps SDK for JavaScript系列之三:在Vue3中使用ArcGIS API加載三維地球

目錄 SceneView類的常用屬性SceneView類的常用方法vue3中使用SceneView類創建三維地球項目準備引入ArcGIS API創建Vue組件在OnMounted中調用初始化函數initArcGisMap創建Camera對象Camera的常用屬性Camera的常用方法 要在Vue 3中使用ArcGIS API for JavaScript加載和展示三維地…

【JavaSE】面向對象之封裝

封裝的概念 封裝是把過程和數據包圍起來,對數據的訪問只能通過已定義的接口。面向對象計算始于這個基本概念,即現實世界可以被描繪成一系列完全自治、封裝的對象,這些對象通過一個受保護的接口訪問其他對象。封裝是一種信息隱藏技術&#xff…

Java旋轉數組中的最小數字(圖文詳解版)

目錄 1.題目描述 2.題解 分析 具體實現 方法一(遍歷): 方法二(排序): 方法三(二分查找): 1.題目描述 有一個長度為 n 的非降序數組,比如[1,2,3,4,5]&a…

Linux基礎

Linux 一、基礎01- 執行環境準備02- linux的版本分類02.1 內核版本02.2 發行版本02.3 內核和發行版本的區別: 03- 虛擬機安裝04- 啟動linux 二、系統操作05- 幫助命令05.1 man 幫助05.2 help 幫助05.2.1 內部命令05.2.2 外部命令 05.3 info 幫助 06- ls命令06.1 -r06.2 -rt06.3…

npm install 中 --save 和 --save-dev 是什么?

npm,全名 Node Package Manager,套件管理工具,package.json 會記下你在項目中安裝的所有套件。 假設在項目中安裝 lodash npm i --save lodash這樣在 dependencies 中會出現: 如果修改了導入方式: npm i --save-dev …

在Linux中對docker 一鍵安裝,本地安裝,無網絡安裝,

在Linux中對docker 一鍵安裝 前提先準備好安裝包 非常絲滑 首先先把需要準備的文件準備好,/package/base.tar 和 /package/docker-20.10.10.tgz包 這兩個文件包必須放在 /package目錄下 再和/package同級的目錄下再準備conf目錄,conf目錄下放docker.se…

Labview解決“重置VI:xxx.vi”報錯問題

文章目錄 前言一、程序框圖二、前面板三、問題描述四、解決辦法 前言 在程序關閉前面板的時候小概率型出現了 重置VI:xxx.vi 這個報錯,并且發現此時只能通過任務管理器殺掉 LabVIEW 進程才能退出,這里介紹一下解決方法。 一、程序框圖 程序…

特征選擇 | 遞歸特征消除算法篩選最優特征

特征選擇 | 遞歸特征消除算法篩選最優特征 目錄 特征選擇 | 遞歸特征消除算法篩選最優特征寫在前面常規方法算法原理結果分析參考資料 寫在前面 在實際應用中,特征選擇作為機器學習和數據挖掘領域的重要環節,對于提高模型性能和減少計算開銷具有關鍵影響…

pve7.2虛擬機 lvm磁盤擴容,增加硬盤操作

之前安裝pve時候只有256的ssd,最近安裝的虛擬機較多,給加塊閑置硬盤,順便學習一下,像pve這種虛擬機系統,硬盤應該可以像nas你這樣隨時增加,而不影響上層應用,我自己也是摸索著做。 一、安裝好硬盤后打開pv…

vue3+ts-tsconfig.json報錯Option ‘importsNotUsedAsValues’

vue3ts-tsconfig.json報錯Option ‘importsNotUsedAsValues’ is deprecated and will stop functioning in TypeScript 5.5. Specify compilerOption ‘“ignoreDeprecations”: “5.0”’ to silence this error. Use ‘verbatimModuleSyntax’ instead 自我記錄 翻譯 選項…

智能家居(2)---串口通信(語音識別)控制線程封裝

封裝語音線程&#xff08;語音通過串口和主控設備進行交流&#xff09;實現對智能家居中各種燈光的控制 mainPro.c(主函數) #include <stdio.h> #include "controlDevice.h" #include "inputCommand.h" #include <pthread.h>struct Devices …

echart 3d立體顏色漸變柱狀圖

如果可以實現記得點贊分享&#xff0c;謝謝老鐵&#xff5e; 1.需求描述 根據業務需求將不同的法律法規&#xff0c;展示不同的3d立體漸變柱狀圖。 2.先看下效果圖 3. 確定三面的顏色&#xff0c;這里我是自定義的顏色 // 右面生成顏色const rightColorArr ref(["#79D…

ComponentOne Studio ASP.NET MVC Crack

ComponentOne Studio ASP.NET MVC Crack FlexReport增強功能 添加了對在Microsoft Windows上部署Microsoft Azure的支持。 添加了對顯示嵌入字體的支持。 .NET標準版的經典C1PDF(Beta版) GrapeCity的經典C1Pdf庫現在提供了基于Microsoft.NET標準的版本。在任何.NET應用程序(包括…

每日一學——IP尋址

IP尋址是指在網絡中分配和識別設備的唯一IP地址。IP地址是由一串數字組成的標識符&#xff0c;用于在網絡中定位和識別設備。 IPv4是最常用的IP地址版本&#xff0c;它由32位的地址組成&#xff0c;通常表示為四個以點分隔的十進制數字&#xff08;例如192.168.0.1&#xff09…

江南大學計算機考研分析

24計算機考研|上岸指南 江南大學 江南大學計算機考研招生學院是人工智能與計算機學院。目前均已出擬錄取名單。 江南大學人工智能與計算機學院成立于2020年3月&#xff0c;辦學歷史可追溯到1994年設立的計算機應用專業。學院秉持江南大學“彰顯輕工特色&#xff0c;服務國計民…