詳解Redis中的簡(jiǎn)單動(dòng)態(tài)字符串和C字符串的區(qū)別
什么是 Redis
Redis(Remote Dictionary Server)是一個(gè)開源的內(nèi)存數(shù)據(jù)存儲(chǔ)系統(tǒng),通常被用作緩存、數(shù)據(jù)庫和消息中間件。它支持多種數(shù)據(jù)結(jié)構(gòu),包括字符串(strings)、哈希表(hashes)、列表(lists)、集合(sets)、有序集合(sorted sets)等。Redis 最顯著的特點(diǎn)之一是其高性能,主要由于數(shù)據(jù)存儲(chǔ)在內(nèi)存中,以及采用了單線程的事件循環(huán)模型。
以下是一些關(guān)鍵特點(diǎn)和用途:
內(nèi)存存儲(chǔ):Redis 主要將數(shù)據(jù)存儲(chǔ)在內(nèi)存中,這使得它能夠提供快速的讀寫操作。然而,為了持久性,可以將數(shù)據(jù)定期寫入磁盤或者使用快照功能。
數(shù)據(jù)結(jié)構(gòu):Redis 支持多種數(shù)據(jù)結(jié)構(gòu),包括字符串、哈希表、列表、集合和有序集合。這種多樣性使得 Redis 適用于各種用途,如緩存、計(jì)數(shù)器、排行榜等。
持久性:Redis 提供持久性選項(xiàng),可以將數(shù)據(jù)保存到磁盤上,以便在重啟時(shí)保留數(shù)據(jù)。
原子性操作:Redis 的命令是原子性的,這意味著對(duì)于給定的操作,要么全部執(zhí)行成功,要么全部失敗,沒有中間狀態(tài)。
分布式:Redis 支持分布式架構(gòu),可以通過主從復(fù)制(master-slave replication)實(shí)現(xiàn)數(shù)據(jù)的復(fù)制,以提高可用性和容錯(cuò)性。
發(fā)布/訂閱:Redis 支持發(fā)布/訂閱模式,允許多個(gè)客戶端訂閱頻道,從而實(shí)現(xiàn)消息的廣播。
事務(wù):Redis 支持事務(wù),通過 MULTI、EXEC、DISCARD 和 WATCH 等命令實(shí)現(xiàn)事務(wù)操作。
由于其靈活性和高性能,Redis 被廣泛應(yīng)用于各種場(chǎng)景,包括緩存、實(shí)時(shí)分析、排行榜、計(jì)數(shù)器等。它是一個(gè)流行的開源項(xiàng)目,并且有著龐大的社區(qū)支持。
簡(jiǎn)單動(dòng)態(tài)字符串
在 Redis 中,簡(jiǎn)單動(dòng)態(tài)字符串(SDS)是一種特殊的字符串表示形式,用于表示 Redis 中的字符串對(duì)象。SDS 是 Redis 自行實(shí)現(xiàn)的一種字符串結(jié)構(gòu),相比于 C 語言中的原始字符串,SDS 具有更多的優(yōu)勢(shì),主要體現(xiàn)在動(dòng)態(tài)調(diào)整內(nèi)存大小、二進(jìn)制安全、O(1) 復(fù)雜度的字符串長(zhǎng)度獲取等方面。
SDS 的定義
每個(gè) sds/sdshdr 結(jié)構(gòu)表述一個(gè) SDS 值:
struct sdshdr{ int len; int free; char buf[]; }
有如下結(jié)構(gòu)圖所示:
上圖中展示了 SDS 的結(jié)構(gòu)示例,其中:
- free:該屬性的值為 0,表示這個(gè) SDS 沒有分配任何未使用空間。
- len:該和塑性的值為 3。
- buf:該屬性是一個(gè) char 類型的數(shù)組,數(shù)組的前三個(gè)字符同時(shí)保存了三個(gè) R。
SDS 遵循 C 字符串以空字符串結(jié)尾的慣例,保存空字符串的 1 字節(jié)空間不計(jì)算在 SDS 的 len 屬性里面,并為空字符串分配額外的 1 字節(jié)空間以及添加空字符串到末尾等操作,都是由 SDS 函數(shù)自動(dòng)完成的,所以這個(gè)空字符串對(duì)于 SDS 的使用來說是完全透明的。
SDS 和 C 字符串的區(qū)別
簡(jiǎn)單動(dòng)態(tài)字符串(SDS)和 C 字符串在實(shí)現(xiàn)和特性上存在一些區(qū)別,這些區(qū)別使得 SDS 更適合作為 Redis 中字符串對(duì)象的內(nèi)部表示。
動(dòng)態(tài)調(diào)整內(nèi)存大小
C 字符串
C 字符串是一系列字符的數(shù)組,以 null 字符('\0')結(jié)尾。在 C 語言中,字符串的內(nèi)存大小是固定的,由數(shù)組的大小決定。例如,如果你聲明一個(gè)字符數(shù)組來存儲(chǔ)字符串,數(shù)組的大小就是字符串能夠容納的最大字符數(shù)。這就導(dǎo)致了一些限制和潛在的性能開銷:
固定大?。?C 字符串的內(nèi)存大小是固定的,因?yàn)閿?shù)組的大小在聲明時(shí)就確定了。如果字符串的長(zhǎng)度超過了數(shù)組的大小,就可能導(dǎo)致數(shù)據(jù)溢出或截?cái)唷?/p>
內(nèi)存重新分配: 當(dāng)字符串長(zhǎng)度變化時(shí),如果新的長(zhǎng)度超過了之前分配的內(nèi)存大小,就需要重新分配內(nèi)存來容納更長(zhǎng)的字符串。這涉及到動(dòng)態(tài)內(nèi)存分配和釋放的操作,通常通過 malloc、realloc 和 free 等函數(shù)來實(shí)現(xiàn)。
性能開銷: 動(dòng)態(tài)內(nèi)存分配和釋放可能引入性能開銷。重新分配內(nèi)存需要時(shí)間,并且頻繁的分配和釋放操作可能導(dǎo)致內(nèi)存碎片化,增加了程序的復(fù)雜性和運(yùn)行時(shí)的不確定性。
SDS
SDS 是 Redis 中使用的一種字符串表示方式,它具有動(dòng)態(tài)調(diào)整內(nèi)存大小的特性,以適應(yīng)字符串實(shí)際長(zhǎng)度的變化。這種設(shè)計(jì)的目標(biāo)是降低頻繁的內(nèi)存分配和釋放操作,提高內(nèi)存利用率,并減輕程序員在處理字符串時(shí)的負(fù)擔(dān)。
SDS 的核心特性是它可以動(dòng)態(tài)地調(diào)整內(nèi)存大小。當(dāng)字符串的長(zhǎng)度變化時(shí),SDS 能夠根據(jù)實(shí)際需要自動(dòng)擴(kuò)展或收縮內(nèi)存,而無需手動(dòng)進(jìn)行內(nèi)存管理。這使得 SDS 更適合處理動(dòng)態(tài)變化的字符串內(nèi)容。
SDS 通過提前分配一些額外的空間,避免了每次字符串長(zhǎng)度變化都進(jìn)行內(nèi)存重新分配的需要。這種方式減少了頻繁的內(nèi)存分配和釋放操作,提高了性能,尤其在有大量字符串動(dòng)態(tài)變化的情況下效果顯著。
SDS 的設(shè)計(jì)允許字符串的內(nèi)存大小比實(shí)際字符串長(zhǎng)度大一些,這使得 SDS 可以更靈活地適應(yīng)字符串的變化。這種方式提高了內(nèi)存利用率,減少了內(nèi)存碎片。
通過上面的比較,可以得出 C 字符串是一固定大小的字符數(shù)組,長(zhǎng)度確定后無法自動(dòng)調(diào)整。在長(zhǎng)度變化時(shí),可能需要手動(dòng)重新分配內(nèi)存,導(dǎo)致性能開銷。
SDS 是 Redis 中使用的字符串表示方式,具有動(dòng)態(tài)調(diào)整內(nèi)存大小的特性。它可以根據(jù)字符串長(zhǎng)度自動(dòng)擴(kuò)展或收縮內(nèi)存,避免頻繁的內(nèi)存分配和釋放,提高性能。SDS 還通過提前分配額外空間,靈活適應(yīng)字符串變化,提高內(nèi)存利用率。
二進(jìn)制安全
C 字符串
C 字符串以 null 字符('\0')作為結(jié)束標(biāo)志,這表示字符串的結(jié)束。這意味著在 C 字符串中,任何包含 null 字符的數(shù)據(jù)都會(huì)被視為字符串的結(jié)束,可能導(dǎo)致對(duì)于包含 null 字符的二進(jìn)制數(shù)據(jù)的不友好。
C 字符串對(duì)二進(jìn)制數(shù)據(jù)不太友好,因?yàn)樗鼘?null 字符用于終止字符串。如果二進(jìn)制數(shù)據(jù)中包含 null 字符,字符串處理函數(shù)會(huì)在遇到 null 字符時(shí)停止處理,導(dǎo)致數(shù)據(jù)截?cái)唷?/p>
SDS
SDS 對(duì)字符串的內(nèi)容沒有任何假設(shè),可以包含任意的二進(jìn)制數(shù)據(jù),包括空字符('\0')。SDS 并不以 null 字符作為字符串的結(jié)束標(biāo)志,而是使用自己的長(zhǎng)度屬性來確定字符串的長(zhǎng)度。
SDS 是二進(jìn)制安全的,因?yàn)樗梢园我獾亩M(jìn)制數(shù)據(jù),而不受 null 字符的限制。這使得 SDS 更適合存儲(chǔ)和處理二進(jìn)制數(shù)據(jù),例如圖像、音頻或其他不以 null 字符結(jié)尾的數(shù)據(jù)。
SDS 使用一個(gè)額外的長(zhǎng)度屬性來存儲(chǔ)字符串的實(shí)際長(zhǎng)度,因此可以正確處理包含 null 字符在內(nèi)的任意二進(jìn)制數(shù)據(jù)。
總體而言,SDS 在處理二進(jìn)制數(shù)據(jù)時(shí)更為靈活和安全,因?yàn)樗灰蕾囉?null 字符來表示字符串的結(jié)束,而是使用長(zhǎng)度屬性來確保對(duì)字符串的正確處理。這使得 SDS 在存儲(chǔ)和處理二進(jìn)制數(shù)據(jù)時(shí)更具通用性。
長(zhǎng)度獲取復(fù)雜度
獲取 C 字符串的長(zhǎng)度需要遍歷整個(gè)字符串,復(fù)雜度為 O(n),其中 n 是字符串的長(zhǎng)度。而獲取 SDS 字符串的長(zhǎng)度是 O(1)復(fù)雜度的操作,因?yàn)?SDS 結(jié)構(gòu)中保存了字符串的長(zhǎng)度信息。
惰性空間釋放
惰性空間釋放是一種優(yōu)化策略,它主要涉及在字符串長(zhǎng)度減小時(shí)延遲釋放多余的內(nèi)存,只在需要重新分配內(nèi)存時(shí)才進(jìn)行釋放。
C 字符串
C 字符串的內(nèi)存大小是固定的,由數(shù)組的大小決定。如果字符串長(zhǎng)度減小,內(nèi)存并不會(huì)隨之減小。
由于 C 字符串的內(nèi)存大小固定,即使字符串的實(shí)際長(zhǎng)度變小,也不會(huì)自動(dòng)釋放多余的空間。這可能導(dǎo)致內(nèi)存浪費(fèi),尤其是在字符串長(zhǎng)度經(jīng)常變化的情況下。
SDS
SDS 具有動(dòng)態(tài)調(diào)整內(nèi)存大小的特性,可以根據(jù)字符串長(zhǎng)度的變化自動(dòng)擴(kuò)展或收縮內(nèi)存。
SDS 采用惰性空間釋放策略。當(dāng)字符串長(zhǎng)度減小時(shí),并不立即釋放多余的空間,而是等到需要重新分配內(nèi)存時(shí)才進(jìn)行釋放。這樣可以減少頻繁的內(nèi)存分配和釋放操作,提高性能。
SDS 在分配內(nèi)存時(shí)通常會(huì)預(yù)留一些額外的空間,避免了每次字符串長(zhǎng)度變化都進(jìn)行內(nèi)存重新分配的需要。這也有助于減輕內(nèi)存碎片化的問題。
SDS 通過延遲釋放多余的空間,避免了在每次字符串長(zhǎng)度減小時(shí)都立即進(jìn)行內(nèi)存釋放的開銷。這在處理動(dòng)態(tài)變化的字符串長(zhǎng)度時(shí)非常有用。
總體而言,SDS 通過惰性空間釋放策略,可以更有效地管理內(nèi)存,特別是在字符串長(zhǎng)度動(dòng)態(tài)變化的情況下,避免了頻繁的內(nèi)存分配和釋放,提高了性能和內(nèi)存利用率。
兼容性
C 字符串
C 字符串是 C 語言中的基本字符串表示,由字符數(shù)組構(gòu)成,以 null 字符('\0')結(jié)尾。
C 字符串與現(xiàn)有的 C 庫和函數(shù)直接兼容。C 標(biāo)準(zhǔn)庫中的字符串處理函數(shù)(如 strlen、strcpy、strcmp 等)以及其他 C 函數(shù)都是設(shè)計(jì)用于操作以 null 結(jié)尾的 C 字符串的。
由于 C 字符串本質(zhì)上是字符數(shù)組,因此可以方便地與其他 C 數(shù)據(jù)類型進(jìn)行交互和操作。
SDS
SDS 是 Redis 中使用的一種動(dòng)態(tài)字符串表示,具有長(zhǎng)度屬性和動(dòng)態(tài)調(diào)整內(nèi)存大小的特性。
SDS 可以通過頭部和尾部的附加空間與 C 字符串兼容。即,SDS 的內(nèi)容部分可以直接當(dāng)作 C 字符串來使用。
SDS 頭部包含一個(gè)長(zhǎng)度屬性,因此可以通過訪問該屬性來獲取 SDS 的長(zhǎng)度,這使得 SDS 可以適應(yīng)使用 C 字符串表示的接口。
SDS 的內(nèi)容部分可以包含 null 字符,因此在需要時(shí)可以將 SDS 作為 C 字符串來處理,保留 C 字符串的兼容性。
SDS 也提供了一些與 C 字符串兼容的函數(shù),例如 sdslen 用于獲取 SDS 的長(zhǎng)度,sdscmp 用于比較 SDS 的內(nèi)容等。
總結(jié)
C 字符串 | SDS |
---|---|
獲取字符串長(zhǎng)度的復(fù)雜的為 O(N) | 獲取字符串長(zhǎng)度的復(fù)雜度為 O(1) |
API 是安全的,可能會(huì)造成緩沖區(qū)溢出 | API 是安全的不會(huì)造成緩沖區(qū)溢出 |
修改字符串長(zhǎng)度 N 次必然需要執(zhí)行 N 次內(nèi)存重新分配 | 修改字符串長(zhǎng)度 N 次最多需要執(zhí)行 N 次內(nèi)存重新分配 |
只能保存文本數(shù)據(jù) | 可以保存文本或者二進(jìn)制數(shù)據(jù) |
可以使用所有的 <string.h> 庫中的函數(shù) | 可以使用一部分的 <string.h> 庫中的函數(shù) |
以上就是詳解Redis中的簡(jiǎn)單動(dòng)態(tài)字符串和C字符串的區(qū)別的詳細(xì)內(nèi)容,更多關(guān)于Redis動(dòng)態(tài)字符串和C字符串區(qū)別的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Redis 對(duì)比 Memcached 并在 CentOS 下進(jìn)行安裝配置詳解
Redis 是一個(gè)開源、支持網(wǎng)絡(luò)、基于內(nèi)存、鍵值對(duì)的 Key-Value 數(shù)據(jù)庫,本篇文章主要介紹了Redis 對(duì)比 Memcached 并在 CentOS 下進(jìn)行安裝配置詳解,有興趣的可以了解一下。2016-11-11從零搭建SpringBoot2.X整合Redis框架的詳細(xì)教程
這篇文章主要介紹了從零搭建SpringBoot2.X整合Redis框架的詳細(xì)教程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-12-12Redis實(shí)戰(zhàn)之商城購物車功能的實(shí)現(xiàn)代碼
這篇文章主要介紹了Redis實(shí)戰(zhàn)之商城購物車功能的實(shí)現(xiàn)代碼,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-02-02