Redis單機資料庫
單機資料庫
·Redis伺服器的所有資料庫都儲存在redisServer.db陣列中,而資料庫的數量則由redisServer.dbnum屬性儲存。
·客戶端通過修改目標資料庫指標,讓它指向redisServer.db陣列中的不同元素來切換不同的資料庫。
·資料庫主要由dict和expires兩個字典構成,其中dict字典負責儲存鍵值對,而expires字典則負責儲存鍵的過期時間。
·因為資料庫由字典構成,所以對資料庫的操作都是建立在字典操作之上的。
·資料庫的鍵總是一個字串物件,而值則可以是任意一種Redis物件型別,包括字串物件、雜湊表物件、集合物件、列表物件和有序集合物件,分別對應字串鍵、雜湊表鍵、集合鍵、列表鍵和有序集合鍵。
·expires字典的鍵指向資料庫中的某個鍵,而值則記錄了資料庫鍵的過期時間,過期時間是一個以毫秒為單位的UNIX時間戳。
·Redis使用惰性刪除和定期刪除兩種策略來刪除過期的鍵:惰性刪除策略只在碰到過期鍵時才進行刪除操作,定期刪除策略則每隔一段時間主動查詢並刪除過期鍵。
·執行SAVE命令或者BGSAVE命令所產生的新RDB檔案不會包含已經過期的鍵。
·執行BGREWRITEAOF命令所產生的重寫AOF檔案不會包含已經過期的鍵。
·當一個過期鍵被刪除之後,伺服器會追加一條DEL命令到現有AOF檔案的末尾,顯式地刪除過期鍵。
·當主伺服器刪除一個過期鍵之後,它會向所有從伺服器傳送一條DEL命令,顯式地刪除過期鍵。
·從伺服器即使發現過期鍵也不會自作主張地刪除它,而是等待主節點發來DEL命令,這種統一、中心化的過期鍵刪除策略可以保證主從伺服器資料的一致性。
·當Redis命令對資料庫進行修改之後,伺服器會根據配置向客戶端傳送資料庫通知。
RDB持久化
RDB持久化既可以手動執行,也可以根據伺服器配置選項定期執行,該功能可以將某個時間點上的資料庫狀態儲存到一個RDB檔案中。
·RDB檔案用於儲存和還原Redis伺服器所有資料庫中的所有鍵值對資料。
·SAVE命令由伺服器程序直接執行儲存操作,所以該命令會阻塞伺服器。
·BGSAVE令由子程序執行儲存操作,所以該命令不會阻塞伺服器。
·伺服器狀態中會儲存所有用save選項設定的儲存條件,當任意一個儲存條件被滿足時,伺服器會自動執行BGSAVE命令。
·RDB檔案是一個經過壓縮的二進位制檔案,由多個部分組成。
·對於不同型別的鍵值對,RDB檔案會使用不同的方式來儲存它們。
AOF持久化
除了RDB持久化功能之外,Redis還提供了AOF(Append Only File)持久化功能。與RDB持久化通過儲存資料庫中的鍵值對來記錄資料庫狀態不同,AOF持久化是通過儲存Redis伺服器所執行的寫命令來記錄資料庫狀態的。
·AOF檔案通過儲存所有修改資料庫的寫命令請求來記錄伺服器的資料庫狀態。
·AOF檔案中的所有命令都以Redis命令請求協議的格式儲存。
·命令請求會先儲存到AOF緩衝區裡面,之後再定期寫入並同步到AOF檔案。
·appendfsync選項的不同值對AOF持久化功能的安全性以及Redis伺服器的效能有很大的影響。
·伺服器只要載入並重新執行儲存在AOF檔案中的命令,就可以還原資料庫本來的狀態。
·AOF重寫可以產生一個新的AOF檔案,這個新的AOF檔案和原有的AOF檔案所儲存的資料庫狀態一樣,但體積更小。
·AOF重寫是一個有歧義的名字,該功能是通過讀取資料庫中的鍵值對來實現的,程式無須對現有AOF檔案進行任何讀入、分析或者寫入操作。
·在執行BGREWRITEAOF命令時,Redis伺服器會維護一個AOF重寫緩衝區,該緩衝區會在子程序建立新AOF檔案期間,記錄伺服器執行的所有寫命令。當子程序完成建立新AOF檔案的工作之後,伺服器會將重寫緩衝區中的所有內容追加到新AOF檔案的末尾,使得新舊兩個AOF檔案所儲存的資料庫狀態一致。最後,伺服器用新的AOF檔案替換舊的AOF檔案,以此來完成AOF檔案重寫操作。
事件
·檔案事件(file event):Redis伺服器通過套接字與客戶端(或者其他Redis伺服器)進行連線,而檔案事件就是伺服器對套接字操作的抽象。伺服器與客戶端(或者其他伺服器)的通訊會產生相應的檔案事件,而伺服器則通過監聽並處理這些事件來完成一系列網路通訊操作。
·時間事件(time event):Redis伺服器中的一些操作(比如serverCron函式)需要在給定的時間點執行,而時間事件就是伺服器對這類定時操作的抽象。
·檔案事件處理器是基於Reactor模式實現的網路通訊程式。
·檔案事件是對套接字操作的抽象:每次套接字變為可應答(acceptable)、可寫(writable)或者可讀(readable)時,相應的檔案事件就會產生。
·檔案事件分為AE_READABLE事件(讀事件)和AE_WRITABLE事件(寫事件)兩類。
·時間事件分為定時事件和週期性事件:定時事件只在指定的時間到達一次,而週期性事件則每隔一段時間到達一次。
·伺服器在一般情況下只執行serverCron函式一個時間事件,並且這個事件是週期性事件。
·檔案事件和時間事件之間是合作關係,伺服器會輪流處理這兩種事件,並且處理事件的過程中也不會進行搶佔。
·時間事件的實際處理時間通常會比設定的到達時間晚一些。
客戶端
·伺服器狀態結構使用clients連結串列連線起多個客戶端狀態,新新增的客戶端狀態會被放到連結串列的末尾。
·客戶端狀態的flags屬性使用不同標誌來表示客戶端的角色,以及客戶端當前所處的狀態。
·輸入緩衝區記錄了客戶端傳送的命令請求,這個緩衝區的大小不能超過1GB。
·命令的引數和引數個數會被記錄在客戶端狀態的argv和argc屬性裡面,而cmd屬性則記錄了客戶端要執行命令的實現函式。
·客戶端有固定大小緩衝區和可變大小緩衝區兩種緩衝區可用,其中固定大小緩衝區的最大大小為16KB,而可變大小緩衝區的最大大小不能超過伺服器設定的硬性限制值。
·輸出緩衝區限制值有兩種,如果輸出緩衝區的大小超過了伺服器設定的硬性限制,那麼客戶端會被立即關閉;除此之外,如果客戶端在一定時間內,一直超過伺服器設定的軟性限制,那麼客戶端也會被關閉。
·當一個客戶端通過網路連線連上伺服器時,伺服器會為這個客戶端建立相應的客戶端狀態。網路連線關閉、傳送了不合協議格式的命令請求、成為CLIENT KILL命令的目標、空轉時間超時、輸出緩衝區的大小超出限制,以上這些原因都會造成客戶端被關閉。
·處理Lua指令碼的偽客戶端在伺服器初始化時建立,這個客戶端會一直存在,直到伺服器關閉。
·載入AOF檔案時使用的偽客戶端在載入工作開始時動態建立,載入工作完畢之後關閉。
伺服器
·一個命令請求從傳送到完成主要包括以下步驟:1)客戶端將命令請求傳送給伺服器;2)伺服器讀取命令請求,並分析出命令引數;3)命令執行器根據引數查詢命令的實現函式,然後執行實現函式並得出命令回覆;4)伺服器將命令回覆返回給客戶端。
·serverCron函式預設每隔100毫秒執行一次,它的工作主要包括更新伺服器狀態資訊,處理伺服器接收的SIGTERM訊號,管理客戶端資源和資料庫狀態,檢查並執行持久化操作等等。
·伺服器從啟動到能夠處理客戶端的命令請求需要執行以下步驟:1)初始化伺服器狀態;2)載入伺服器配置;3)初始化伺服器資料結構;4)還原資料庫狀態;5)執行事件迴圈。
引用
《Redis 設計與實現》