成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Redis數(shù)據(jù)結(jié)構(gòu)之簡(jiǎn)單動(dòng)態(tài)字符串SDS

存儲(chǔ) 存儲(chǔ)軟件 Redis
Redis的底層數(shù)據(jù)結(jié)構(gòu)非常多,其中包括SDS、ZipList、SkipList、LinkedList、HashTable、Intset等。如果你對(duì)Redis的理解還只停留在get、set的水平的話,是遠(yuǎn)遠(yuǎn)不足以應(yīng)對(duì)面試提問(wèn)的。本文簡(jiǎn)單介紹了Redis底層最重要的數(shù)據(jù)結(jié)構(gòu) - 簡(jiǎn)單動(dòng)態(tài)字符串(SDS)。

 Redis的底層數(shù)據(jù)結(jié)構(gòu)非常多,其中包括SDS、ZipList、SkipList、LinkedList、HashTable、Intset等。如果你對(duì)Redis的理解還只停留在get、set的水平的話,是遠(yuǎn)遠(yuǎn)不足以應(yīng)對(duì)面試提問(wèn)的。本文簡(jiǎn)單介紹了Redis底層最重要的數(shù)據(jù)結(jié)構(gòu) - 簡(jiǎn)單動(dòng)態(tài)字符串(SDS)。

[[258985]]

Redis使用C語(yǔ)言開(kāi)發(fā),但并沒(méi)有使用C語(yǔ)言傳統(tǒng)的字符串表示(以空字符結(jié)尾的字節(jié)數(shù)組,以下簡(jiǎn)稱C字符串),而是自己構(gòu)建了一種名為簡(jiǎn)單動(dòng)態(tài)字符串的(simple dynamic string,SDS)的抽象類型,并將SDS用作Redis的默認(rèn)字符串表示。

在Redis里面,C字符串只會(huì)作為字符串字面量(static literal)用在一些無(wú)須對(duì)字符串值進(jìn)行修改的地方。當(dāng)Redis需要的不僅僅是一個(gè)字符串字面量,而是一個(gè)可以被修改的字符串值時(shí),Redis就會(huì)使用SDS來(lái)表示字符串值,比如在Redis的數(shù)據(jù)庫(kù)里面,包含字符串的鍵值對(duì)在底層都是由SDS實(shí)現(xiàn)的。

咱們來(lái)舉個(gè)例子,如果在客戶端執(zhí)行命令:

  1. redis> SET msg "hello world" 
  2. ok 

那么Redis將在數(shù)據(jù)庫(kù)中創(chuàng)建一個(gè)新的鍵值對(duì),其中:

鍵值對(duì)的鍵是一個(gè)字符串對(duì)象,對(duì)象的底層實(shí)現(xiàn)是一個(gè)保存著字符串“msg”的SDS。

鍵值對(duì)的值也是一個(gè)字符串對(duì)象,對(duì)象的底層實(shí)現(xiàn)是一個(gè)保存著字符串“hello world”的SDS。

除了用來(lái)保存數(shù)據(jù)庫(kù)中的字符串值之外,SDS還被用作緩沖區(qū):AOF模塊中的AOF緩沖區(qū),以及客戶端狀態(tài)中的輸入緩沖區(qū),都是由SDS實(shí)現(xiàn)的。總之,SDS是Redis的最基礎(chǔ)也是最重要的數(shù)據(jù)結(jié)構(gòu)。

1.SDS的定義

