學習記錄之Redis
Redis數據類型

緩存使用原則
什么時候,什么樣的數據能夠保存在Redis中?
1.數據量不能太大
2.使用越頻繁,Redis保存這個數據越值得
3.保存在Redis中的數據一般不會是數據庫中頻繁修改的
Redis將數據保存在內存中,?內存的容量是有限的
如果Redis服務器的內存已經全滿,現(xiàn)在還需要向Redis中保存新的數據,如何操作,就是緩存淘汰策略
noeviction:返回錯誤**(默認)**
如果我們不想讓它發(fā)生錯誤,就可以設置它將滿足某些條件的信息刪除后,再將新的信息保存
allkeys-random:所有數據中隨機刪除數據
volatile-random:有過期時間的數據中隨機刪除數據
volatile-ttl:刪除剩余有效時間最少的數據
allkeys-lru:所有數據中刪除上次使用時間最久的數據
volatile-lru:有過期時間的數據中刪除上次使用時間最久的數據
allkeys-lfu:所有數據中刪除使用頻率最少的
volatile-lfu:有過期時間的數據中刪除使用頻率最少的
緩存穿透
正常業(yè)務下,一個請求查詢到數據后,我們可以將這個數據保存在Redis
之后的請求都可以直接從Redis查詢,就不需要再連接數據庫了
如果一個請求查詢的數據,數據庫中沒有會發(fā)生什么事情?
它會先查詢Redis,Redis沒有會查詢數據庫,數據庫也沒有這就是緩存穿透
因為數據庫中沒有數據,所以Redis也無法保存數據,如果這個請求反復出現(xiàn),就會反復連接數據庫,嚴重的導致數據庫性能降低甚至宕機
解決方案:業(yè)界主流解決方案:布隆過濾器
布隆過濾器的使用步驟
1.針對現(xiàn)有所有數據,生成布隆過濾器
2.在業(yè)務邏輯層,判斷Redis之前先檢查這個id是否在布隆過濾器中
3.如果布隆過濾器判斷這個id不存在,直接返回
4.如果布隆過濾器判斷id存在,再進行后面業(yè)務執(zhí)行
緩存擊穿
一個計劃在Redis保存的數據,業(yè)務查詢,查詢到的數據Redis中沒有,但是數據庫中有
這種情況要從數據庫中查詢后再保存到Redis,這就是緩存擊穿
但是這個情況也不是異常情況,因為我們大多數數據都需要設置過期時間,而過期時間到時,這些數據一定會從數據庫中再次同步

緩存雪崩
上面講到擊穿現(xiàn)象
同一時間發(fā)生少量擊穿是正常的
但是如果出現(xiàn)同一時間大量擊穿現(xiàn)象就會如下圖

