Redis 模擬簡單鍵值資料庫

2021-10-18 16:24:47 字數 3179 閱讀 9600

redis核心技術與實戰 - 01

目錄

1、可以儲存那些資料

redis的value可以儲存豐富的【資料型別】

2、可以對資料做什麼操作

redis提供了基本的增刪改查等和基於複雜value型別操作介面

3、如何儲存鍵值對(記憶體還是外存)

redis以記憶體為主儲存鍵值對,但存在一旦掉電,資料就會全部消失問題,提供【redis的持久化方式】。

4、鍵值對資料庫基本架構

5、採用什麼訪問模式

redis採用的是網路框架訪問【redis使用單執行緒並提供高效服務】

6、如何定位鍵值對位置

redis採用hash表定位key,並對於複雜資料型別的value的訪問也需要索引,redis 採用一些常見的高效索引結構作為某些 value 型別的底層資料結構。【redis底層資料結構】

7、不同操作的具體邏輯是怎樣的

8、如何進行記憶體分配

redis以記憶體儲存為主,redis 的記憶體分配器提供了多種選擇,分配效率也不一樣。

9、如何實現重啟後快速提供服務

redis的高可靠不僅體現在資料少丟失,還體現在服務不中斷【主從複製讀寫分離(多例項提供資料服務)】【哨兵機制(監控主庫狀態)】【哨兵集群(監控哨兵狀態)】

對於鍵值資料庫而言,基本的資料模型是 key-value 模型;

不同的資料庫支援的key 的資料型別一般差異不大,而 value 儲存的資料型別則有較大差別。

put/get/delete/scan 是乙個鍵值資料庫的基本操作集合。scan 操作,即根據一段 key 的範圍返回相應的 value 值。根據value的不同型別,提供不同的操作介面。

記憶體讀取速度快,但是一旦斷電資料就會完全丟失,但是儲存在外存,雖然可以避免資料丟失,卻受限於磁碟的慢速讀寫(通常在幾 ms 級別),鍵值資料庫的整體效能會被拉低。

如何進行設計選擇,我們通常需要考慮鍵值資料庫的主要應用場景:

比如,快取場景下的資料需要能快速訪問但允許丟失,那麼,用於此場景的鍵值資料庫通常採用記憶體儲存鍵值資料。

乙個鍵值資料庫包括了訪問框架、索引模組、操作模組和儲存模組四部分

訪問模式通常有兩種:

一種是通過函式庫呼叫的方式供外部應用使用,比如,上圖中的 lib******kv.so,就是以動態鏈結庫的形式鏈結到我們自己的程式中,提供鍵值儲存功能;

另一種是通過網路框架以 socket 通訊的形式對外提供鍵值對操作,這種形式可以提供廣泛的鍵值儲存服務。

在上圖中,我們可以看到,網路框架中包括 socket server 和協議解析。

redis 則是通過網路框架訪問, redis 現有的客戶端和通訊協議。對於網路連線的處理、網路請求的解析,以及資料訪問的處理,redis採取的是單執行緒,redis如何通過單執行緒實現高效能的呢?

通過網路框架提供鍵值儲存服務,一方面擴大了鍵值資料庫的受用面,但另一方面,也給鍵值資料庫的效能、執行模型提供了不同的設計選擇,帶來了一些潛在的問題。

舉個例子,當客戶端傳送乙個命令(put hello world)後,該命令會被封裝在網路包中傳送給鍵值資料庫。鍵值資料庫網路框架接收到網路包,並按照相應的協議進行解析之後,就可以知道,客戶端想寫入乙個鍵值對,並開始實際的寫入流程。

此時,我們會遇到乙個系統設計上的問題,簡單來說,就是網路連線的處理、網路請求的解析,以及資料訪問的處理,是用乙個執行緒、多個執行緒,還是多個程序來互動處理呢?該如何進行設計和取捨呢?我們一般把這個問題稱為 i/o 模型設計。不同的 i/o 模型對鍵值資料庫的效能和可擴充套件性會有不同的影響。舉個例子,如果乙個執行緒既要處理網路連線、解析請求,又要完成資料訪問,一旦某一步操作發生阻塞,整個執行緒就會阻塞住,這就降低了系統響應速度。如果我們採用不同執行緒處理不同操作,那麼,某個執行緒被阻塞時,其他執行緒還能正常執行。但是,不同執行緒間如果需要訪問共享資源,那又會產生執行緒競爭,也會影響系統效率,這又該怎麼辦呢?所以,這的確是個「兩難」選擇,需要我們進行精心的設計。你可能經常聽說 redis 是單執行緒,那麼,redis 又是如何做到「單執行緒,高效能」的呢?後面我再和你好好聊一聊。