每個(gè) sds.h/sdshdr 結(jié)構(gòu)表示一個(gè)SDS值:

  1. struct sdshdr{ 
  2.     // 記錄buf數(shù)組中已使用字節(jié)的數(shù)量 
  3.     // 等于SDS所保存字符串的長(zhǎng)度 
  4.     int len; 
  5.      
  6.     // 記錄buf數(shù)組中未使用字節(jié)的數(shù)量 
  7.     int free
  8.     //字節(jié)數(shù)組,用于保存字符串 
  9.     char buf[]; 

 

用一張圖來(lái)表示:

 

SDS 遵循 C 字符串以空字符結(jié)尾的慣例, 保存空字符的 1字節(jié)空間不計(jì)算在 SDS 的 len 屬性里面, 并且為空字符分配額外的 1 字節(jié)空間, 以及添加空字符到字符串末尾等操作都是由 SDS 函數(shù)自動(dòng)完成的, 所以這個(gè)空字符對(duì)于 SDS 的使用者來(lái)說(shuō)是完全透明的。

2.SDS與C字符串的區(qū)別

現(xiàn)在來(lái)說(shuō),C語(yǔ)言使用長(zhǎng)度為N+1的字符數(shù)組來(lái)表示長(zhǎng)度為N的字符串,并且字符數(shù)組的***一個(gè)元素總是空字符“”。

C的這種簡(jiǎn)單的字符串表達(dá)方式,并不能滿足Redis對(duì)字符串在安全性、效率以及功能方面的要求。具體有以下幾個(gè)方面。

2.1 常數(shù)復(fù)雜度獲取字符串長(zhǎng)度

因?yàn)镃字符串并不記錄字符串的長(zhǎng)度信息,所以為了獲取一個(gè)C字符串的長(zhǎng)度,程序必須遍歷整個(gè)字符串,對(duì)遇到的每個(gè)字符進(jìn)行計(jì)數(shù),直到遇到空字符為止,這個(gè)操作的復(fù)雜度為O(n)。而在Redis的SDS中,這個(gè)時(shí)間復(fù)雜度只有O(1)。

2.2 杜絕緩沖區(qū)溢出

除了獲取字符串長(zhǎng)度的復(fù)雜度高之外,C字符不記錄自身長(zhǎng)度帶來(lái)的另一個(gè)問(wèn)題就是緩沖區(qū)溢出。舉個(gè)例子,C語(yǔ)言的 strcat 函數(shù)可以將字符串中的內(nèi)容拼接到 dest 字符串的末尾,但是當(dāng)字符串的容量不夠就會(huì)產(chǎn)生緩存區(qū)溢出,因?yàn)樽址彩腔跀?shù)組實(shí)現(xiàn)的,也是有大小限制的。

Redis的SDS已經(jīng)杜絕了這個(gè)問(wèn)題,那它是如何解決的呢?

當(dāng)API要對(duì)SDS進(jìn)行修改時(shí),API會(huì)先檢查SDS的空間是否滿足修改所需的空間,如果不夠的話,API會(huì)自動(dòng)將SDS的空間進(jìn)行擴(kuò)容,然后才執(zhí)行實(shí)際的修改操作。這就避免了緩沖區(qū)內(nèi)存溢出。

2.3 減少修改字符串時(shí)帶來(lái)的內(nèi)存重分配次數(shù)

上面說(shuō)到了API會(huì)在修改SDS字符串時(shí)自動(dòng)擴(kuò)容,如果每次修改都伴隨著對(duì)字符串內(nèi)的數(shù)組的內(nèi)存重分配,那效率可想而知。所以Redis實(shí)現(xiàn)了空間預(yù)分配和惰性空間釋放兩種優(yōu)化策略。

空間預(yù)分配

空間預(yù)分配用于優(yōu)化SDS的字符串增長(zhǎng)操作:當(dāng)SDS的API對(duì)一個(gè)SDS進(jìn)行修改,并且需要對(duì)SDS進(jìn)行空間擴(kuò)展的時(shí)候,程序不僅會(huì)為SDS分配修改所需要的空間,還會(huì)為SDS分配額外的未使用空間。

總的來(lái)說(shuō),額外分配的未使用空間數(shù)量大小有兩種可能:

如果對(duì)SDS修改之后,SDS的長(zhǎng)度將小于1MB,那么程序分配和len 屬性同樣大小的未使用空間,這時(shí)候SDS的 free 屬性的值將和 len 屬性的值相同。也就是說(shuō),該SDS字符串修改完后還有近一半的容量。

如果對(duì)SDS修改之后,SDS的長(zhǎng)度大于等于1MB,那么程序會(huì)分配1MB的未使用空間。這個(gè)是固定的。

通過(guò)空間預(yù)分配,Redis可以減少連續(xù)執(zhí)行字符串操作所需的內(nèi)存重分配次數(shù)。

惰性空間釋放

惰性空間釋放用于優(yōu)化SDS的字符串縮短操作:當(dāng)SDS的API需要縮短SDS保存的字符串時(shí),程序并不立即使用內(nèi)存重分配來(lái)回收縮短后多出來(lái)的字節(jié),而是使用 free 屬性將這些字節(jié)的數(shù)量記錄起來(lái),并等待將來(lái)使用。

2.4 二進(jìn)制安全

在C語(yǔ)言中,字符串的存儲(chǔ)必須符合某種編碼(ASCII),并且字符串不能包含空字符,否則會(huì)被認(rèn)為是字符串結(jié)尾。這些限制使得C字符串只能保存文本數(shù)據(jù),而不能保存像圖片、音頻、視頻、壓縮文件這樣的二進(jìn)制數(shù)據(jù)。

