1. 程式人生 > 資料庫 >2020-12-21簡單的redis問題及回答

2020-12-21簡單的redis問題及回答

學習筆記-面試問題筆記

2020-12-18,公司大佬問我面試問題,redis是什麼,為什麼要用它。

redis是非關係型資料庫,儲存的都是鍵值對型別的資料,因為是單執行緒的所以效能比關係型資料庫(mysql,sqlserver,oracle )更優,緩解資料庫的壓力,資料處理效率更快。

redis的應用場景?驗證碼,購物車資訊,待支付的訂單資訊(用過的待微信回撥)。

但是具體的我就不是很清楚了。

 

關於面試題,記幾個網上有的,希望手打能勉強記住

1.Redis支援的基本資料型別?

五種基本資料型別:String 字串,LIst 列表,Hash 雜湊,Set 集合,ZSet(sort set) 有序集合

具體解釋:

String 

格式是 set key value

string是二進位制安全的。意思是redis的string可以包含任何資料。比如jpg圖片或者序列化的物件。

string型別是Redis最基本的資料型別,一個鍵最大能儲存512MB。

List 列表

Redis 列表是簡單的字串列表,按照插入順序排序。你可以新增一個元素到列表的頭部(左邊)或者尾部(右邊)

格式 lpush name value

在 key 對應 list 的頭部新增字串元素

格式 rpush name value

在 key 對應 list 的尾部新增字串元素

格式 lrem name index (目前不能理解)

key 對應 list 中刪除count個和value相同的元素

格式 llen name

返回 key 對應 list 的長度

Hash 雜湊

格式 hmset name key1 value1 key2 value2

Redis hash 是一個鍵值對集合。

Redis hash 是一個 string 型別的 field 和 value 的對映表,hash特別適合用於儲存物件。

Set 集合

格式 sadd  name value

Redis 的 Set 是 String 型別的無序集合。

集合是通過雜湊表實現的,所以新增,刪除,查詢的複雜度都是0(1)。

ZSet 有序集合

格式 zadd name score value

Redis ZSet 和 Set 一樣也是String型別元素的集合,且不允許重複的成員。

不同的是每個元素都會關聯一個double型別的分數。Redis正是通過分數來為集合中的成員進行從小到大的排序。

ZSet的成員是唯一的,但是分數(Score)可以重複。

2.什麼是Redis持久化?Redis有哪幾種持久化方式?優缺點是什麼?

持久化就是把快取(記憶體)中的資料寫到磁碟中去,防止服務宕機了快取(記憶體)資料丟失。

Redis提供兩種方式持久化:RDB和AOF

  • RDB:是 Redis DataBase 的縮寫 學名叫 映象全量持久化

        功能核心函式 rdbSave(生成RDB檔案) 和 rdbLoad(從檔案載入記憶體) 兩個函式

  • AOF:是 Append-only file 的縮寫 學名叫 增量持久化

        每當執行伺服器(定時)任務或者函式時,flushAppendOnlyFile 函式都被會呼叫,此時,此函式將執行一下兩個工作:aof 寫入儲存:write 和 save

           write 根據條件 ,將 aof_buf 中的快取寫入到AOF檔案

           save 根據條件,呼叫 fsync 或 fdatasync函式,將AOF檔案儲存到磁碟中

比較:

  1. aof 檔案比 rdb更新頻率高,優先使用 aof 還原資料。
  2. aof 比 rdb 更安全也更大
  3. rdb 效能比 aof 更好
  4. 如果兩個都配了,建議優先載入 aof

3.什麼是快取雪崩和快取穿透 還有擊穿,怎麼解決?

快取雪崩 是指 伺服器重啟或者大量快取集中在同一個時間 失效,導致大量的請求直接由後端資料庫處理。導致系統崩潰。

個人理解:啟用redis是 用來 緩解後端資料庫 壓力,大概是 前端訪問redis,redis如果存有需要的資料則直接返回資料,如果沒有則返回不存在,前端直接請求資料庫,然後將主動將資料庫資料快取到redis。假如,大部分的快取的資料,在某一個時間段失效,比如說,快取到期或者伺服器重啟,導致大量的請求同時 需要直接 去訪問後臺資料庫,造成後端資料庫掛掉。

快取穿透 是指 請求 快取和資料庫中都沒有的資料 ,而使用者不斷髮起請求。

網頁案例:一般的快取系統,都是按照key去快取查詢,如果不存在對應的value,就應該去後端系統查詢,一些惡意的請求會故意查詢不存在的key,就會對後端系統造成很大壓力。

