redis設計思想

來源:互聯網
上載者:User
不同於nginx的精雕細琢,redis代碼的風格趨向於簡潔實用。簡潔啟事,下面所述不再列舉任何源碼,不拼湊任何外來資料。去除末枝,下面直入redis主題,儘可能簡潔地描述redis的設計思想。 整體模型:單進程單線程事件驅動模式。 Redis在主處理流程中,採用了單進程接受各種client請求並返回結果,整體處理流程採用事件驅動的方式進行。通過其IO複用的方式監聽aeEventLoop事件,在事件處理的過程中,這種模式對處理函數的要求:進行一次事件處理需要儘可能地快。因此會有以下幾種處理方法: 1.對於非長時間處理事件,直接處理。如set命令; 2.對於需要長時間處理的事件,分步處理,直至完成。如rehash過程,在單次事件處理過程中,每次只移動一個桶。 3.對於阻塞函數,如從磁碟讀取vm資料等,採用非同步模式。從磁碟load資料,是一個較為耗時的操作,如處理函數中直接讀取資料,將會阻塞整體的單線程處理其他的client請求。 多線程開發的複雜性是我們所清楚的。採用單進程單線程的模式,可以避免很多複雜性,另外事務性操作,無須額外加鎖,大大降低了開發難度。 IO複用 Redis的IO複用層,可以看作是一個tiny libevent,其實現只有四個檔案,ae.c,ae_select.c, ae_kqueue.c,ae_epoll.c。一目瞭然,ae是事件監聽總的interface,select、kqueque、epoll是三種可選的IO複用方式。小而夠用,簡潔高效,充分體現了redis的設計理念。Redis Default:select,C10K max。 事件監聽 在單線程事件驅動模型中,往往會遇到兩種任務,定時處理任務及事件觸發任務,於是會有如下問題:事件觸發任務在無任務時,會處於阻塞狀態;定時任務要求定時處理,於是往往會有如下兩種處理方式: 1. 如果定時任務時間間隔為t,一般設IO複用層的逾時時間為t/10,這樣可以保證定時任務得到及時處理,在調用所有cron任務時,會做間隔時間判斷。 2. 計算當前事件與最近的定時任務開始時間的間隔,設定IO複用逾時時間為該事件。這樣定時任務也能得到及時處理。 注意:以上定時任務的處理時間,都為估約時間,非精確時間。前一種方式每輪計算量少,當容易引起空轉,後一種計算量大,但減少了空轉次數。Redis採用的是後一種方式。 這裡也許有人會問:為什麼不採用sigaction、setitimer等設定精確時鐘,以後再也不用為cron事件做額外處理。原因如下: 定時時鐘,往往會讓進程陷入核心態,核心非強制中斷往往會打破使用者態一個函數的完整性,因此會破壞相關的狀態轉移;另外加入非強制中斷的程式,將可能為程式帶來不可避免地複雜性。 以曾經做過一個項目的一段挫折經曆為例: 一個電話多路呼轉的項目,採用的是單線程非同步事件驅動模型,每次定時任務有個讓空閑通道“掛機”的任務。先前採用預製的驅動時鐘,時鐘訊號為即時訊號(訊號宏值取32-64之間的一個數),訊號在sigqueue中排隊,這樣如果任務阻塞返回後,會瞬間拋出大量時鐘事件,造成空閑通道多次掛機失敗。後改用setitimer設定系統時鐘,非強制中斷打斷了使用者態的一次mutex_lock和mutex_unlock,並且掛機時使用了該鎖,造成整個進程時有時無的死結現象。 資料結構 Intset,該set不同於hash set資料結構,該資料結構其實是一個有序數組,對於: 插入操作:二分尋找該有序數組——>找到位置——>有則返回,無則插入該位置,memmove後續元素。 尋找操作:二分尋找。 相對於以hash table為基礎的set而言,該模型簡單且更省空間。時間複雜度,在作者的presentation中提及在size 20-50k的資料量下,基本與hashset無異。這裡可以認為,hash set遍曆鏈表的時間,與intset二分尋找的時間基本差不多。但其實另一方面,作者沒有提及的,intset的插入速度,實際降低了,因為需要memmove的資料量,是O(n)的;但較hash set更有優勢的是,該array set,是有序的。 Ziplist,該資料結構是針對small size資料設計的數組list,好比常見的索引數組,不同於linked list,其儲存在一個數組中,且用value-header儲存連結項及其本身的位移、長度,encoding等,用於遍曆list。在需求上,encoding保證多種不同的資料,可以儲存在同一個list中,如int16、int32、str等。 zset:hash dict + skip list。常見的有序set以rb tree為基礎。而在整個redis中,我們很難發現任何複雜資料結構tree的蹤影。Redis以hash dict保證散列尋找的效率,以跳錶結構保證有序及範圍尋找需求的快速滿足,範圍尋找拋棄了rb tree,b+-* tree,也體現了其不想複雜的簡潔美學。 ...... 整個redis中,沒有任何專門的記憶體池結構。所有記憶體配置,不像stl,niginx,記憶體配置都有其記憶體池機構分配,redis沒有。Redis全是size+malloc的zmalloc分配,其常見的小對象,在intset,ziplist等資料結構地以數組方式申請,並不斷用realloc的方式resize,間接地體現了記憶體池的思想,但卻沒有實現一個記憶體池管理模組,作者簡單暴力的美學,體現得淋漓盡致。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.