redis 系列3 簡單動態字元串 SDS

来源:https://www.cnblogs.com/MrHSR/archive/2018/10/31/9881986.html
-Advertisement-
Play Games

一. SDS概述 Redis 沒有直接使用C語言傳統的字元串表示,而是自己構建了一種名為簡單動態字元串(simple dynamic string, SDS)的抽象類型,並將SDS用作Redis的預設字元串表示。Redis只會使用C字元串作為字面量。在Redis里,使用SDS來表示字元串值,是一個可 ...


一.  SDS概述

  Redis 沒有直接使用C語言傳統的字元串表示,而是自己構建了一種名為簡單動態字元串(simple dynamic string, SDS)的抽象類型,並將SDS用作Redis的預設字元串表示。Redis只會使用C字元串作為字面量。在Redis里,使用SDS來表示字元串值,是一個可以被修改的字元串,字元串“鍵值對”底層都是由SDS實現的。

-- 例1:客戶端執行如下命令:
127.0.0.1:6379> set msg "hello world"
OK
127.0.0.1:6379> get msg
"hello world"

  上面例1中就在資料庫里創建一個新的鍵值對。 其中“鍵”是一個字元串對象,對象的底層實現是一個保存著字元串"msg" 的SDS。 "鍵值" 也是一個字元串對象,對象的底層實現是一個保存著字元串" hello world " 的SDS。

-- 例2: 客戶端執行如下命令:
127.0.0.1:6379> rpush  fruits "apple" "banana" "cherry"
(integer) 3
127.0.0.1:6379> lrange fruits 0 -1
1) "apple"
2) "banana"
3) "cherry"

  上面例2中也在資料庫里創建一個新的鍵值對。其中“鍵”是一個字元串對象,對象的底層實現是一個保存著字元串" fruits " 的SDS。"鍵值"是一個列表對象,列表包含了三個字元串對象,分別由三個SDS實現。

  SDS除了用來保存資料庫中的字元串值之外,還用作緩衝區(buffer): AOF模塊中的AOF緩衝區,以及客戶端狀態中的輸入緩衝區。

 

二. SDS 定義

  每個SDS.h文件下的sdshdr結構表示一個SDS值, 下麵是Redis源碼,在github的地址是https://github.com/antirez/sds

struct  sdshdr{
    //記錄buf數組中已使用位元組的數量,也就是字元串的長度
     int len ;
    // 記錄buf數組中未使用位元組的數量
     int free;
    //位元組數組,用於保存字元串
     char buf[];
}

  在C語言中使用長度為N+1的字元數組來表示長度為N的字元串,並且字元數組最後一個元素總是空字元'\0'。 假設SDS的值為 "Redis",那麼free屬性值為0, len 屬性值為5, buf數組為R,e,d,i,s五個字元,最後一個位元組則保存空字元'\0' 。

 

