日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

java中redis原理_Redis字符串键的底层原理

發(fā)布時間:2024/8/5 数据库 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java中redis原理_Redis字符串键的底层原理 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

before

C語言基礎

Redis基礎

導入

redis的命令如下:

set x "hello";

get x;

hello

Redis作為一種存儲字符串的緩存結(jié)構,其具體實現(xiàn)是由C語言完成,在C語言中,字符串是通過字符數(shù)組實現(xiàn)的,即char[],那么Redis對于字符串的實現(xiàn)是不是也是基于字符數(shù)組嗎?不是的,Redis對字符串的處理是通過SDS(Simple Dynamic String)實現(xiàn)的。

SDS介紹

SDS(Simple Dynamic String)簡單動態(tài)字符串,它是由C語言完成,如下是其具體實現(xiàn)

Redis作為一種存儲字符串的緩存結(jié)構,其具體實現(xiàn)是由C語言完成,在C語言中,字符串是通過字符數(shù)組實現(xiàn)的,即char[],那么Redis對于字符串的實現(xiàn)是不是也是基于字符數(shù)組嗎?不是的,Redis對字符串的處理是通過SDS(Simple Dynamic String)實現(xiàn)的。

struct sdshdr{//記錄buf數(shù)組已使用字節(jié)的數(shù)量//等于SDS所保存字符串的長度

intlength;//記錄buf數(shù)組未使用字節(jié)的數(shù)量

intfree;//buf數(shù)組

char[] buf;

};

看看redis的示例:

sdshdr

free0length5buf-->|'R'|'e'|'d'|'i'|'s'|'\0'|解釋:-free為0,表示這個SDS沒有分配任何未使用的空間-length為5,表示這個SDS保存了一個長度為5的字符串- buf數(shù)組中保存著“Redis”字符串

SDS遵循C字符串以空字符串結(jié)尾的慣例,保存空字符串的1字節(jié)空間不計算在SDS的len屬性之中。

再看看SDS的free不為0的情況:

sdshdr

free3length5buf-->|'R'|'e'|'d'|'i'|'s'| | | |

free的值為3,表示這個SDS分配了三個空閑的空間

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

C語言使用簡單的字符串表示方式,并不能滿足Redis對字符串在安全性,效率,以及功能方面的要求,SDS更使用Redis。

@1 常數(shù)復雜度獲取字符串長度

C字符串:

因為C語言并不記錄自身的長度信息,所以獲取一個C字符串的長度,程序必須遍歷整個字符串,對遇到的,每個字符進行計數(shù),直到遇到代表字符串結(jié)尾的空字符串為止,這個操作的復雜度為O(n)。

SDS:

與C語言不同的是,SDS結(jié)構中的屬性length記錄了SDS本身的長度,所以獲取一個SDS長度的復雜度為O(1)。有人疑問那么SDS的length值是哪來的?這里的length值是SDS API在設置和更新SDS時自動完成的。

總結(jié)1:通過使用SDS而不是C字符串,Redis獲取字符串長度的復雜度由O(N)降為O(1),這確保了字符串長度的獲取的工作不會成為Redis的性能瓶頸。

@ 2杜絕緩沖區(qū)溢出

C字符串:

由于C自身不記錄字符串的長度帶來一個問題是容易造成緩沖區(qū)溢出(buffer overflow)。在/strcat函數(shù)中,可以將一個字符串拼接到另外一個字符串的末尾。

`char *strcat(char *dest,const char *src)`

理想狀態(tài)下,用戶在使用這個函數(shù)時,假定C為dest分配了足夠多的內(nèi)存,可以容納src字符串中的所有內(nèi)容,而一旦這個假定不成立,就會產(chǎn)生緩沖區(qū)溢出。舉個例子,假定內(nèi)存中有相鄰的兩個字符串s1,s2,如圖:

s1 s2| |...|'R'|'e'|'d'|'i'|'s'|'\0'||'g'|'o'|'o'|'d'|'\0'|...

如果執(zhí)行strcat(s1," cluster");將Redis改為”Redis cluster“,但是粗心的卻忘了在執(zhí)行這句之前為s1分配足夠的空間,那么在執(zhí)行之后,s1的數(shù)據(jù)將會溢出到s2所在的空間,導致s2保存的內(nèi)容意外的被修改。

SDS:

與C語言不同的是,SDS空間分配政策完全杜絕了發(fā)生緩沖區(qū)溢出的可能性:當SDS API需要對字符串進行修改時,首先會檢查SDS的空間是否滿足修改所需的要求,因為SDS自身有對字符串長度記錄的屬性length和空閑空間屬性free,可以借助這兩個參數(shù)進行檢查。SDS會在執(zhí)行動作之前判斷SDS的空間大小,再去執(zhí)行操作,如果空間不夠的話,SDS API會自動擴展空間。

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

C字符串:

因為C字符串不記錄自身長度,每次增長或者縮短字符串長度時,程序都要對這個C字符串數(shù)組進行一次內(nèi)存重新分配操作,不然容易造成內(nèi)存益出。因為內(nèi)存,分配設計復雜的算法,并且可能需要執(zhí)行系統(tǒng)調(diào)用,所以它通常是一個比較耗時和耗能的操作。但是Redis作為緩存,追求速度,所以不能經(jīng)常發(fā)生內(nèi)存分配操作。

SDS:

SDS數(shù)組中的未使用空間字節(jié)數(shù)量由SDS的屬性free記錄,通過free記錄,SDS實現(xiàn)了空間預分配和惰性釋放兩種優(yōu)化策略。

1. 空間預分配

空間預分配用于優(yōu)化SDS的字符串增長操作:當SDS的API對一個SDS進行修改,并且需要對SDS的空間進行擴展時,程序不僅會為SDS分配修改所需要的空間,而且還會為SDS分配額外的空間。額外的空間分配規(guī)則如下:

(1)如果修改SDS之后,SDS的長度小于1MB,那么程序會給SDS分配和length一樣大的額外空間,這是SDSlength和free的值相等。舉個例子,如果修改后的字符串長度為13k,那么SDS的空間將會占據(jù)13+13+1=27k(額外的一個字節(jié)用于保存空字符串)。

(2)如果修改SDS之后,SDS的長度大于1MB,那么程序會給SDS分配額外的1MB空間,舉個例子,比如修改后的SDS有30MB的大小,那么程序會分配1MB的未使用空間,SDS的buf數(shù)組實際大小將是30MB+1MB+1byte。

2.惰性釋放

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

@4 二進制安全

C字符串中的字符必須符合某種編碼(比如ASCII),并且除了字符串末尾之外,字符串里面不能包含空字符串,否則最先被程序讀入的空字符串將被誤認為是字符串結(jié)尾。

SDS API都是二進制安全的,所有SDS API都會以處理二進制的方式來處理存放在SDS buf中的數(shù)據(jù),數(shù)據(jù)寫什么樣,它被讀取時就是什么樣子。

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

SDS的API總會以SDS保存的數(shù)據(jù)的末尾設置為空字符串,并且在分配SDS空間時會多分配一個字節(jié)的空間來容納空字符串,這是為了那些保存的數(shù)據(jù)可以重用一部分庫中的函數(shù)。

總結(jié)

字符串和SDS之間的區(qū)別總結(jié)如下:

總結(jié)

以上是生活随笔為你收集整理的java中redis原理_Redis字符串键的底层原理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。