Redis數據結構
- 引言
- 數據結構
- string
- SDS數據結構
- 原生string的不足
- hash
本博客基于《Redis設計與實現》進行整理和補充,該書依賴于Redis 3.0版本,但是Redis6.0版本在一些底層實現上仍然沒有明顯的變動,因此本文將在該書的基礎上,對于后面進行變更的一些技術項進行額外說明,當然我相信大家學習Redis,可能更多的是進行面試,本博客的一個功利目的,也是希望讀完本書之后對于市面上常見的redis面試題能做到心中有數,直接秒殺。
引言
Redis是什么,大家可能會不假思索的說出 是個緩存中間件,但是如果只是緩存的話,我們為什么不能直接使用本地緩存,或者mongo這樣的nosql呢,那么這里呢,我們就要從一個更高更抽象的角度去理解Redis,Redis并不是在開發過程中必須存在的中間件,甚至在最開始單機開發的場景,我們可以完全不用Redis,我們從Redis這幾個字母上來理解一下Redis的含義,Re- Remote Di- dictionary S-server 遠程字典服務,也就是他其實就是一個遠程的本地字典存儲。
本地緩存的缺點是很明顯的,如果我們不使用比如guava或者caffine這樣的本地緩存管理包, 那么在本地僅僅是管理緩存就是一件很困難的事情,更何況 本地緩存也更加不適合分布式的開發環境,重啟服務緩存消失這樣的問題。而mongo將數據存儲在磁盤上,從而導致,讀寫速度可能會成為mongo的瓶頸。正是因為有著這樣的問題,因此我們才單獨將一些需要進行告訴讀取寫入存儲一些字典的功能交給了一個更合適的遠程服務 即是 Redis。
而在使用上,我們甚至可以直接理解為Redis就是一個遠程的Hash,我們能像使用本地緩存那樣使用Redis,而不需要單獨考慮數據會不會丟失,數據一致性問題等等。
當然我們現在還是要看一個更加學術并且權威的介紹,這里我直接給到Redis最新的intro:
Redis is an open source (BSD licensed), in-memory data structure store used as a database, cache, message broker, and streaming engine. Redis provides data structures such as strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglogs, geospatial indexes, and streams
Redis是一款擁有BSD授權的開源軟件,可以存儲一些內存數據結構數據,你可以把它用作數據庫緩存,消息中間存儲,流引擎。 Redis支持的數據結構有字符串,hash,列表,集合,帶范圍的有序列表,位圖,hyperloglogs,gis存儲和流。
好,那么經過上面的簡單介紹,我們接下來將繼續更加深入的學習Redis的數據結構。
數據結構
redis所有的存儲類型都是一個的鍵值對類型,其中key的類型肯定是一個字符串,而value的存儲對象則有 string,hash,set等類型,下面我們會對這些類型的底層實現進行更詳細的探討。
string
redis是使用c語言編寫的,在c語言中,并沒有string這個內置類型,而是使用char[]來代替string,但是很顯然[]char類型有很多問題,所以redis采用SDS來實現字符串。
SDS數據結構
在開始之前我們有必要首先了解一下SDS的數據結構
struct sdshdr {int len; //記錄使用長度int free; // 記錄還沒有使用的長度char buf[] // 實際進行的數據存儲
}
我們下面詳細探討一下char[]可能存在的問題,以及SDS是如何通過自身的數據結構解決的
原生string的不足
- 獲取字符串長度原生char[]時間復雜度為O(N)
c語言中,char[]數組的結尾事’\0’,我們如果想要獲取一個char[]數組的長度的話唯一的方法就是,不斷的從頭遍歷,直到讀到空字符,所以為了防止僅僅是獲取數組長度這個功能成為性能瓶頸,我們采用len字段記錄了char[]數組的長度
- 存儲 空字符
在char[]我們顯然沒有辦法直接存儲’\0’,因為我們一讀到空白符,就默認無法已經結束了,因此我們在sds中可以對這種特殊字符進行編碼,從而方便我們在寫入值時,更加靈活多樣