當鍵值對資料庫接收到服務請求,需要查詢所要操作的鍵值對是否存在,這依賴於鍵值資料庫的索引模組。索引的作用是讓鍵值資料庫根據 key 找到相應 value 的儲存位置,進而執行操作。

索引的型別有很多,常見的有雜湊表、b+ 樹、字典樹等。不同的索引結構在效能、空間消耗、併發控制等方面具有不同的特徵。如果你看過其他鍵值資料庫,就會發現,不同鍵值資料庫採用的索引並不相同,例如,memcached 和redis 採用雜湊表作為 key-value 索引,而 rocksdb 則採用跳表作為記憶體中 key-value 的索引。

一般而言,記憶體鍵值資料庫(例如 redis)採用雜湊表作為索引,很大一部分原因在於,其鍵值資料基本都是儲存在記憶體中的,而記憶體的高效能隨機訪問特性可以很好地與雜湊表 o(1) 的操作複雜度相匹配。

對於 redis 而言,很有意思的一點是,它的 value 支援多種型別,當我們通過索引找到乙個 key 所對應的 value 後,仍然需要從 value 的複雜結構(例如集合和列表)中進一步找到我們實際需要的資料,這個操作的效率本身就依賴於它們的實現結構。redis 採用一些常見的高效索引結構作為某些 value 型別的底層資料結構,這一技術路線為 redis 實現高效能訪問提供了良好的支撐。

常用的記憶體分配器 glibc 的 malloc 和 free,這樣使得鍵值資料庫不需要特別考慮記憶體空間的管理問題。

但是,鍵值資料庫的鍵值對通常大小不一,glibc 的分配器在處理隨機的大小記憶體塊分配時,表現並不好。一旦儲存的鍵值對資料規模過大,就可能會造成較嚴重的記憶體碎片問題。

因此,分配器是鍵值資料庫中的乙個關鍵因素。對於以記憶體儲存為主的 redis 而言,這點尤為重要。redis 的記憶體分配器提供了多種選擇,分配效率也不一樣。

鍵值資料庫雖然依賴於記憶體儲存資料,提供快速訪問,但是,也希望其重啟後能快速重新提供服務,因此需要增加持久化功能。

一種方式是,對於每乙個鍵值對,鍵值資料庫都對其進行落盤儲存,這雖然讓資料更加可靠,但是,因為每次都要寫盤,對鍵值對資料庫的效能會受到很大影響。

另一種方式是,鍵值資料庫只是周期性地把記憶體中的鍵值資料儲存到檔案中,這樣可以避免頻繁寫盤操作的效能影響。但是,乙個潛在的代價是資料仍然有丟失的風險。

高效能鍵值對資料庫 Redis

支援持久化,可以進行資料災難恢復 string 型別資料的基本操作 新增 修改多個資料 獲取多個資料 獲取資料 刪除資料 判定性新增資料 獲取資料字元個數 字串長度 追加資訊到原始資訊後部 如果原始資訊存在就追加,否則新建 hash 型別資料的基本操作 新增 修改多個資料 獲取資料 獲取多個資料 h...

Redis基礎篇 01鍵值資料庫基礎架構

1 更好的學習方式 1 先建立起 系統觀 也就是說,如果我們想要深入理解和優化 redis,就必須要對它的總體架構和關鍵模組有乙個全域性的認知,然後再深入到具體的技術點 2 專欄講解方式 1 通過剖析乙個最簡單 kv 鍵值資料庫,來迅速抓住學習和調優 redis 的關鍵 1 kv 的基本內部架構 1...

Django 資料庫鍵值處理

這節我們學習python資料庫表表之間的鍵處理 主要有三種鍵 onetoone,foreignkey,manytomany 一 foreignkey 1.父表呼叫子表 這樣也叫反向查詢 fatherobject.sonname set.all 這樣可以拿到子表的集合 fatherobject是父類物...