文章目錄:
1.什么是Redis?
2.為什么要用 Redis / 為什么要用快取?
3.Redis為什么這么快?
4.Redis都有哪些資料型別?
5.什么是Redis持久化?Redis 的持久化有哪些實作方式?
6.什么是Redis事務?
7.談談你對Redis集群方案——哨兵模式 的理解
8.Redis主從復制的原理是什么?
9.Redis如何實作分布式鎖?
10.Redis中的快取穿透、快取擊穿、快取雪崩是什么?
1.什么是Redis?
Redis(Remote Dictionary Server) 是一個使用 C 語言撰寫的,開源的(BSD許可)高性能非關系型(NoSQL)的鍵值對資料庫,
Redis 可以存盤鍵和五種不同型別的值之間的映射,鍵的型別只能為字串,值支持五種資料型別:字串、串列、散串列、集合、有序集合,
與傳統資料庫不同的是 Redis 的資料是存在記憶體中的,所以讀寫速度非常快,因此 redis 被廣泛應用于快取方向,每秒可以處理超過 10萬次讀寫操作,是已知性能最快的Key-Value DB,另外,Redis 也經常用來做分布式鎖,除此之外,Redis 支持事務 、持久化、LUA腳本、LRU驅動事件、多種集群方案,
2.為什么要用 Redis / 為什么要用快取?
主要從“高性能”和“高并發”這兩點來看待這個問題,
高性能
假如用戶第一次訪問資料庫中的某些資料,這個程序會比較慢,因為是從硬碟上讀取的,再將該用戶訪問的資料存在快取中,這樣下一次再訪問這些資料的時候就可以直接從快取中獲取了,操作快取就是直接操作記憶體,所以速度相當快,如果資料庫中的對應資料改變的之后,同步改變快取中相應的資料即可!

高并發
直接操作快取能夠承受的請求是遠遠大于直接訪問資料庫的,所以我們可以考慮把資料庫中的部分資料轉移到快取中去,這樣用戶的一部分請求會直接到快取這里而不用經過資料庫,