上圖同時大量緩存失效,導致請求都壓在mysql上,mysql承擔不了,非??赡軐е庐惓?/p>
要想避免這種情況,就需要避免大量緩存同時失效
大量緩存同時失效的原因:通常是同時加載的數據設置了相同的有效期導致的
那么我們需要在設置有效期時添加一個隨機數,大量數據就不會同時失效了,
Redis 持久化
Redis將信息保存在內存
內存的特征就是一旦斷電,所有信息都丟失,對于Redis來講,所有數據丟失,就需要從數據庫從新查詢所有數據,這個是慢的
更有可能,Redis本身是有新數據的,還沒有和數據庫同步就斷電了
所以Redis支持了持久化方案,在當前服務器將Redis中的數據保存在本地硬盤上
Redis持久化策略有兩種
RDB:(Redis Database Backup)
RDB本質上就是數據庫快照(就是當前Redis中所有數據轉換成二進制的對象,保存在硬盤上)
默認情況下,會生成一個dump.rdb的文件
當Redis斷電或宕機,需要恢復數據時,可以恢復成dump.rdb生成時的所有內容
我們可以在Redis的配置文件中添加如下配置信息
60表示秒數,既1分鐘
5表示key被修改的次數
配置效果:1分鐘內如果有5個key以上被修改,就啟動rdb數據庫快照程序
優(yōu)點:
因為是整體Redis數據的二進制格式,數據恢復是整體恢復的
缺點:
生成的rdb文件是一個硬盤上的文件,讀寫效率是較低的
如果突然斷電,只能恢復最后一次生成的rdb中的數據
AOF(Append Only File):
AOF策略是將Redis運行過的所有命令(日志)備份下來
這樣即使Redis斷電,我們也可以根據運行過的日志,恢復為斷電前的樣子
我們可以在Redis的配置文件中添加如下配置信息
經過這個設置,就能保存運行過的指令的日志了,理論上任何運行過的指令都可以恢復
但是實際情況下,Redis非常繁忙時,我們會將日志命令緩存之后,整體發(fā)送給備份,減少io次數以提高備份的性能和對Redis性能的影響
實際開發(fā)中,配置一般會采用每秒將日志文件發(fā)送一次的策略,斷電最多丟失1秒數據
優(yōu)點:
?相對RDB來講,信息丟失的較少
缺點:
?因為保存的是運行的日志,所以占用空間較大
實際開發(fā)中RDB和AOF是可以同時開啟的
也可以單個開啟
Redis的AOF為減少日志文件的大小,支持AOF rewrite,簡單來說就是將日志中無效的語句刪除,能夠減少占用的空間.
Redis存儲原理
Redis將內存劃分為16384個區(qū)域(類似hash槽)
將數據的key使用CRC16算法計算出一個值,取余16384
得到的結果是0~16383
將這個key保存在計算結果對應的槽位
再次查詢這個key時,直接到這個槽位查找,效率很高(下面的計算值只用來演示,不少真的計算出來的)

實際上這就是"散列表",提高查詢的效率
Redis集群
Redis最小狀態(tài)是一臺服務器,這個服務器的運行狀態(tài),直接決定Redis是否可用
如果它離線了,整個項目就會無Redis可用,系統(tǒng)會面臨崩潰,為了防止這種情況的發(fā)生,我們可以準備一臺備用機
主從復制

也就是主機(master)工作時,安排一臺備用機(slave)實時同步數據,萬一主機宕機,我們可以切換到備機運行
缺點,這樣的方案,slave節(jié)點沒有任何實質作用,只要master不宕機它就和沒有一樣,沒有體現(xiàn)價值
讀寫分離

這樣slave在master正常工作時也能分擔Master的工作了
但是如果master宕機,實際上主備機的切換,實際上還是需要人工介入的,這還是需要時間的
那么如果想實現(xiàn)故障時自動切換,一定是有配置好的固定策略的
哨兵模式:故障自動切換

哨兵節(jié)點每隔固定時間向所有節(jié)點發(fā)送請求
如果正常響應認為該節(jié)點正常
如果沒有響應,認為該節(jié)點出現(xiàn)問題,哨兵能自動切換主備機
如果主機master下線,自動切換到備機運行
但是這樣的模式存在問題

但是如果哨兵判斷節(jié)點狀態(tài)時發(fā)生了誤判,那么就會錯誤將master下線,降低整體運行性能
哨兵集群

我們可以將哨兵節(jié)點做成集群,由多個哨兵投票決定是否下線某一個節(jié)點
哨兵集群中,每個節(jié)點都會定時向master和slave發(fā)送ping請求
如果ping請求有2個(集群的半數節(jié)點)以上的哨兵節(jié)點沒有收到正常響應,會認為該節(jié)點下線
分片集群
當業(yè)務不斷擴展,并發(fā)不斷增高時
只有一個節(jié)點支持寫操作無法滿足整體性能要求時,系統(tǒng)性能就會到達瓶頸
這時我們就要部署多個支持寫操作的節(jié)點,進行分片,來提高程序整體性能
分片就是每個節(jié)點負責不同的區(qū)域
Redis0~16383號槽,
例如MasterA復制0~5000
MasterB復制5001~10000
MasterC復制10001~16383
一個key根據CRC16算法只能得到固定的結果,一定在指定的服務器上找到數據

為了節(jié)省哨兵服務器的成本,有些公司在Redis集群中直接添加哨兵功能,既master/slave節(jié)點完成數據讀寫任務的同時也都互相檢測它們的健康狀態(tài)