Redis 為什么響應快
1. 數據保存在內存中
Redis 數據保存在內存中,讀寫操作只要訪問內存,不需要磁盤 IO。
2. 底層數據結構
如下:
Redis 的數據以 key:value 的格式存儲在散列表中,時間復雜度 o(1)。
Redis 為 value 定義了豐富的數據結構,包括動態字符串、雙向鏈表、壓縮列表、hash、跳表和整數數組,可以根據 value 的特性選擇選擇最高效的數據結構。
3. 單線程模型
Redis 的網絡 IO 和數據讀寫使用單線程模型,可以綁定 CPU,這避免了線程上下文切換帶來的開銷。
注意:Redis 6.0 對網絡請求引入了多線程模型,讀寫操作還是用單線程。
Redis 底層數據結構
Redis 有 5 種數據類型,包括:字符串、列表、集合、有序集合和字典。
Redis 底層的數據結構有 6 種,包括:動態字符串、雙向鏈表、壓縮列表(ziplist)、hash 表、跳表(skip list)和整數數組。
1. 字符串類型
底層數據結構是動態字符串。
2. 列表
如果同時滿足下面條件,就使用壓縮列表,否則使用雙向鏈表:
列表中單個元素小于 64 字節
列表中元素個數少于 512
壓縮列表在內存中是一塊兒連續的內存空間,
壓縮列表查找時間復雜度是 o(n)。
3. 集合
如果同時滿足下面條件,就使用有序整數數組,否則使用 hash 表:
集合中元素都是整數類型
集合中元素個數不超過 512 個
4. 有序集合
如果同時滿足下面 2 個條件,就使用壓縮列表,否則使用跳表:
集合中元素都小于 64 字節
集合中元素個數小于 128 個
注意:有序集合還有一個 HASH 表用于保存集合中元素的分數,做 ZSCORE 操作時,查詢的就是這個 HASH 表,所以效率很高。如果不加索引,查找 10 這個數字需要查詢 10 次,使用了二級索引,查找 10 這個數字需要 5 次,而使用一級索引,需要查詢 3 次。跳表的每一層都是一個有序鏈表,最下面一層保存了全部數據。跳表插入、刪除、查詢的時間復雜度是 o(logN)。跳表需要存儲額外的索引節點,會增加額外的空間開銷。
5. 字典
如果同時滿足下面 2 個條件,就使用壓縮列表,否則使用 hash 表:
字典中每個 entry 的 key/value 都小于 64 字節
字典中元素個數小于 512 個
Redis 緩存淘汰策略,Redis 總共有 8 種淘汰策略,如下圖:
volatile-lfu 和 allkeys-lfu 策略是 4.0 版本新增的:
lru:是按照數據的最近最少訪問原則來淘汰數據,可能存在的問題是如果大批量冷數據最近被訪問了一次,就會占用大量內存空間,如果緩存滿了,部分熱數據就會被淘汰掉。
lfu:是按照數據的最小訪問頻率訪問次數原則來淘汰數據,如果兩個數據的訪問次數相同,則把訪問時間較早的數據淘汰。
Redis 數據持久化
Redis 持久化的方式有 2 種,一種是寫后日志(AOF),一種是內存快照(RDB)。
1. AOF 日志
AOF 日志記錄了每一條收到的命令,Redis 故障宕機恢復時,可以加載 AOF 日志中的命令進行重放來進行故障恢復。
AOF 有 3 種同步策略:
Always:執行命令同步寫盤;
everysec:每秒寫一次盤;
no:操作系統控制寫盤
如果不是對丟失數據特別敏感的業務,推薦使用 everysec,對主線程的阻塞少,故障后丟失數據只有 1s。
2. RDB 快照
RDB 快照是一個內存快照,記錄了 Redis 某一時刻的全部數據。
3. 混合日志
從 Redis 4.0 開始,AOF 文件也可以保存 RDB 快照,AOF 重寫的時候 Redis 會把 AOF 文件內容清空,先記錄一份 RDB 快照,這份數據以"REDIS"開頭。
記錄 RDB 內容后,AOF 文件會接著記錄 AOF 命令。故障恢復時,先加載 AOF 文件中 RDB 快照,然后回放 AOF 文件中后面的命令。
4. 主從同步
Redis 主從同步時,主節點會先生成一份 RDB 快照發送給從節點,把快照之后的命令寫入主從同步緩存區(replication buffer),從節點把 RDB 文件加載完成后,主節點把緩存區命令發送給從節點。
5. AOF 重寫
AOF 日志是用記錄命令的方式追加的,這樣可能存在對同一個 key 的多條命令,這些命令是可以合并成 1 條的。比如對同一個 key 的多個 set 操作日志,可以合成一條。
6. 阻塞
AOF 重寫和 RDB 快照執行的過程中,Redis 都會 Fork 一個子進程來執行操作,子進程執行過程中是不是阻塞主線程的。
但是要注意 2 點:
Fork 子進程的過程中,Redis 主線程會拷貝一份內存頁表(記錄了虛擬內存和物理內存的映射關系)給子進程,這個過程是阻塞的,Redis 主線程內存越大,阻塞時間越長。
子進程和 Redis 主線程共用一塊兒物理內存,如果新的請求到來,必須使用 copy on write 的方式,拷貝要修改的數據頁到新的內存空間進行修改。
注意:如果開啟了內存大頁,每次拷貝都需要分配 2MB 的內存。
Redis 高可用
從圖我們可以看到哨兵之間、哨兵和主從節點之間、哨兵和客戶端之間都建立了連接。
如果主節點掛了,哨兵集群需要完成主從切換:判斷主節點下線--->選舉新主---->選舉哨兵leader---->執行主從切換:
1. 判斷主節點下線
當一個哨兵監控到主節點下線時,就會給其他哨兵發送確認命令,其他命令會根據自己的判斷回復"Y"或"N"。
如果有 n/2+1 以上數量的哨兵都認為主節點下線了,才會判定主節點下線。這里的n是哨兵集群的數量。
n/2+1 這個參數由 quorum 參數配置,比如有 5 個哨兵,這里一般配置成 3。也可以配置成其他值。
2. 選舉新主節點
主節點被判定下線后,哨兵集群會重新選擇新的主節點。
淘汰不穩定從節點:根據配置參數 down-after-milliseconds * 10 來淘汰。
down-after-milliseconds 表示主從節點斷開時間,10 表示次數,如果從節點跟主節點斷開時間超過 down-after-milliseconds 的次數達到了 10 次以上,從節點就被淘汰了。
slave-priority 參數:配置了從節點的優先級,選擇從節點時哨兵會優先選擇優先級高的從節點。
復制進度:Redis 有一個記錄主從增量復制的緩存區叫 repl_backlog_buffer。
主節點有一個寫偏移量 master_repl_offset,從節點也有一個偏移量 slave_repl_offset。
優先選擇 slave_repl_offset 最接近 master_repl_offset 的從節點作為新的主節點。
所以,上圖中偏移量為 114 的從節點優先被選為新的主節點。
ID 編號:優先級和參數都一樣的情況下,ID 編號小的從節點優先被選為新主節點。
3. 選舉哨兵 Leader
第一個判斷主節點下線的哨兵節點收到其他節點的回復并確定主節點下線后,就會給其他哨兵發送命令申請成為哨兵 Leader。
成為 Leader 的條件如下:
收到贊成票必須大于等 quorum 值
必須拿到半數以上的贊成票
如果集群配置了 5 個哨兵,quorum 的值設置為 3,其中一個哨兵節點掛了,很有可能會判斷到主節點下線,但是因為選舉不出哨兵 Leader 而不能切換。
如果集群有 2 個哨兵,其中一個掛了,那必定選不出哨兵 Leader。
4. 主節點切換
選出新主節點和哨兵 Leader 后,哨兵 Leader 會執行主從切換的操作。
完成后會做一些事件通知:
通知其他哨兵新主節點地址
通知所有從節點新的主節點地址,從節點收到后向新主節點請求主從同步
通知客戶端連接新主節點
5. 主從切換過程中請求處理
如果客戶端的讀請求會發送到從節點,可以正常處理。在客戶端收到新主節點地址通知前寫請求會失敗。客戶端可以采取一些應急措施應對主節點下線,比如緩存寫請求。
為了能夠及時獲取到新主節點信息,客戶端可以訂閱哨兵的主節點下線事件和新主節點變更事件。
Redis 實現分布式鎖
1. Redis 單節點的分布式鎖
一個服務部署了 2 個客戶端,獲取分布式鎖時一個成功,另一個就失敗了。
Redis 一般使用 setnx 實現分布式鎖,命令如下:
SETNX KEY_NAME VALUE
設置成功返回 1,設置失敗返回 0。使用單節點分布式鎖存在一些問題。
客戶端 1 獲取鎖后發生了故障:結果鎖就不能釋放了,其他客戶端永遠獲取不到鎖。
解決方法是用下面命令對 key 設置過期時間:
SET key value [EX seconds] [PX milliseconds] NX
客戶端 2 誤刪除了鎖:解決方法是對 key 設置 value 時加入一個客戶端表示,比如在客戶端 1 設置 key 時在 value 前拼接一個字符串 application1,刪除的時候做一下判斷。
2. Redis 紅鎖
Redis 單節點會有可靠性問題,節點故障后鎖操作就會失敗。Redis 為了應對單點故障的問題,設計了多節點的分布式鎖,也叫紅鎖。
主要思想是客戶端跟多個 Redis 實例請求加鎖,只有超過半數的實例加鎖成功,才認為成功獲取了分布式鎖。
更多精彩干貨分享
點擊下方名片關注
IT那活兒
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/129777.html
摘要:哨兵是社區版本推出的原生高可用解決方案,部署架構主要包括兩部分集群和數據集群,其中集群是由若干節點組成的分布式集群。自研推薦推薦自研的高可用解決方案,主要體現在配置中心故障探測和的處理機制上,通常需要根據企業業務的實際線上環境來定制化。 最近很多朋友向我咨詢關于高可用的方案的優缺點以及如何選擇合適的方案線上使用,剛好最近在給宜人貸,光大銀行做企業內訓的時候也詳細講過,這里我再整理發出來...
摘要:哨兵是社區版本推出的原生高可用解決方案,部署架構主要包括兩部分集群和數據集群,其中集群是由若干節點組成的分布式集群。自研推薦推薦自研的高可用解決方案,主要體現在配置中心故障探測和的處理機制上,通常需要根據企業業務的實際線上環境來定制化。 最近很多朋友向我咨詢關于高可用的方案的優缺點以及如何選擇合適的方案線上使用,剛好最近在給宜人貸,光大銀行做企業內訓的時候也詳細講過,這里我再整理發出來...
摘要:而今天主要講用得比較多的三個。支持持久化操作,可以進行及數據持久化到磁盤,從而進行數據備份或數據恢復等操作,較好的防止數據丟失的手段。單線程請求,所有命令串行執行,并發情況下不需要考慮數據一致性問題。 前言 NoSQL,泛指非關系型的數據庫。隨著互聯網不斷的發展,傳統的關系數據庫在應付新互聯網模式的網站,特別是超大規模和高并發的SNS類型的純動態網站已經顯得力不從心,暴露了很多難以克服...
摘要:而今天主要講用得比較多的三個。支持持久化操作,可以進行及數據持久化到磁盤,從而進行數據備份或數據恢復等操作,較好的防止數據丟失的手段。單線程請求,所有命令串行執行,并發情況下不需要考慮數據一致性問題。 前言 NoSQL,泛指非關系型的數據庫。隨著互聯網不斷的發展,傳統的關系數據庫在應付新互聯網模式的網站,特別是超大規模和高并發的SNS類型的純動態網站已經顯得力不從心,暴露了很多難以克服...
摘要:而今天主要講用得比較多的三個。支持持久化操作,可以進行及數據持久化到磁盤,從而進行數據備份或數據恢復等操作,較好的防止數據丟失的手段。單線程請求,所有命令串行執行,并發情況下不需要考慮數據一致性問題。 前言 NoSQL,泛指非關系型的數據庫。隨著互聯網不斷的發展,傳統的關系數據庫在應付新互聯網模式的網站,特別是超大規模和高并發的SNS類型的純動態網站已經顯得力不從心,暴露了很多難以克服...
閱讀 1346·2023-01-11 13:20
閱讀 1684·2023-01-11 13:20
閱讀 1132·2023-01-11 13:20
閱讀 1858·2023-01-11 13:20
閱讀 4100·2023-01-11 13:20
閱讀 2704·2023-01-11 13:20
閱讀 1385·2023-01-11 13:20
閱讀 3597·2023-01-11 13:20