3.Redis為什么這么快?
- 完全基于記憶體,絕大部分請求是純粹的記憶體操作,非常快速,資料存在記憶體中,類似于 HashMap,HashMap 的優勢就是查找和操作的時間復雜度都是O(1);
- 資料結構簡單,對資料操作也簡單,Redis 中的資料結構是專門進行設計的;
- 采用單執行緒,避免了不必要的背景關系切換和競爭,也不存在多行程或者多執行緒導致的切換而消耗 CPU,不用去考慮各種鎖的問題,不存在加鎖釋放鎖操作,沒有因為可能出現死鎖而導致的性能消耗;
- 使用 I/O 多路復用模型,非阻塞 IO;
4.Redis都有哪些資料型別?
Redis主要有5種資料型別,包括String,List,Hash,Set,ZSet,
| 資料型別 | 可以存盤的值 | 操作 | 應用場景 |
| String | 字串、整數或者浮點數 | 對整個字串或者字串的其中一部分執行操作對整數和浮點數執行自增或者自減操作 | 做簡單的鍵值對快取 |
| List | 串列 | 從兩端壓入或者彈出元素對單個或者多個元素進行修剪,只保留一個范圍內的元素 | 存盤一些串列型的資料結構,類似粉絲串列、文章的評論串列之類的資料 |
| Hash | 包含鍵值對的無序散串列 | 添加、獲取、移除單個鍵值對獲取所有鍵值對 檢查某個鍵是否存在 | 結構化的資料,比如一個物件 |
| Set | 無序集合 | 添加、獲取、移除單個元素檢查一個元素是否存在于集合中 計算交集、并集、差集從集合里面隨機獲取元素 | 交集、并集、差集的操作,比如交集,可以把兩個人的粉絲串列整一個交集 |
| ZSet | 有序集合 | 添加、獲取、洗掉元素根據分值范圍或者成員來獲取元素 計算一個鍵的排名 | 去重但可以排序,如獲取排名前幾名的用戶 |
5.什么是Redis持久化?Redis 的持久化有哪些實作方式?
持久化就是把記憶體的資料寫到磁盤中去,防止服務宕機了記憶體資料丟失,
Redis 提供兩種持久化機制 RDB(默認) 和 AOF 機制:
RDB持久化:是Redis DataBase縮寫,快照
RDB是Redis默認的持久化方式,在指定的時間間隔內將記憶體中的資料集快照寫入磁盤, 也就是行話講的Snapshot快照,它恢復時是將快照檔案直接讀到記憶體里,對應產生的資料檔案為dump.rdb,通過組態檔中的save引數來定義快照的周期,
如何觸發RDB快照;保持策略,
組態檔中默認的快照配置,這三行save代碼的意思是:
在3600秒(一個小時)內,如果有1個資料發生改變,則進行持久化,
在30秒內,如果有10個資料發生改變,則進行持久化,(原先是 save 300 100),我為了后面測驗RDB,這里進行了修改,
在60秒內,如果有10000個資料發生改變,則進行持久化,
作業流程
redis根據配置嘗試去生成rdb快照檔案
redis主行程fork一個子行程出來
子行程嘗試將記憶體中的資料dump到臨時的rdb快照檔案中
完成rdb快照檔案的生成之后,覆寫舊的快照檔案
優點
只有一個檔案 dump.rdb,方便持久化,容災性好,
性能最大化,fork 子行程來完成寫操作,讓主行程繼續處理命令,保證了 redis 的高性能
資料集大時,比 AOF 的啟動效率更高,
缺點
資料安全性低,RDB 是間隔一段時間進行持久化,如果持久化之間 redis 發生故障,會發生資料丟失,
AOF持久化:Append Only File縮寫
將Redis執行的每條寫命令記錄到單獨的aof日志檔案中,當重啟Redis服務時,會從持久化的日志檔案中恢復資料,
當兩種方式同時開啟時,資料恢復時,Redis會優先選擇AOF恢復,
配置
# 表示是否開啟AOF持久化(默認no,關閉) appendonly yes作業流程
所有的寫入命令會追加到AOF緩沖區中,
AOF緩沖區根據對應的策略向硬碟做同步操作,
隨著AOF檔案越來越大,需要定期對AOF檔案進行重寫,達到壓縮的目的,
當Redis服務器重啟時,可以加載AOF檔案進行資料恢復,
優點
資料安全,可以配置每進行一次命令操作就記錄到 aof 檔案中一次,
通過 append 模式寫檔案,即使中途服務器宕機,可以通過 redis-check-aof 工具解決資料一致性問題,
缺點
AOF 檔案比 RDB 檔案大,且恢復速度慢,
資料集大時,比 rdb 啟動效率低,
6.什么是Redis事務?
事務是邏輯上的一組操作,要么都執行,要么都不執行,Redis 事務不是嚴格意義上的事務,只是用于幫助用戶在一個步驟中執行多個命令,單個 Redis 命令的執行是原子性的,但 Redis 沒有在事務上增加任何維持原子性的機制,所以 Redis 事務的執行并不是原子性的,
Redis 事務可以理解為一個打包的批量執行腳本,redis 事務不保證原子性,且沒有回滾,中間某條命令執行失敗,前面已執行的命令不回滾,后續的指令繼續執行,
Redis 事務可以一次執行多個命令, 并且帶有以下三個重要的保證:
批量操作在發送 EXEC 命令前被放入佇列快取,
收到 EXEC 命令后進入事務執行,事務中任意命令執行失敗,前面已執行的命令不回滾,后續的命令繼續執行,
事務在執行的程序中,不會被其他客戶端發送來的命令請求所打斷,
Redis事務的三個階段
事務開始 MULTI
命令入隊
事務執行 EXEC
Redis事務的相關命令:
| 命令 | 描述 |
| WATCH | WATCH 命令是一個樂觀鎖,可以為 Redis 事務提供 check-and-set (CAS)行為,可以監控一個或多個鍵,一旦其中有一個鍵被修改(或洗掉),之后的事務就不會執行,監控一直持續到EXEC命令, |
| UNWATCH | UNWATCH命令可以取消watch對所有key的監控, |
| MULTI | MULTI命令用于開啟一個事務,它總是回傳OK,MULTI執行之后,客戶端可以繼續向服務器發送任意多條命令,這些命令不會立即被執行,而是被放到一個佇列中,當EXEC命令被呼叫時,所有佇列中的命令才會被執行, |
| EXEC | EXEC:執行所有事務塊內的命令,回傳事務塊內所有命令的回傳值,按命令執行的先后順序排列,當操作被打斷時,回傳空值 nil , |
| DISCARD | 通過呼叫DISCARD,客戶端可以清空事務佇列,并放棄執行事務, 并且客戶端會從事務狀態中退出, |
7.談談你對Redis集群方案——哨兵模式 的理解

哨兵的介紹
sentinel,中文名是哨兵,哨兵是 redis 集群機構中非常重要的一個組件,主要有以下功能:
集群監控:負責監控 redis master 和 slave 行程是否正常作業,
訊息通知:如果某個 redis 實體有故障,那么哨兵負責發送訊息作為報警通知給管理員,
故障轉移:如果 master node 掛掉了,會自動轉移到 slave node 上,
配置中心:如果故障轉移發生了,通知 client 客戶端新的 master 地址,
哨兵用于實作 redis 集群的高可用,本身也是分布式的,作為一個哨兵集群去運行,互相協同作業,
8.Redis主從復制的原理是什么?
從節點執行 slaveof 命令
從節點只是保存了 slaveof 命令中主節點的資訊,并沒有立即發起復制
從節點內部的定時任務發現有主節點的資訊,開始使用 socket 連接主節點
連接建立成功后,發送 ping 命令,希望得到 pong 命令回應,否則會進行重連
如果主節點設定了權限,那么就需要進行權限驗證;如果驗證失敗,復制終止,
權限驗證通過后,進行資料同步,這是耗時最長的操作,主節點將把所有的資料全部發送給從節點,
當主節點把當前的資料同步給從節點后,便完成了復制的建立流程,接下來,主節點就會持續的把寫命令發送給從節點,保證主從資料一致性,

9.Redis如何實作分布式鎖?
Redis為單行程單執行緒模式,采用佇列模式將并發訪問變成串行訪問,且多客戶端對Redis的連接并不存在競爭關系,Redis中可以使用SETNX命令實作分布式鎖,
SETNX 是『SET if Not eXists』(如果不存在,則 SET)的簡寫,
當且僅當 key 不存在,將 key 的值設為 value,若給定的 key 已經存在,則 SETNX 不做任何動作
回傳值:設定成功,回傳 1 ,設定失敗,回傳 0 ,
使用SETNX完成同步鎖的流程及事項如下:
使用SETNX命令獲取鎖,若回傳0(key已存在,鎖已存在)則獲取失敗,若回傳1則獲取成功
為了防止獲取鎖后程式出現例外,導致其他執行緒/行程呼叫SETNX命令總是回傳0而進入死鎖狀態,需要為該key設定一個合理的過期時間
釋放鎖,使用DEL命令將鎖資料洗掉
10.Redis中的快取穿透、快取擊穿、快取雪崩是什么?
快取穿透:
當我們訪問某個key時,這個key對應的資料在資料源并不存在,每次針對這個key的請求從快取中都獲取不到,那么這些請求都會壓到資料源(DB),從而可能壓垮資料源,比如用一個不存在的用戶id獲取用戶資訊,不論快取還是資料庫都沒有,若黑客利用此漏洞進行攻擊可能壓垮資料庫,
解決方案:
- 對空值快取:如果一個查詢回傳的資料為空(不管是資料是否不存在),我們仍然把這個空結果(null)進行快取,設定空結果的過期時間會很短,最長不超過五分鐘,
- 設定可訪問的名單(白名單):使用bitmaps型別定義一個可以訪問的名單,名單id作為bitmaps的偏移量,每次訪問和bitmap里面的id進行比較,如果訪問id不在bitmaps里面,進行攔截,不允許訪問,
- 采用布隆過濾器:將所有可能存在的資料哈希到一個足夠大的bitmaps中,一個一定不存在的資料會被 這個bitmaps攔截掉,從而避免了對底層存盤系統的查詢壓力,
快取擊穿:
key對應的資料存在,但在redis中過期,此時若有大量并發請求過來,這些請求發現快取過期一般都會從后端DB加載資料并回設到快取,這個時候大并發的請求可能會瞬間把后端DB壓垮,
解決方案:
- 預先設定熱門資料:在redis高峰訪問之前,把一些熱門資料提前存入到redis里面,加大這些熱門資料key的存活時長,避免在高并發期間這些資料過期,
- 實時調整:現場監控哪些資料熱門,實時調整key的過期時長,
- 使用鎖
快取雪崩:
當我們訪問多個key對應的資料時,這些key在redis中都過期(無法獲取)了,那么這些大量的高并發請求就會轉到后端DB中去查找訪問,進而造成了資料庫的崩潰現象,快取雪崩與快取擊穿的區別在于:快取雪崩是針對很多key而言的快取,而快取擊穿則是針對某一個key,
解決方案:
- 構建多級快取架構:nginx快取 + redis快取 +其他快取(ehcache等),
- 使用鎖或佇列:用加鎖或者佇列的方式保證不會有大量的執行緒對資料庫一次性進行讀寫,從而避免失效時大量的并發請求落到底層存盤系統上,不適用高并發情況,
- 設定過期標志更新快取:記錄快取資料是否過期(設定提前量),如果過期會觸發通知另外的執行緒在后臺去更新實際key的快取,
- 將快取失效時間分散開:比如我們可以在原有的失效時間基礎上增加一個隨機值,比如1-5分鐘隨機,這樣每一個快取的過期時間的重復率就會降低,就很難引發集體失效的事件,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/310566.html
標籤:java