快取擊穿 是指 某幾個key非常熱點,承擔了大量請求,當這幾個key在失效的瞬間,持續的大併發就穿破快取,直接請求資料庫。這個和快取雪崩的區別在於這裡針對某幾個key快取,前者則是很多key。

個人理解:一般秒殺活動或者什麼活動,如果幾個熱點商品,快取失效,還是會導致量大量請求直接衝向後端資料庫。

redis快取雪崩怎麼解決?

  1. 使用互斥鎖(mutex key)在快取失效後,通過加鎖或者佇列來控制 讀資料庫寫快取 的執行緒數量。比如對某個key只允許一個執行緒查詢資料和寫快取,其他執行緒等待。
  2. 做二級快取,A1為原始快取,A2為拷貝快取,A1的失效時間設定為短期,A2設定為長期,A1失效時,可以訪問A2
  3. 不同的key,設定不同的過期時間,一般需要在時間上加一個隨機值,讓快取失效的時間點儘量均勻。

redis快取穿透怎麼解決?

  1. 對查詢結果為空的情況也進行快取,快取時間設定短一點,或者該key對應的資料insert了之後清理快取。
  2. 對一定不存在的key進行過濾。可以把所有的可能存在的key放到一個大的Bitmap中,查詢時通過該bitmap過濾。

redis快取擊穿怎麼解決?

  1. 使用互斥鎖(mutex key) 只讓一個執行緒構建快取,其他執行緒等待 構建快取的執行緒執行完,重新從快取獲取資料。
  2. 熱點資料設定永不過期,有更新操作就更新快取

大佬給我發的,我也記錄下來

快取穿透
快取穿透是指查詢一個一定不存在的資料,由於快取是不命中時被動寫的,並且出於容錯考慮,如果從儲存層查不到資料則不寫入快取,這將導致這個不存在的資料每次請求都要到儲存層去查詢,失去了快取的意義。在流量大時,可能DB就掛掉了,要是有人利用不存在的key頻繁攻擊我們的應用,這就是漏洞。
解決方案
有很多種方法可以有效地解決快取穿透問題,最常見的則是採用布隆過濾器,將所有可能存在的資料雜湊到一個足夠大的bitmap中,一個一定不存在的資料會被 這個bitmap攔截掉,從而避免了對底層儲存系統的查詢壓力。另外也有一個更為簡單粗暴的方法(我們採用的就是這種),如果一個查詢返回的資料為空(不管是數 據不存在,還是系統故障),我們仍然把這個空結果進行快取,但它的過期時間會很短,最長不超過五分鐘。
快取雪崩
快取雪崩是指在我們設定快取時採用了相同的過期時間,導致快取在某一時刻同時失效,請求全部轉發到DB,DB瞬時壓力過重雪崩。
解決方案
快取失效時的雪崩效應對底層系統的衝擊非常可怕。大多數系統設計者考慮用加鎖或者佇列的方式保證快取的單線 程(程序)寫,從而避免失效時大量的併發請求落到底層儲存系統上。這裡分享一個簡單方案就時講快取失效時間分散開,比如我們可以在原有的失效時間基礎上增加一個隨機值,比如1-5分鐘隨機,這樣每一個快取的過期時間的重複率就會降低,就很難引發集體失效的事件。
快取擊穿
對於一些設定了過期時間的key,如果這些key可能會在某些時間點被超高併發地訪問,是一種非常“熱點”的資料。這個時候,需要考慮一個問題:快取被“擊穿”的問題,這個和快取雪崩的區別在於這裡針對某一key快取,前者則是很多key。
快取在某個時間點過期的時候,恰好在這個時間點對這個Key有大量的併發請求過來,這些請求發現快取過期一般都會從後端DB載入資料並回設到快取,這個時候大併發的請求可能會瞬間把後端DB壓垮。
解決方案
使用互斥鎖(mutex key)
業界比較常用的做法,是使用mutex。簡單地來說,就是在快取失效的時候(判斷拿出來的值為空),不是立即去load db,而是先使用快取工具的某些帶成功操作返回值的操作(比如Redis的SETNX或者Memcache的ADD)去set一個mutex key,當操作返回成功時,再進行load db的操作並回設快取;否則,就重試整個get快取的方法。
 

4.為什麼redis會啥快?

  1. 完全基於記憶體,記憶體的讀寫速度是非常快的。
  2. 資料結構簡單
  3. 採用單執行緒,避免不必要的上下文切換和競爭條件,省去了很多上下文切換執行緒的時間
  4. 也不存在多程序或者多執行緒導致的切換而消耗CPU,不用考慮各種鎖的問題
  5. 使用多路 I/O 複用模型,非阻塞I/O
  6. 底層通過機制優化

文件來源: