淺談Redis架構

    REDIS是一個開源的、先進的鍵值存儲系統。它一般能夠被用做數據結構服務器,由於它的鍵能夠包含字符串(string)、哈希值(hash)、列表(list)、集合(set)以及有序集合(sortedset)。並且Redis使用的是內存數據集合。根據你自身的使用狀況,你能夠定時將這些內存中的數據保存至磁盤中,或者將每一個命令都添加至日誌中。你能夠經過redis的項目主頁瞭解它的更多功能。Redis最初的做者是Salvatore Sanfilippo,而且VMWare從2010年5月份開始資助該項目。目前,Redis已經被用在不少重要產品和服務之中,如:github、stackoverflow、Disqus、Guardian以及你訪問的不少網頁。git

    Redis是使用ANSI C標準編寫的,能夠在不依賴其餘程序的狀況下運行在大部分POSIX系統中,如:Linux、BSD以及Solaris。而從我有限的角度來看,redis的代碼很是簡單並且易於閱讀;並且它的代碼庫不是很大(2.2版本大約爲20k),同時它的內部結構在網站上都被很好的記錄在文檔中。在繼續這篇文章以前我邀請你首先看下由做者本人最近寫的他本身的發展哲學的聲明。下面我引用一段其中我很是讚揚的話:github

咱們樂於優化。咱們堅信寫代碼是一項很是艱難的工做,而值得堅持的惟一方法就是享受寫代碼;當你再也不享受寫代碼的過程時,那麼最好的作法是停一停。爲了防止這種狀況的發生,咱們會盡可能避免有下降redis開發樂趣的事情發生。redis

這篇文章將嘗試這去總結我對幫助文檔和源碼的一些理解。Redis是一個Client/Server模式的系統,典型的調度圖以下:服務器

Redis服務端是一個進程,該進程經過TCP協議和客戶端進行會話。網絡

雖然redis-cli是官方提供的客戶端,可是第三方項目實現了其餘語言的客戶端,如:C++, C#, Clojure, Common Lisp, Erlang, Haskell, Java, JavaScript,Lua, Objective-C, Perl, PHP, Python, R, Ruby, Scala, Go以及Tcl。因爲在官網上都有關於協議的說明文檔,所以你也能夠根據官網上的協議文檔實現本身的協議。除此以外,redis的主從複製功能可能也是大多數人所須要的。數據結構

我設計了一個關於源代碼的模塊化視圖以下:app

  1. redis 是服務端守護進程。它是由一個單一的redis.c文件組成,大約爲6k。socket

  2. networking 網絡功能的實現代碼。尤爲是基於事件的邏輯,能夠經過epoll、kqueue以及select等系統調用實現。ide

  3. datastructure 標識服務器所使用的重要數據結構。相當重要的是例如sds.c表示redis編寫的全部代碼所使用的字符串模塊化

  4. redis-cli 表示客戶端命令行


Redis
是如何工做的

從其根原本看,redis是一個單線程的服務器。這意味着經過一個單獨的線程使用事件模式如epoll、kqueue、select來讀取傳入的鏈接。當一個特定的時間生成一個文件描述符後,這個線程處理這些文件描述符並會寫響應結果。這個UML序列圖顯示了一個命令被客戶端接受後是如何被redis在內部處理的:

Redis使用自定義的時間庫,該庫抽象了低層面的socket管理。核心對象是eventLoop,它包含了已經被scoket I/O釋放的事件。同時,aeApiPoll(eventLoop)檢查全部的socket描述符來肯定是否還有網絡處於激活狀態。而在aeProcessEvents方法中,全部被釋放的事件都會被檢查並調用適當的處理程序。對於協議中的全部命令,redis會攔截全部命令並經過一個命令表單來查找合適的操做來執行。命令表單被定義在redis.c中,具體以下:

這個結構的第二個參數是要調用的方法的名稱。例如,saveCommand方法實現以下:

addReply方法被用來推送相應結果至客戶端。

以上內容快速回顧:

redis使用一個單獨的線程來管理同步全部網絡鏈接。redis實現了一個輕量級的事件庫來抽線unix系統的一些系統調用(如epoll, select, kqueue)。在redis的郵件列表中,在推進使用新的事件庫仍是依賴已有的開源庫這個問題上有一個有趣的爭論。

請求經過命令來完成。redis使用了一個命令列表,在從socket中讀取到相關命令後經過該列表來找到並調用執行須要的操做。

基礎數據結構是SDS字符串。

數據存儲管理

Redis實例包括表明服務器狀態的全局變量。例如在redis.c中的定義以下:

其中,變量redisDB的定義以下:

其中dict是redis模型中使用的內存數據結構。它在dict.c中定義,當你須要實現一個hashtable時,它可提供一系列所須要的方法,例如:

若是咱們來看一個最重要的命令-set command-命令,咱們會看到如下代碼:

Redis啓動原理

啓動過程很是簡單。如前所說,redis實例是由一組全局變量組成,並經過方法來訪問這些變量。redis服務器main方法以下:

在讀取完配置文件以後,initServer方法會被調用。該方法會初始化redis的全部全局變量。特別是它建立一組連接列表用於管理:

同時,它還建立最重要的數據結構:

它還初始化事件庫來建立eventloop以及服務端socket。最終,進入主循環來管理客戶端I/O:

aeProcessEvents就是在上一小節中分析的方法。

虛擬內存

Redis也支持虛擬內存:這意味着,當你的數據集不適合放在RAM中,redis能夠支持回寫在磁盤上。

Redis語言及工具概述

相關文章
相關標籤/搜索