亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Redis把簡單的字符串設計成SDS原因有哪些

發布時間:2021-10-09 17:00:01 來源:億速云 閱讀:144 作者:iii 欄目:數據庫

本篇內容主要講解“Redis把簡單的字符串設計成SDS原因有哪些”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Redis把簡單的字符串設計成SDS原因有哪些”吧!

Redis把簡單的字符串設計成SDS原因有哪些

我們知道redis是用C寫的,但它卻沒有完全直接使用C的字符串,而是自己又重新構建了一個叫簡單動態字符串SDS(simple dynamic string)的抽象類型。

redis也支持使用C語言的傳統字符串,只不過會用在一些不需要對字符串修改的地方,比如靜態的字符輸出。

而我們開發中使用redis,往往會經常性的修改字符串的值,這個時候就會用SDS來表示字符串的值了。有一點值得注意:在redis數據庫中,key-value鍵值對含有字符串值的,都是由SDS來實現的。

比如:在redis執行一個最簡單的set命令,這時redis會新建一個鍵值對。

127.0.0.1:6379> set xiaofu "AAA"

此時鍵值對的key和value都是一個字符串對象,而對象的底層實現分別是兩個保存著字符串xiaofu和AAA的SDS結構。

再比如:我向一個列表中壓入數據,redis 又會新建一個鍵值對。

127.0.0.1:6379> lpush xiaofu "AAA" "BBB"

這時候鍵值對的鍵和上邊一樣,還是一個由SDS實現的字符串對象,鍵值對的值是一個包含兩個字符串對象的列表對象了,而這兩個對象的底層也是由SDS實現。

SDS結構

一個SDS值的數據結構,主要由len、free、buf[]這三個屬性組成。

struct sdshdr{    int free; // buf[]數組未使用字節的數量    int len; // buf[]數組所保存的字符串的長度    char buf[]; // 保存字符串的數組  }

其中buf[]為實際保存字符串的char類型數組;free表示buf[]數組未使用字節的數量;len表示buf[]數組所保存的字符串的長度。

Redis把簡單的字符串設計成SDS原因有哪些

例如上圖表示的是buf[]保存長度為6個字節的字符串,未使用的字節數free為0,但是眼尖的同學會發現這明明是7個字符,還有一個"\0"啊?

上邊提到過SDS沒有完全直接使用C的字符串,還是沿用了一些C特性的,比如遵循C的字符串以空格符結尾的規則,這樣還可以使用一部分C字符串的函數。而對于SDS來說,空字符串占用的一字節是不計算在len屬性里的,會為他分配額外的空間。

簡單了解SDS結構后,下邊我們來看看SDS相比于C字符串有哪些優點。

效率高

舉個例子:工作中使用redis,經常會通過STRLEN命令得到一個字符串的長度,在SDS結構中len屬性記錄了字符串的長度,所以我們獲取一個字符串長度直接取len的值,復雜度是O(1)。

Redis把簡單的字符串設計成SDS原因有哪些

而如果用C字符串,在獲取一個字符串長度時,需對整個字符串進行遍歷,直至遍歷到空格符結束(C中遇到空格符代表一個完整字符串),此時的復雜度是O(N)。

在高并發場景下頻繁遍歷字符串,獲取字符串的長度很有可能成為redis的性能瓶頸,所以SDS性能更好一些。

數據溢出

上邊提到C字符串是不記錄自身長度的,相鄰的兩個字符串存儲的方式可能如下圖,為字符串分配了合適的內存空間。

Redis把簡單的字符串設計成SDS原因有哪些

如果此時我想把“AAA”改成“AAA123”,可之前分配的內存只有6個字節,修改后的字符串需要9個字節才能放下啊,怎么搞?

Redis把簡單的字符串設計成SDS原因有哪些

沒辦法只能侵占相鄰字符串的空間,自身數據溢出導致其他字符串的內容被修改。

而SDS很好的規避了這點,當我們需要修改數據時,首先會檢查當前SDS空間len是否滿足,不滿足則自動擴容空間至修改所需的大小,然后再執行修改,如下圖所示。

Redis把簡單的字符串設計成SDS原因有哪些

不過有個特殊的地方,在把“AAA”的6個字節擴容到“AAA123”9個字節后,發現free屬性的值變成了擴容后字符串的總長度,這就涉及到下邊要說的內存重分配策略了。

內存重分配策略

C字符串長度是一定的,所以每次在增長或者縮短字符串時,都要做內存的重分配,而內存重分配算法通常又是一個比較耗時的操作,如果程序不經常修改字符串還是可以接受的。

但很不幸,redis作為一個數據庫,數據肯定會被頻繁修改,如果每次修改都要執行一次內存重分配,那么就會嚴重影響性能。

SDS通過兩種內存重分配策略,很好的解決了字符串在增長和縮短時的內存分配問題。

1.空間預分配

空間預分配策略用于優化SDS字符串增長操作,當修改字符串并需對SDS的空間進行擴展時,不僅會為SDS分配修改所必要的空間,還會為SDS分配額外的未使用空間free,下次再修改就先檢查未使用空間free是否滿足,滿足則不用在擴展空間。

通過空間預分配策略,redis可以有效的減少字符串連續增長操作,所產生的內存重分配次數。

Redis把簡單的字符串設計成SDS原因有哪些

額外分配未使用空間free的規則:

  •  如果對 SDS 字符串修改后,len 值小于 1M,那么此時額外分配未使用空間 free 的大小與len相等。

  •  如果對 SDS 字符串修改后,len 值大于等于 1M,那么此時額外分配未使用空間 free 的大小為1M。

2.惰性空間釋放

惰性空間釋放策略則用于優化SDS字符串縮短操作,當縮短SDS字符串后,并不會立即執行內存重分配來回收多余的空間,而是用free屬性將這些空間記錄下來,如果后續有增長操作,則可直接使用。

Redis把簡單的字符串設計成SDS原因有哪些

數據格式多樣性

C字符串中的字符必須符合某些特定的編碼格式,而且上邊我們也提到,C字符串以\0空字符結尾標識一個字符串結束,所以字符串里邊是不能包含\0的,不然就會被誤認是多個。

由于這種限制,使得C字符串只能保存文本數據,像音視頻、圖片等二進制格式的數據是無法存儲的。

redis 會以處理二進制的方式操作Buf數組中的數據,所以對存入其中的數據未做任何的限制、過濾,只要存進來什么樣,取出來還是什么樣。

到此,相信大家對“Redis把簡單的字符串設計成SDS原因有哪些”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

万源市| 辰溪县| 泰和县| 界首市| 柘城县| 东平县| 商丘市| 句容市| 海盐县| 抚顺市| 石嘴山市| 凤翔县| 镇坪县| 永吉县| 化隆| 莎车县| 浦江县| 类乌齐县| 沁水县| 温宿县| 廉江市| 祥云县| 石阡县| 彭山县| 灯塔市| 达州市| 许昌县| 吴堡县| 黄平县| 伊宁县| 九龙城区| 宜丰县| 卓资县| 皮山县| 和顺县| 安阳市| 商城县| 大连市| 色达县| 阳信县| 黄龙县|