您好,登錄后才能下訂單哦!
本文從網絡模型、數據結構和內存管理、持久化和多機協作四個角度對redis的設計思路進行分析。
一.網絡模型
Redis是典型的基于Reactor的事件驅動模型,單進程單線程,高效的框架總是類似的。網絡模型與spp的異步模型幾乎一致。
Redis流程上整體分為接受請求處理器、響應處理器和應答處理器三個同步模塊,每一個請求都是要經歷這三個部分。
Redis集成了libevent/epoll/kqueue/select等多種事件管理機制,可以根據操作系統版本自由選擇合適的管理機制,其中libevent是最優選擇的機制。
Redis的網絡模型有著所有事件驅動模型的優點,高效低耗。但是面對耗時較長的操作的時候,同樣無法處理請求,只能等到事件處理完畢才能響應。所以了解清楚網絡模型有助于在業務中揚長避短,減少長耗時的請求,盡可能多一些簡單的短耗時請求發揮異步模型的最大的威力。
二.數據結構和內存管理
1.字符串
1.1 內存管理方式
動態內存管理方式,動態方式最大的好處就是能夠較為充分的利用內存空間,減少內存碎片化,與此同時帶來的劣勢就是容易引起頻繁的內存抖動,通常采用“空間預分配”和“惰性空間釋放”兩種優化策略來減少內存抖動,redis也不例外。
每次修改字符串內容時,首先檢查內存空間是否符合要求,否則就擴大2倍或者按M增長;減少字符串內容時,內存并不會立刻回收,而是按需回收。
關于內存管理的優化,最基本的出發點就是浪費一點空間還是犧牲一些時間的權衡,像STL、tcmalloc、protobuf3的arena機制等采用的核心思路都是“預分配遲回收”,Redis也是一樣的。
1.2 二進制安全
判斷字符串結束與否的標識是len字段,而不是C語言的’\0’,因此是二進制安全的。
放心的將pb序列化后的二進制字符串存入redis。
簡而言之,通過redis的簡單封裝,redis的字符串的操作更加方便,性能更友好,并且屏蔽了C語言字符串的一些需要用戶關心的問題。
2.字典(哈希)
字典的底層一定是hash,涉及到hash一定會涉及到hash算法、沖突的解決方法和hash表擴容和縮容。
2.1 hash算法
Redis使用的就是常用的Murmurhash3,Murmurhash算法能夠給出在任意輸入序列下的散列分布性,并且計算速度很快。之前做共享內存的Local-Cache的需求時也正是利用了Murmurhash的優勢,解決了原有結構的hash函數散列分布性差的問題。
2.2 hash沖突解決方法
鏈地址法解決hash沖突,通用解決方案沒什么特殊的。多說一句,如果選用鏈地址解決沖突,那么勢必要有一個散列性非常好的hash函數,否則hash的性能將會大大折扣。Redis選用了Murmurhash,所以可以放心大膽的采用鏈地址方案。
3.整數集合
變長整數存儲,整數分為16/32/64三個變長尺度,根據存入的數據所屬的類型,進行規劃。
每次插入新元素都有可能導致尺度升級(例如由16位漲到32位),因此插入整數的時間復雜度為O(n)。這里也是一個權衡,內存空間和時間的一個折中,盡可能節省內存。
4.跳躍表
Redis的skilplist和普通的skiplist沒什么不同,都是冗余數據實現的從粗到細的多層次鏈表,Redis中應用跳表的地方不多,常見的就是有序集合。
5.鏈表
Redis的鏈表是雙向非循環鏈表,擁有表頭和表尾指針,對于首尾的操作時間復雜度是O(1),查找時間復雜度O(n),插入時間復雜度O(1)。
三.AOF和RDB持久化
AOF持久化日志,RDB持久化實體數據,AOF優先級大于RDB。
1.AOF持久化
機制:通過定時事件將aof緩沖區內的數據定時寫到磁盤上。
2.AOF重寫
為了減少AOF大小,Redis提供了AOF重寫功能,這個重寫功能做的工作就是創建一個新AOF文件代替老的AOF,并且這個新的AOF文件沒有一條冗余指令。(例如對list先插入A/B/C,后刪除B/C,再插入D共6條指令,最終狀態為A/D,只需1條指令就可以)
實現原理就是讀現有數據庫的狀態,根據狀態反推指令,跟之前的AOF無關。同樣,為了避免長時間耗時,重寫工作放在子進程進行。
3.RDB持久化
SAVE和BGSAVE兩個命令都是用于生成RDB文件,區別在于BGSAVE會fork出一個子進程單獨進行,不影響Redis處理正常請求。定時和定次數后進行持久化操作。
簡而言之,RDB的過程其實是比較簡單的,滿足條件后直接去寫RDB文件就結束了。
四.多機和集群
1.主從服務器
避免單點是所有服務的通用問題,Redis也不例外。解決單點就要有備機,有備機就要解決固有的數據同步問題。
1.1 sync——原始版主從同步
Redis最初的同步做法是sync指令,通過sync每次都會全量數據,顯然每次都全量復制的設計比較消耗資源。改進思路也是常規邏輯,第一次全量,剩下的增量,這就是現在的psync指令的活。
1.2 psync
部分重同步實現的技術手段是“偏移序號+積壓緩沖區”,具體做法如下:
(1)主從分別維護一個seq,主每次完成一個請求便seq+1,從每同步完后更新自己seq;
(2)從每次打算同步時都是攜帶著自己的seq到主,主將自身的seq與從做差結果與積壓緩沖區大小比較,如果小于積壓緩沖區大小,直接從積壓緩沖區取相應的操作進行部分重同步;
(3)否則說明積壓緩沖區不能夠cover掉主從不一致的數據,進行全量同步。
本質做法用空間換時間,顯然在這里犧牲部分空間換回高效的部分重同步,收益比很大。
2.Sentinel
本質:多主從服務器的Redis系統,多臺主從上加了管理監控,以保證系統高可用性。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。