所以,為了解決C字符串的不足,Redis的 buf 數(shù)組保存的是二進(jìn)制數(shù)據(jù),這也就是把SDS的 buf 數(shù)組稱為字節(jié)數(shù)組的原因。

2.5 兼容部分C字符串函數(shù)

雖然 Redis 的API都是二進(jìn)制安全的,但它們一樣遵循C字符串以空字符串結(jié)尾的慣例,這些API總會(huì)將SDS保存的數(shù)據(jù)的末尾設(shè)置為空字符,并且總會(huì)在為 buf 數(shù)組分配空間時(shí)多分配一個(gè)字節(jié)來(lái)容納這個(gè)空字符,這是為了讓那些保存文本數(shù)據(jù)的SDS可以重用一部分C的函數(shù)。

舉個(gè)例子, 如果我們有一個(gè) SDS 的指針 s , 那么我們可以直接使用 stdio.h/printf 函數(shù), 通過(guò)執(zhí)行以下語(yǔ)句:

  1. printf("%s", s->buf); 

來(lái)打印出 SDS 保存的字符串值 "Redis" , 而無(wú)須為 SDS 編寫專門的打印函數(shù)。

責(zé)任編輯:武曉燕 來(lái)源: 博客園
相關(guān)推薦

2020-06-29 07:44:36

Redis

2021-12-21 11:39:01

數(shù)據(jù)結(jié)構(gòu)算法同構(gòu)字符串

2023-10-19 15:11:48

Redis

2022-02-10 09:04:18

RediSDS數(shù)據(jù)結(jié)構(gòu)

2023-03-28 07:44:23

數(shù)據(jù)結(jié)構(gòu)數(shù)組

2021-12-24 11:59:47

數(shù)據(jù)結(jié)構(gòu)算法字符串

2020-07-07 07:34:29

RedisSDS數(shù)據(jù)結(jié)構(gòu)

2020-05-13 12:17:33

RedisC字符C語(yǔ)言

2024-02-20 20:12:09

C語(yǔ)言字符串Redis

2021-02-18 07:45:09

redis 字符串SDS

2021-02-23 09:35:33

redis字符串數(shù)據(jù)庫(kù)

2021-04-27 10:53:58

Redis數(shù)據(jù)庫(kù)SDS

2021-12-23 14:09:43

數(shù)據(jù)結(jié)構(gòu)算法字符串

2023-01-09 08:42:04

String數(shù)據(jù)類型

2023-11-12 21:49:10

Redis數(shù)據(jù)庫(kù)

2021-12-27 11:30:51

數(shù)據(jù)結(jié)構(gòu)算法動(dòng)態(tài)規(guī)劃

2021-07-16 07:57:34

Python數(shù)據(jù)結(jié)構(gòu)

2009-08-26 13:24:54

C#字符串

2020-12-16 07:36:46

Redis字符串數(shù)據(jù)

2024-01-26 06:42:05

Redis數(shù)據(jù)結(jié)構(gòu)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 日韩欧美三级在线 | 99pao成人国产永久免费视频 | 婷婷久久综合 | 日本高清中文字幕 | 亚洲欧美中文字幕 | 国产精品高潮呻吟久久久久 | 色综合桃花网 | 久久久久久免费毛片精品 | 四虎影院在线观看免费视频 | 欧美高清一级片 | 特黄毛片 | 日韩免费一区二区 | 亚洲一区免费视频 | 久久久久亚洲精品 | 久久精品视频网站 | 欧美激情久久久 | 91小视频在线 | www.四虎.com | 欧美a√ | 欧美成人一区二免费视频软件 | 日本成人午夜影院 | 狠狠涩 | 涩爱av一区二区三区 | 国产成人精品一区二区三区视频 | 国产一区二区三区在线 | 日韩欧美高清dvd碟片 | 国产精品色 | 欧美精品乱码久久久久久按摩 | 午夜精品一区二区三区免费视频 | 手机在线一区二区三区 | 欧美一区二区小视频 | 亚洲欧美日韩电影 | 日韩综合在线 | 亚洲 精品 综合 精品 自拍 | 免费av在线 | 91极品视频| 久久久无码精品亚洲日韩按摩 | 青青草av网站 | 九九久久国产 | 国产不卡一区在线观看 | 成人一区二|