Redis設計與實現閱讀總結(二)單機資料庫的實現

不知發表於2019-03-22

書的重點內容逐漸到了,我們的寫作方式也該換一下了,不會像(一)一樣流水賬式了的解釋幾種資料結構了

在第一篇文章中,我簡略的解釋下有關的資料結構,現在我們開始想想如何實現

先提幾個問題

  • 如何實現多資料庫
  • redis資料是存在記憶體中的,但是這樣資料存在丟失的風險,那我們怎樣化解決這個問題
  • redis伺服器和多個客戶端的互動是怎樣實現的呢

在我看來,該書第二部分<單機資料庫的實現>就是圍繞上面的幾個問題,來用列舉式行文寫下相應部分知識點的。

伺服器中的資料庫

看到這個多字,其實我們很容易就想到用連結串列的方式去儲存

一個伺服器,先假設是一個簡單的struct結構來維護的,我們想在其中實現多資料庫,自然想到,在其中新增一個鍵值對,而這個值我們使用一個連結串列

這個連結串列中存放一個又一個的指標,每個指標指向一個struct結構(維護著資料庫結構的struct)

好,這樣,我們就簡單的實現這個

Redis設計與實現閱讀總結(二)單機資料庫的實現

然後我們再去實現單資料庫

伺服器中的多資料庫

每個資料庫中那有該如何存放資料呢

由於redis是kv資料庫,資料都是以kv形式存在的,那我們完全就可以用字典去實現

鍵值對中的值可以是(一)中的多種形式,那麼,

下圖的形式就能得出了

Redis設計與實現閱讀總結(二)單機資料庫的實現

到了這裡後,書上將過期問題在後續進行了說明。

過期問題

書籍主要是解釋了 列舉式解釋了相關命令

我覺得比較重要是redis的過期鍵刪除策略

一個經典的問題是:如果一個鍵過期了,那麼它什麼時候會被刪除呢?

這個問題有三種可能的答案,它們分別代表了三種不同的刪除策略:

  • 定時刪除:在設定鍵的過期時間的同時,建立一個定時器(timer),讓定時器在鍵的過期時間來臨時,立即執行對鍵的刪除操作。

    • 優點:對記憶體是最友好的:通過使用定時器,定時刪除策略可以保證過期鍵會盡可能快地被刪除,並釋放過期鍵所佔用的記憶體。
    • 缺點:它對CPU時間是最不友好的:在過期鍵比較多的情況下,刪除過期鍵這一行為可能會佔用相當一部分CPU時間 | 建立一個定時器需要用到Redis伺服器中的時間事件,而當前時間事件的實現方式——無序連結串列,查詢一個事件的時間複雜度為O(N)
  • 惰性刪除:放任鍵過期不管,但是每次從鍵空間中獲取鍵時,都檢查取得的鍵是否過期,如果過期的話,就刪除該鍵;如果沒有過期,就返回該鍵。

    • 對CPU時間來說是最友好的。 這個策略不會在刪除其他無關的過期鍵上花費任何CPU時間
    • 它對記憶體是最不友好的:如果一個鍵已經過期,而這個鍵又仍然保留在資料庫中,那麼只要這個過期鍵不被刪除,它所佔用的記憶體就不會釋放
  • 定期刪除:每隔一段時間,程式就對資料庫進行一次檢查,刪除裡面的過期鍵。至於要刪除多少過期鍵,以及要檢查多少個資料庫,則由演算法決定

    • 定期刪除策略是前兩種策略的一種整合和折中
    • 定期刪除策略的難點是確定刪除操作執行的時長和頻率。

上面大概性的介紹了資料庫的儲存實現,但是現在資料仍然保持在記憶體中的,但是這樣資料存在丟失的風險,這個時候我們應該設計持久化的策略了。

Redis的持久化

Redis 分別提供了 RDB 和 AOF 兩種持久化機制:

RDB 將資料庫的快照(snapshot)以二進位制的方式儲存到磁碟中。 AOF 則以協議文字的方式,將所有對資料庫進行過寫入的命令(及其引數)記錄到 AOF 檔案,以此達到記錄資料庫狀態的目的

我們繼續想第三個問題,客戶端和伺服器是如何互動的?

Redis客戶端和伺服器的互動

關於這一點,書上用了三個章節來講解。

分別是 伺服器事件客戶端伺服器

Redis的事件處理器是單執行緒的,但並不意味著Redis就是單執行緒的!

I/O多路服用程式

Redis的事件處理機制是I/O多路複用的。多個檔案事件可能併發的出現,但是I/O多路複用程式會將所有的產生的套接字放到一個佇列裡。

以有序,同步的方式,I/O多路複用程式向檔案事件分派器傳送套接字,當一個套接字處理完,才會傳送下一個。

I/O多路複用程式底層有多種實現可以選擇,epoll,select,evport,kqueue.

檔案事件處理器

  1. 連線應答處理器

     為了對連線伺服器的客戶端進行應答,伺服器為套接字連線進行應答的處理器
    複製程式碼
  2. 命令處理器

  3. 命令回覆處理器

後面主要就是 伺服器和客戶端的通訊協議部分,這部分我不準備講解,也不是什麼特別重要和難點的部分,就略過了

相關文章