Redis從基礎到進階(一)
提示:文章寫完後,目錄可以自動生成,如何生成可參考右邊的幫助文件
文章目錄
前言
Redis(Remote Dictionary Server)2008年,義大利的一家創業公司Merzia推出了一款基於MySQL的網站實時統計系統LLOOGG,然而沒過多久該公司的創始人SalvatoreSanfilippo(antirez)便對MySQL的效能感到失望,於是他決定親自為LLOOGG量身定做一個數據庫,並於2009年開發完成,這個資料庫就是Redis。
提示:以下是本篇文章正文內容,下面案例可供參考
一、什麼是Redis?
Redis(Remote Dictionary Server)遠端字典伺服器,是用C語言開發的一個開源的高效能鍵值對(key-value)記憶體資料庫。它提供了五種資料型別來儲存值:字串型別、雜湊型別、列表型別、集合型別、有序集合型別它是一種NoSQL資料儲存。
1.1redis應用場景
快取使用,減輕DB壓力
DB使用,用於臨時儲存資料(字典表,購買記錄)
解決分散式場景下Session分離問題(登入資訊)
任務佇列(秒殺、搶紅包等等)樂觀鎖
應用排行榜zset
簽到 bitmap
分散式鎖
冷熱資料交換
1.2命令說明
redis-server:啟動redis服務
redis-cli:進入redis命令客戶端
redis-benchmark:效能測試的工具
redis-check-aof:aof檔案進行檢查的工具
redis-check-dump:rdb檔案進行檢查的工具
redis-sentinel:啟動哨兵監控服務
1.3快取過期和淘汰策略
快取過期
長期使用,key會不斷增加,Redis作為快取使用,實體記憶體也會滿記憶體與硬碟交換(swap)虛擬記憶體,頻繁IO 效能急劇下降
在Redis中可以使用expire命令設定一個鍵的存活時間(ttl: time to live),過了這段時間,該鍵就會自動被刪除。
淘汰策略
刪除策略
Redis的資料刪除有定時刪除、惰性刪除和主動刪除三種方式。 Redis目前採用惰性刪除+主動刪除的方式。 定時刪除在設定鍵的過期時間的同時,建立一個定時器,讓定時器在鍵的過期時間來臨時,立即執行對鍵的刪除操作。需要建立定時器,而且消耗CPU,一般不推薦使用。 惰性刪除在key被訪問時如果發現它已經失效,那麼就刪除它。呼叫expireIfNeeded函式,該函式的意義是:讀取資料之前先檢查一下它有沒有失效,如果失效了就刪除它。
主動刪除
在redis.conf檔案中可以配置主動刪除策略,預設是no-enviction(不刪除)
快取淘汰策略的選擇
allkeys-lru :在不確定時一般採用策略。冷熱資料交換
volatile-lru :比allkeys-lru效能差 需儲存過期時間
allkeys-random :希望請求符合平均分佈(每個元素以相同的概率被訪問)
自己控制:volatile-ttl 快取穿透
二、Redis持久化
Redis是記憶體資料庫,宕機後資料會消失。Redis重啟後快速恢復資料,要提供持久化機制Redis持久化是為了快速的恢復資料而不是為了儲存資料Redis有兩種持久化方式:RDB和AOF(通過配置檔案redis.conf來實現)
RDB
RDB(Redis DataBase),是redis預設的儲存方式,RDB方式是通過快照(snapshotting)完成的。
2.1觸發快照的方式
- 符合自定義配置的快照規則
- 執行save或者bgsave命令
- 執行flushall命令
- 執行主從複製操作 (第一次)!
2.2RDB執行流程
2.3RDB的優缺點
優點
RDB是二進位制壓縮檔案,佔用空間小,便於傳輸(傳給slaver)主程序fork子程序,可以最大化Redis效能,主程序不能太大,Redis的資料量不能太大,複製過程中主程序阻塞
缺點
不保證資料完整性,會丟失最後一次快照以後更改的所有資料
AOF
AOF(append only file)是Redis的另一種持久化方式。Redis預設情況下是不開啟的。開啟AOF持久化後Redis 將所有對資料庫進行過寫入的命令(及其引數)(RESP)記錄到 AOF 檔案,以此達到記錄資料庫狀態的目的,這樣當Redis重啟後只要按順序回放這些命令就會恢復到原始狀態了。AOF會記錄過程,RDB只管結果
程式碼如下(示例):
2.4AOF原理
命令傳播
當一個 Redis 客戶端需要執行命令時,它通過網路連線,將協議文字傳送給 Redis 伺服器。伺服器在接到客戶端的請求之後,它會根據協議文字的內容,選擇適當的命令函式,並將各個引數從字串文字轉換為 Redis 字串物件(StringObject)。每當命令函式成功執行之後,命令引數都會被傳播到AOF 程式。
快取追加
當命令被傳播到 AOF 程式之後,程式會根據命令以及命令的引數,將命令從字串物件轉換回原來的協議文字。協議文字生成之後,它會被追加到redis.h/redisServer結構的aof_buf末尾。redisServer結構維持著 Redis 伺服器的狀態,aof_buf域則儲存著所有等待寫入到 AOF 檔案的協議文字(RESP)。
檔案寫入和儲存
每當伺服器常規任務函式被執行、或者事件處理器被執行時, aof.c/flushAppendOnlyFile 函式都會被呼叫,這個函式執行以下兩個工作:WRITE:根據條件,將 aof_buf 中的快取寫入到 AOF 檔案。SAVE:根據條件,呼叫 fsync 或 fdatasync 函式,將 AOF 檔案儲存到磁碟中。
2.5 AOF重寫、混合持久化
AOF記錄資料的變化過程,越來越大,需要重寫“瘦身”
Redis可以在 AOF體積變得過大時,自動地在後臺(Fork子程序)對 AOF進行重寫。重寫後的新 AOF檔案包含了恢復當前資料集所需的最小命令集合。所謂的“重寫”其實是一個有歧義的詞語,實際上,AOF 重寫並不需要對原有的 AOF 檔案進行任何寫入和讀取,它針對的是資料庫中鍵的當前值。
重寫過程分析
Redis 在建立新 AOF 檔案的過程中,會繼續將命令追加到現有的 AOF 檔案裡面,即使重寫過程中發生停機,現有的 AOF 檔案也不會丟失。而一旦新 AOF 檔案建立完畢,Redis 就會從舊 AOF 檔案切換到新 AOF 檔案,並開始對新 AOF 檔案進行追加操作。
當子程序在執行 AOF 重寫時,主程序需要執行以下三個工作:
處理命令請求。將寫命令追加到現有的 AOF 檔案中。將寫命令追加到 AOF 重寫快取中。這樣一來可以保證:在這裡插入圖片描述
現有的 AOF 功能會繼續執行,即使在 AOF 重寫期間發生停機,也不會有任何資料丟失。所有對資料庫進行修改的命令都會被記錄到 AOF 重寫快取中。當子程序完成 AOF 重寫之後,它會向父程序傳送一個完成訊號,父程序在接到完成訊號之後,會呼叫一個訊號處理函式,並完成以下工作:
將 AOF 重寫快取中的內容全部寫入到新 AOF 檔案中。對新的 AOF 檔案進行改名,覆蓋原有的 AOF 檔案。
Redis資料庫裡的+AOF重寫過程中的命令------->新的AOF檔案---->覆蓋老的
當步驟 1 執行完畢之後,現有 AOF 檔案、新 AOF 檔案和資料庫三者的狀態就完全一致了。
當步驟 2 執行完畢之後,程式就完成了新舊兩個 AOF 檔案的交替。這個訊號處理函式執行完畢之後,主程序就可以繼續像往常一樣接受命令請求了。在整個 AOF 後臺重寫過程中,只有最後的寫入快取和改名操作會造成主程序阻塞,在其他時候, AOF 後臺重寫都不會對主程序造成阻塞,這將 AOF 重寫對效能造成的影響降到了最低。以上就是 AOF 後臺重寫,也即是 BGREWRITEAOF 命令(AOF重寫)的工作原理。
混合持久化
RDB和AOF各有優缺點,Redis 4.0 開始支援 rdb 和 aof 的混合持久化。如果把混合持久化開啟,aofrewrite 的時候就直接把 rdb 的內容寫到 aof 檔案開頭。RDB的頭+AOF的身體---->appendonly.aof
開啟混合持久化
aof-use-rdb-preamble yes
AOF檔案的載入與資料還原
因為AOF檔案裡面包含了重建資料庫狀態所需的所有寫命令,所以伺服器只要讀入並重新執行一遍AOF檔案裡面儲存的寫命令,就可以還原伺服器關閉之前的資料庫狀態Redis讀取AOF檔案並還原資料庫狀態的詳細步驟如下:1、建立一個不帶網路連線的偽客戶端(fake client):因為Redis的命令只能在客戶端上下文中執行,而載入AOF檔案時所使用的命令直接來源於AOF檔案而不是網路連線,所以伺服器使用了一個沒有網路連線的偽客戶端來執行AOF檔案儲存的寫命令,偽客戶端執行命令的效果和帶網路連線的客戶端執行命令的效果完全一樣2、從AOF檔案中分析並讀取出一條寫命令3、使用偽客戶端執行被讀出的寫命令4、一直執行步驟2和步驟3,直到AOF檔案中的所有寫命令都被處理完畢為止當完成以上步驟之後,AOF檔案所儲存的資料庫狀態就會被完整地還原出來,整個過程如下圖所示: