本文目錄
- 一、 Redis資料結構
- (1)String 字串
- (2)Hash 哈希
- (3)List鏈表
- (4)Set集合
- (5)Zset有序集合
- 二、 Redis單執行緒模型為啥這么快?
- (一)基于記憶體操作
- (二)C語言實作
- (三)簡單的資料結構
- (四)多路I/O復用模型
- (五)單執行緒模型
- 三、持久化之RDB與AOF
- (一)RDB
- (二)AOF
- (三)RDB和AOF對比
- 四、 主從復制與故障轉移
- (一)資料復制的意義
- (二)Redis注冊復制原理
- (三)故障轉移
- 五、 高可用與 Sentinel 哨兵
- (一)sentinel的功能
- 六、分布式快取與 Redis Cluster
- 七、快取擊穿(快取穿透)、快取雪崩
- (一) 快取擊穿(快取穿透)
- (二)快取雪崩
- 八、Redis熱點Key
- 九、布隆過濾
- 十、快取資料一致性
一、 Redis資料結構
(1)String 字串
使用場景:
1.快取: 經典使用場景,把常用資訊,字串,圖片或者視頻等資訊放到redis中,redis作為快取層,mysql做持久化層,降低mysql的讀寫壓力,
2.計數器:redis是單執行緒模型,一個命令執行完才會執行下一個,同時資料可以一步落地到其他的資料源,
3.session:常見方案spring session + redis實作session共享,
(2)Hash 哈希
使用場景:
1.快取: 能直觀,相比string更節省空間,的維護快取資訊,如用戶資訊,視頻資訊等,
(3)List鏈表
使用場景:
1.timeline:例如微博的時間軸,有人發布微博,用lpush加入時間軸,展示新的串列資訊
(4)Set集合
使用場景:
1.標簽(tag),給用戶添加標簽,或者用戶給訊息添加標簽,這樣有同一標簽或者類似標簽的可以給推薦關注的事或者關注的人,
2.點贊,或點踩,收藏等,可以放到set中實作
(5)Zset有序集合
使用場景:
1.排行榜:有序集合經典使用場景,例如小說視頻等網站需要對用戶上傳的小說視頻做排行榜,榜單可以按照用戶關注數,更新時間,字數等打分,做排行,
二、 Redis單執行緒模型為啥這么快?
(一)基于記憶體操作
Redis將所有需要存盤的資料都存放在記憶體中,基于記憶體的隨機訪問速度是磁盤的10萬倍左右,即使是SSD也遙不可及,這是Redis操作快速的重要物理基礎,
(二)C語言實作
相同邏輯下的C語言程式,執行效率要比其他語言的高很多,C語言與當前主流的作業系統之間有著獨特的關系,拋開開發難度來看,執行速度還是蠻快的,
(三)簡單的資料結構
記憶體資料庫的另一個優點是,基于記憶體的資料結構要比基于硬碟的資料結構更加簡單,對資料的操作也更加簡單,因此Redis可以做很多事情,內部復雜性很小,Redis占用的記憶體空間也是比較少,
(四)多路I/O復用模型
多路 指的的是多個網路連接,復用 指的是重復使用一個執行緒,I/O多路復用技術可以使單個執行緒處理多個網路連接請求,
(五)單執行緒模型
避免了多執行緒的啟動、銷毀、背景關系切換、加鎖、解鎖等消耗資源的操作,單執行緒簡單,不僅能避免背景關系切換這種非常消耗資源的操作,而且可以避免死鎖的情況,大大提升CPU的利用率,如果是多核服務器,可以通過啟動多個Redis實體來利用多個CPU,
三、持久化之RDB與AOF
Redis 是一種基于記憶體的資料庫,一旦斷電、重啟,Redis 中的資料將不復存在,Redis 提供了 RDB 和 AOF 兩個持久化的方式,當 Redis 實體重啟時,可以使用已持久化的資料(檔案)來還原記憶體資料集,
(一)RDB
這種持久化方式是將當前Redis記憶體中的資料生成 快照(Snapshot) 檔案保存到硬碟,簡單粗暴,RDB也是Redis默認開啟的持久化方式,
1、 觸發持久化
save
在之前已經廢棄的 save 命令來實作RDB持久化資料,save 命令持久化時會一直阻塞,直到持久化完成,資料量越大,持久化程序帶來的阻塞時間就越長,
bgsave
現在可以使用 bgsave 命令來代替 save,bg就是background,使用 bgsave 方式RDB持久化時,Redis作業行程會 fork 一個子行程,該子行程專門來負責耗時的RDB持久化,而作業行程會繼續作業,阻塞時間只發生在短暫的 fork 階段,
除了主動觸發命令外,Redis還是提供了自動觸發RDB持久化命令 bgsave ,該命令表示在seconds秒內,Redis記憶體資料修改的次數達到changes次時,將觸發RDB持久化,比如 bgsave 7200 10 表示在2個小時內,資料被更改10次時將自動觸發RDB持久化,
(注意changes計數并不包含查詢陳述句,當然被操作的key一定存在,否則也不會進行計數)
2、 資料快照存盤
首先,作業目錄默認為當前Redis目錄,那么持久化的RDB資料快照將存盤在該目錄,可通過 dir ./ 引數進行修改,生成的資料存盤快照名稱默認為 dump.rdb ,可通過 dbfilename dump.rdb 引數進行修改,RDB持久化先生存一個臨時快照,待資料持久化完成,這個臨時快斬訓替換原快照,以防持久化程序出現問題,
RDB存盤快照默認是使用LZF演算法壓縮功能,壓縮后的檔案體積將大大減少,壓縮檔案但并不是十全十美,RDB快照壓縮時也會消耗CPU,資料量越大,消耗CPU資源就越多,但官網還是極力推薦我們開始此功能,
RDB持久化時可能出現權限問題、存盤空間不夠用等問題,Redis 默認開啟stop-writes-on-bgsave-error yes 引數,意味著出現 error時,Redis將停止向快照檔案寫入資料,
在Redis保存/恢復資料時,并不是一股腦進行保存/恢復,默認會對RDB快照檔案進行檢查,性能會受到影響(大約10%),因此可以禁用它以獲得最大的性能,(推薦開啟)
(二)AOF
這種持久化方式是通過保存寫命令來記錄操作日志,在資料恢復時,重新執行已記錄的寫命令,來達到資料恢復,
1、 AOF原理
默認情況下,AOF是關閉的,可以通過修改 appendonly no 為 appendonly yes 來開啟 AOF 持久化,記憶體的Output的帶寬遠大于磁盤Input的帶寬,如果記憶體瞬時將大量的資料寫入磁盤,必然發生IO堵塞,對于單執行緒作業的Redis也將會在性能上大打折扣,所以所有的寫命令并不會直接寫入AOF檔案,而是先將寫命令存盤至AOF Buffer緩沖區,最后在同步至AOF檔案,
生成的AOF檔案名,默認為 appendonly.aof ,可以修改 appendfilename “appendonly.aof” 引數來更改生成的AOF檔案名,
從緩沖區同步至磁盤,Redis提供了三種同步方式:
always: 寫命令被追加到AOF快取后,呼叫系統fsync函式將緩沖區的資料同步至磁盤,最后回傳
everysec: 寫命令被追加到AOF快取后,呼叫系統write函式,在write函式執行完成,然后回傳,會觸發系統將對緩沖區的資料進行同步至磁盤
no: 寫命令被追加到AOF快取后,呼叫系統write函式,然后回傳,后續的同步由系統負責
其中 everysec 不僅是默認的方式,也是推薦的方式,
2、 AOF重寫機制
AOF持久化檔案存盤的是Redis寫命令,這比僅僅是資料的存盤檔案要大了很多,在AOF重寫機制中,首先遍歷資料庫,如果資料庫為空庫,則跳過該庫,對于非空的資料庫,則遍歷所有的key,如果key過期則跳過該key,如果key有過期時間則設定key的過期時間,
AOF的重寫機制并不是隨機觸發的,默認是當前寫入AOF檔案大小較上次重寫后檔案大小增長了 100% 時就觸發重寫機制,比如上次重寫后的檔案大小是1G,經過一段時間,AOF檔案體積增長了 1G ,那么增長率就是 100% ,就會觸發AOF重寫,可以通過設定 auto-aof-rewrite-percentage 100 來調節檔案增長率的觸發閾值,
如果AOF的檔案較少,不足以影響太大性能,所以沒必要重寫AOF檔案,可以通過 auto-aof-rewrite-min-size 64mb 來設定AOF檔案重寫的最小閾值,
aof-load-truncated yes 引數表示,在Redis恢復資料時,最后一條命令可能不完整,開啟則表示忽略最后一條不完整的命令,
(三)RDB和AOF對比
RDB開始壓縮后,生成一個體量更小、更緊湊的二進制檔案,占有空間小,RDB不僅有著較快的資料恢復能力,而且可以直接復制RDB檔案至其他Redis實體進行回復資料,有著良好的容災體驗,RDB適用于定時復制、全量復制、快速恢復的場景,由于RDB檔案生成時間長,資料有存盤延遲,不適用于近實時持久化的場景,
AOF以追加命令的方式,持續的、近實時的寫入檔案(秒級別),而且,在一定程度時,AOF不斷的重寫持久化檔案,不斷的優化,特別是在資料完整性上要比RDB好很多,例如,使用默認的資料同步策略,Redis在發生服務器斷電等重大事件時,可能只丟失一秒鐘的寫入時間,或者在Redis行程本身發生錯誤但作業系統仍在正常運行時丟失一次寫入時間,所以AOF比較適合對資料實時性和資料完整性要求比較高的場景,AOF相較于RDB,缺點是檔案相對較大,而且恢復資料時因為要執行全部的寫命令,所以資料恢復比較慢,特別在是在被依賴的應用系統高負載的情況下,較長時間的資料恢復,對后端系統是不可容忍的,
但AOF和RDB持久性可以同時啟用,不會出現問題,如果在啟動時啟用了AOF,redis將加載AOF,即具有更好的持久性保證的檔案,而且在較新的版本還支持混合模式,
RDB-AOF混合持久化
Redis從 4.0 開始支持RDB-AOF混合持久化,默認是關閉狀態,可以通過 aof-use-rdb-preamble yes 開啟,AOF檔案在重寫之后,將生成一份記錄已有資料的RDB快照檔案,再生成一份記錄最近寫命令的AOF檔案,作為對RDB快照的補充,這樣的混合持久化模式,將兼具RDB和AOF的雙優特性,
四、 主從復制與故障轉移
(一)資料復制的意義
1、讀寫分離,降低單節點的讀寫壓力;
2、容災轉移,單機出現問題,從節點接替,
(二)Redis注冊復制原理
首先,通過上述配置主從復制,從節點保存主節點的資訊,然后建立 socket 連接,Redis的ping命令是用于客戶端檢測服務端是否正常運作或訊息延時的一種命令,是一種心跳機制,在這里從節點就是客戶端,主節點就是服務端,從節點發送ping命令至主節點,如果主節點正常運作則回傳pong,這樣才能表示雙方網路通達,緊接著,如果主節點開啟 requirepass foobared 引數(foobared 可以認為是安全校驗密碼),主節點會對從節點進行權限校驗,密碼正確后,才進行資料同步,最后不斷的、陸陸續續的、持續復制后面的資料,實作這一持續復制資料的實作方式就是復制其操作命令,
(三)故障轉移
對于單個節點而言,有可能出現故障(fail),為了保證該服務的可用性,需要使用其他冗余或備用節點來接替該節點作業,這種拯救方式就是 故障轉移(Failover) ,
比如一個 一主兩從 的高可用方案,主節點作業,從節點作備用:
如果主節點(master節點)出現故障,那么服務不可用,從節點(slave節點)也無法從master節點持續復制資料,如何實作故障轉移呢?下面是基于客戶端的實作,
1、客戶端使用心跳機制,定時檢測 master、slave節點活性,比如使用ping命令;
2、如果master節點在一定時間內無回復,則認為master節點此時不可用;
3、從slave節點中隨機選擇或選擇一個ping-pong網路較好的一個節點晉升為master,比如6380節點;
4、6380節點和6381節點先與6379斷開復制關系 slaveof no one;
5、然后以6380為master節點,6381為salve節點建立復制關系;
建立新的主從復制
6、通過心跳檢測6379節點故障恢復后,作為salve節點與master節點建立主從復制關系;
螢屏快照 2019-02-16 下午4.10.30.png
7、故障轉移完成,(其實到了第3步選取6380為主節點后,服務就可用了)
客戶端為了高可用,也可以做成多節點,在Redis的master節點出現故障時,客戶端多節點通過選舉方式來產生新的master節點,從Redis 2.8 版本開始,新加入了 Redis Sentinel 來實作高可用,
五、 高可用與 Sentinel 哨兵
Redis-Sentinel是Redis官方推薦的高可用性(HA)解決方案,當用Redis做Master-slave的高可用方案時,假如master宕機了,Redis本身(包括它的很多客戶端)都沒有實作自動進行主備切換,而Redis-sentinel本身也是一個獨立運行的行程,它能監控多個master-slave集群,發現master宕機后能進行自動切換,
(一)sentinel的功能
1.監控
Sentinel會不斷地檢查你的主服務器和從服務器是否運作正常,
2.提醒
當被監控的某個Redis服務器出現問題時,Sentinel可以通過API向管理員或者其他應用程式發送通知,
3.自動故障遷移
當一個主服務器不能正常作業時,Sentinel會開始一次自動故障遷移操作,它會將失效主服務器的其中一個從服務器升級為新的主服務器,并讓失效主服務器的其他從服務器改為復制新的主服務器;當客戶端試圖連接失效的主服務器時,集群也會向客戶端回傳新主服務器的地址,使得集群可以使用新主服務器代替失效服務器,
六、分布式快取與 Redis Cluster
redis最開始使用主從模式做集群,若master宕機需要手動配置slave轉為master;后來為了高可用提出來哨兵模式,該模式下有一個哨兵監視master和slave,若master宕機可自動將slave轉為master,但它也有一個問題,就是不能動態擴充;所以在3.x提出cluster集群模式,
Redis-Cluster采用無中心結構,每個節點保存資料和整個集群狀態,每個節點都和其他所有節點連接,
七、快取擊穿(快取穿透)、快取雪崩
(一) 快取擊穿(快取穿透)
快取(Cache) 是分布式、高并發的場景下,為了保護后端資料庫,降低資料庫的壓力,引入的一種基于記憶體的資料訪問機制,能加快資料的讀取與寫入,進而提高系統負載能力,
快取擊穿(快取穿透) 是訪問不存在快取中的資料,進而直接訪問資料庫,
快取擊穿 和 快取穿透 更為詳細的分類:

在快取穿透這種情形下,如果快取和資料庫都沒有需要被訪問的資料,那么訪問快取時沒有資料則直接回傳空,避免重復訪問資料庫,造成不必要的后端資料庫壓力,
解決方案
1.快取空值: 如果第一次訪問一個不存在的資料,那么將此key與value為空值的資料快取起來,下次再有對應的key訪問時,快取直接回傳空值,通常要設定key的過期時間,再次訪問時更新過期時間;
2.布隆過濾: 類似散列集合(hash set),判斷key是否在這個集合中,實作機制在于位元位,一個key對應一個位元位,并且存盤一個標識,如果key有對應的位元位,并且標識位表示存在,則表示有對應的資料,比如使用Redis 的 Bitmap實作,
(二)快取雪崩
大量的快取擊穿意味著大量的請求懟在資料庫上,輕者造成資料庫回應巨慢,嚴重者造成資料庫宕機,比如快取內的資料集體定時重繪、服務器重啟等,
解決方案
1、降低快取重繪頻率;
2、部分快取重繪,重繪資料時按照一定規則分組重繪;
3、設定key永遠不過期,如果需要重繪資料,則定時重繪;
4、分片快取,在分布式快取下,將需要快取的資料 散列 分布到多個節點,盡量將熱點資料均勻分布到多節點,
八、Redis熱點Key
在一定時間內,被頻繁訪問的key稱為 熱點key ,比如突發性新聞,微博上常見的熱搜新聞,引起千千萬萬人短時間內瀏覽;在線商城大促活動,消費者比較關注的商品突然降價,引起成千上萬消費者點擊、購買,熱點key會導致流量過于集中,快取服務器的壓力驟然上升,如果超出物理機器的承載能力,則快取不可用,進而可能誘發快取擊穿、快取雪崩的問題,
解決方案
1、 讀寫分離
通過將資料的寫入與讀取分散去各個節點,通過資料復制到達各個節點資料一致性的目的,在寫少的情形下,master節點寫入資料,在讀取請求壓力大的情形下,配置多個slave節點,資料橫向同步(拓撲結構),結合Redis Sentinel (或其他高可用技術)實作快取節點的高可用,
2、 阿里云云資料庫 Redis 版解決方案
在熱點 Key 的處理上主要分為寫入跟讀取兩種形式,在資料寫入程序當 SLB 收到資料 key1 并將其通過某一個 Proxy 寫入一個 Redis,完成資料的寫入,假若經過后端熱點模塊計算發現 key1 成為熱點 key 后, Proxy 會將該熱點進行快取,當下次客戶端再進行訪問 key1 時,可以不經 Redis,最后由于 Proxy 是可以水平擴充的,因此可以任意增強熱點資料的訪問能力,
3、 熱點key不過期
如果key存在,那么不要設定key過期時間,如果key對應的資料不可用(比如洗掉了),那么從快取中洗掉key,從請求來說,如果在快取找到對應的key,表明該key及其value就是用戶需要的資料,如果快取中不存在對應的key,表明無對應的資料,回傳空值,比如微博發來爆料某明星文章,短時間內訪問量直接上升,如果key不過期,那么請求永遠命中快取,只有當文章被洗掉的時候,才從快取中洗掉對應的key,如果此時還有請求訪問,在快取中查無資料時,直接回傳空值,表明文章被洗掉,當然也可以更新key對應的value值,回傳想要表達的value,
九、布隆過濾
布隆過濾器是一個神奇的資料結構,可以用來判斷一個元素是否在一個集合中,很常用的一個功能是用來去重,布隆過濾器本質是一個位陣列,位陣列就是陣列的每個元素都只占用 1 bit ,每個元素只能是 0 或者 1,
布隆過濾器除了一個位陣列,還有 K 個哈希函式,當一個元素加入布隆過濾器中的時候,會進行如下操作:
1、使用 K 個哈希函式對元素值進行 K 次計算,得到 K 個哈希值,
2、根據得到的哈希值,在位陣列中把對應下標的值置為 1,
3、當要判斷一個值是否在布隆過濾器中,對元素再次進行哈希計算,得到值之后判斷位陣列中的每個元素是否都為 1,如果值都為 1,那么說明這個值在布隆過濾器中,如果存在一個值不為 1,說明該元素不在布隆過濾器中,
- 布隆過濾器說某個元素在,可能會被誤判,
- 布隆過濾器說某個元素不在,那么一定不在,
十、快取資料一致性
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/247172.html
標籤:其他
上一篇:thinkPHP6報錯:Failed to listen on 0.0.0.0:8000 (reason: ????“
