(一)執行緒IO模型
redis是單執行緒。memcached 是多執行緒模型,nginx 是master 和work 多程式模型
如何處理多併發客戶端連線?
非非同步IO+事件輪詢API(多路複用,相當於JAVA裡面的NIO)。
指令佇列:redis會為每個客戶端關聯一個指令佇列,通過佇列的順序進行排隊,先來先服務(響應佇列類似)
定時任務:redis的定時任務會被記錄在一個叫“最小堆”的資料結構中,最快要執行的任務排在堆的最上方
(二)通訊協議
RESP 是 Redis 序列化協議的簡寫
協議傳輸的資料結構:Redis 協議將傳輸的結構資料分為 5 種最小單元型別,單元結束時統一加上回車換行符號\r\n。
無論是客戶端-->伺服器 還是 伺服器-->客戶端都是基於下面五種資料結構的組合
1.單行字串以“+”開頭
2.多行字串以“$”開頭,後面跟字串的長度
3.數值以“:”開頭,後跟整數的字串形式
4.錯誤訊息以“-”開頭
5.陣列以“*”開頭,後跟陣列的長度
(三)持久化
持久化的目的:redis的資料全是存在記憶體的,如果突然當機,需要保證資料的完整性,就需要將資料持久化
持久化的方式:1.快照 2.AOF日誌
快照
型別:全量備份
原理:Redis 使用作業系統的多程式 COW(Copy On Write) 機制來實現快照持久化
COW機制:資料段頁面的分離
fork(多程式):Redis 在持久化時會呼叫 glibc 的函式fork產生一個子程式,快照持久化完全交給子程式來處理,父程式繼續處理客戶端請求。這樣就不會造成阻塞。
子程式只會複製資料,但是父程式會修改資料結構,如何保證持久化的資料不變:利用COW機制
AOF日誌
型別:增量備份
原理:AOF 日誌儲存的是 Redis 伺服器的順序指令序列,AOF 日誌只記錄對記憶體進行修改的指令記錄,但是注意:Redis在長期執行中會產生大量的日誌,如果redis當機,重放整個AOF日誌會非常費時,所以需要定期對AOF日誌瘦身。
運維相關
因為對資料持久化是一個非常耗資源的操作,所以一般redis的主節點主節點不會進行持久化操作,而是由從節點來備份
redis4.0採用了混合持久化的方式:rdb+aof重放的方式使重啟的效率大大提高
(四)管道
客戶端通過對管道中的指令列表改變讀寫順序就可以大幅節省 IO 時間。管道中指令越多,效果越好。
例如:客戶端傳送兩次訊息:write->read->write->read,利用管道改變讀寫順序後變為write->write->read->read,伺服器端的操作並沒有變,收到的是同樣的資料
(五)事務
multi 指示事務的開始,exec 指示事務的執行,discard 指示事務的丟棄。 所有的指令在exec之前都不執行,只是被快取到伺服器的一個佇列裡,只有在收到exec指令後才開始執行
redis的事務不能滿足原子性,僅僅是滿足了事務的隔離性(當前執行的事務不被其他事務打斷)
discard指令:用於丟棄事務快取佇列中的所有指令,在exec執行之前
watch機制
分散式鎖是一種悲觀鎖,redis提供的watch(命令)機制就是一種樂觀鎖,也可以用來解決併發修改的問題
注意事項:
redis不能在multi和exec之間使用watch命令,而必須在 multi 之前做好盯住關鍵變數,否則會出錯。
tips:悲觀鎖和樂觀鎖:讀取頻繁使用樂觀鎖,寫入頻繁使用悲觀鎖。
悲觀鎖:總是假設最壞的情況,認為每次取資料時資料都會被其他執行緒所修改,所以都會加鎖(行鎖,表鎖等),當其他執行緒想要讀取資料時,都需要阻塞掛起(互斥鎖)。可以依靠資料庫實現,如行鎖、讀鎖和寫鎖等。(synchronized的思想也是悲觀鎖)
樂觀鎖:總是認為不會有併發問題,認為每次取資料時資料不會被其他執行緒更改,所以不會加鎖,但是在更新之前會判斷資料有沒有被其他執行緒修改,一般通過版本號或CAS(自旋鎖)操作實現
(六)PubSub
PublisherSubscriber,釋出者訂閱者模型,用於支援訊息多播
詳看小冊
(七)小物件壓縮(ziplist)
ziplist是一個緊湊的位元組陣列結構
intset是一個整數陣列結構,用於存放元素都是整型且元素個數較少的set集合
(八)主從同步
一句話說明分散式CAP理論:當網路分割槽發生時,一致性和可用性兩難全(一般只保證最終一致性)。
redis保證可用性和最終一致性:即redis主節點修改資料之後直接返回,即使在從節點掛了的情況下依然保持可用性,而不保證一致性,redis保證最終一致性,即從節點在恢復正常後會採用相應的辦法保持與主庫的一致性。
主從同步
同步方法:增量同步,快照同步
增量同步:在網路不好時,從節點在短時間內無法與主節點同步,會導致需要同步的指令在buffer中被後續指令覆蓋,所以需要快照同步
當增加從節點時,必須要先進行一次快照同步,然後在進行增量同步