三. SDS與C字元串的區別

  C語言使用簡單的字元串表示方式,並不能滿足Redis對字元串在安全性,效率以及功能方面的要求,從幾個方面說明:

  1. 常數複雜度獲取字元串長度

    因為c字元串並不記錄自身的長度信息,所以為了獲取一個c字元串的長度,程式必須遍歷整個字元串。與C 字元串不同,因為SDS在len屬性中記錄了SDS本身的長度,對於SDS的值為"Redis"的位元組長度就是5。

  2. 杜絕緩衝區溢出

    在c中, 假設緊鄰的字元串s1 和 s2, s1保存為"redis", s2保存為"mongodb",  如果修改s1的值為 redis cluster, 但修改之前沒了空間,那麼s1的數據將溢出到s2所在空間中。

    在SDS中,會先檢查給定的SDS空間是否足夠,會自動擴展修改所需的大小空間。然後在執行實際的修改操作。

  3. 減少修改字元串時帶來的記憶體重分配次數

     在c 中,字元串的底層實現總是一個N+1個字元長的數組,因為字元串的長度和底層數組的長度之間存在著這種關聯,所以每次增長或者縮短一個c字元串,程式都要對保存這個C字元串的數組進行一次記憶體重分配操作。

    在SDS中通過未使用空間解除了字元串長度和底層數組長度之間的關聯,buf數組的長度不一定就是字元數量加1, 數組裡機可以包含未使用的位元組,這些由free屬性記錄。

    3.1 空間預分配

      當SDS的API對一個SDS進行操作,並且需要對SDS進行空間擴展的時候,程式不僅會為SDS 分配修改所必須要的空間,還會為SDS分配額外的未使用空間。額外分配的未使用空間數量由以下公式決定:

      如果對SDS進行修改之後,SDS的長度(也即是len屬性的值) 將小於1MB,那麼程式分配和len屬性同樣大小的未使用空間。這時SDS len屬性的值將和fee屬性的值相同,例如:修改之後,SDS的len將變成13位元組, 那麼程式也會分配13位元組的未使用空間,SDS的buf數組的實際長度將變成13+13+1=27位元組。

      如果對SDS進行修改之後,SDS的len大於等於1MB, 那麼程式會分配1MB的未使用空間,如果對SDS進行修改之後, SDS的len變成30MB,那麼程式會分配1MB的未使用空間,SDS的buf數組的實際長度為30MB + 1MB +1byte。

    通過空間預分配策略,Redis可以減少連續執行字元串增長操作所需的記憶體重分配次數。

    3.2 惰性空間釋放

      惰性空間釋放用於優化SDS的字元串縮短操作。當SDS的API需要縮短SDS保存的字元串時,程式並不立即使用記憶體重分配來回收縮短多出來的位元組,而是使用free屬性將這些位元組的數據記錄起來,並等待將來使用(縮短後未使用的空間不會釋放,而是將來增長操作時,再使用這些未使用空間)。

  4. 二進位安全

    在c字元串的字元必須符合某種編碼(如ASCII), 並且除了字元串的末尾之處,字元串裡面不能包含空字元,否則最先被程式讀入的空字元將被誤以為是字元串的結尾,這使得c字元串只能保存文本數據,不能保存圖片,音頻,視頻,壓縮文件之類的二進位數據。

    為了保證Redis 可以適用各種不同的使用場景,SDS的API 都是二進位安全的,程式不會對其中的數據做任何限制,過濾,數據寫入是什麼,讀取時就是什麼。

  5. 相容部分C字元串函數

    在SDS中會遵循C字元串以空字元結尾的慣例,總會為buf數組分配空間時多分配一個位元組來容納這個空字元,這是為了讓SDS的字元串可以重用一部分(string.h>庫定入的函數。

 

四 總結

  4.1  C字元串與SDS之間的區別總結

C字元串

SDS

獲取字元串長度的複雜度為0(N)

獲取字元串長度的複雜度為0(1)

API是不安全的,可能會造成緩衝區溢出

API是安全的,不會造成緩衝區溢出

修改字元串長度N次必然需要執行N次記憶體重分配

修改字元串長度N次最多需要執行N次記憶體重分配

只能保存文本數據

可以保存文本或者二進位數據

可以使用所有<string.h>庫中函數

可以使用一部分<string.h>庫中函數

  4.2  SDS API(主要的一些API)      

函數

作用

sdsnew

創建一個SDS字元串

sdsempty

創建一個不包含內容的空SDS 字元串

sdsfree

釋放給定的SDS字元串未使用空間

sdslen

返回SDS字元串已使用空間位元組數

sdsavail

返回SDS字元串未使用空間位元組數

sdsdup

創建一個給定SDS的副本

sdsclear

清空SDS字元串內容

sdscat

將給定c字元拼接到SDS字元串的末尾

sdscatsds

將給定的SDS字元串拼接到另一個SDS字元串的末尾

sdscpy

將給定的c字元拼複製到SDS里機,覆蓋SDS原有字元串

sdsgrowzero

用空字元將SDS擴展至指定長度

sdsrange

保留SDS指定區間內的數據,不在區間內的數據會被覆蓋或清除

sdstrim

接受一個SDS和一個C字元串作為參數,從SDS中移除所有在C字元串中出現過的字元

sdscmp

對比兩個SDS字元串是否相同

 

  


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 工具/原料 win7旗艦版系統 筆記本一臺 WIN7下怎麼安裝iis教程: 點擊開始→控制面板,然後再點擊程式和功能,勿點擊卸載程式,否則到不了目標系統界面。 然後在程式和功能下麵,點擊打開和關閉windows功能。 進入Windows功能視窗,然後看到internet信息服務選項,然後按照圖中設置 ...
  • 1. 首先去官方網站下載壓縮文件:https://dev.mysql.com/downloads/mysql/ 2. 解壓下載的文件。 3. 將解壓的所有文件放在一個文件夾里(最好是C:\Program Files\MySQL\里(Mysql文件夾是自己創建的),其他位置也可以,我安裝在D盤上,下為... ...
  • 實驗機器: Kali虛擬機一臺(192.168.163.133) Windows XP虛擬機一臺(192.168.163.130) 如何用Kali虛擬機一步一步“黑掉”這個windowsXP虛擬機呢? 用到的軟體: SLmail程式(存在緩衝區溢出漏洞) ImmunityDebugger(調試工具) ...
  • linux的資料比較零散,經常是好不容易查到了,然後幾秒鐘就忘了,然後就怎麼都找不到了。看來學這個不能偷懶,必須要隨時隨地把資料給記錄下來。這就是這篇博文的意義。Xfce 一個圖形桌面環境。debian 一個linux發行版。引導提示符,按tab編輯命令行:desktop=xfceX Window ... ...
  • 下麵是我們在使用AlwaysOn過程中遇到的一個切換案例。這個案例發生在2014年8月,雖然時間相對久遠了,但是對我們學習理解AlwaysOn的FailOver原理和過程還是很有幫助的。本次FailOver的觸發原因是系統I/O問題。大家需要理解,操作系統I/O出現了問題不一定立即觸發SQL Ser ...
  • Alluxio的基本特性:透明數據緩存機制;抽象數據訪問API;和適用應用場景分析,主要包括複雜系統設計解耦和計算存儲分離應用場景的性能加速。 ...
  • Oracle條件查詢 參考網址:http://www.oraclejsq.com/article/010100259.html Oracle條件查詢時經常使用=、IN、LIKE、BETWEEN...AND來作為條件查詢的操作符。在Oracle select 查詢中where條件經常使用到這幾個操作符 ...
  • 今天小試了一把Percona Monitoring Plugins for Zabbix模板,自己辛辛苦苦寫的那一大堆Python腳本,貌似用這個模板全都覆蓋到了。 但是,我也發現最新的版本percona monitoring plugins_1.1.8也還是存在一個問題,那就是用於Mysql Re ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...