久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

Redis面試題的示例分析

153次閱讀
沒有評論

共計 5194 個字符,預計需要花費 13 分鐘才能閱讀完成。

自動寫代碼機器人,免費開通

這篇文章給大家分享的是有關 Redis 面試題的示例分析的內容。丸趣 TV 小編覺得挺實用的,因此分享給大家做個參考,一起跟隨丸趣 TV 小編過來看看吧。

應用場景

緩存

共享 Session

消息隊列系統

分布式鎖

相關推薦:Redis 視頻教程

單線程的 Redis 為什么快

純內存操作

單線程操作,避免了頻繁的上下文切換

合理高效的數據結構

采用了非阻塞 I / O 多路復用機制(有一個文件描述符同時監聽多個文件描述符是否有數據到來)

Redis 的數據結構及使用場景

String 字符串: 字符串類型是 Redis 最基礎的數據結構,首先鍵都是字符串類型,而且 其他幾種數據結構都是在字符串類型基礎上構建的,我們常使用的 set key value 命令就是字符串。常用在緩存、計數、共享 Session、限速等。

Hash 哈希: 在 Redis 中,哈希類型是指鍵值本身又是一個鍵值對結構,哈希可以用來存放用戶信息,比如實現購物車。

List 列表(雙向鏈表): 列表(list)類型是用來存儲多個有序的字符串。可以做簡單的消息隊列的功能。

Set 集合:集合(set)類型也是用來保存多個的字符串元素,但和列表類型不一 樣的是,集合中不允許有重復元素,并且集合中的元素是無序的,不能通過索引下標獲取元素。利用 Set 的交集、并集、差集等操作,可以計算共同喜好,全部的喜好,自己獨有的喜好等功能。

Sorted Set 有序集合(跳表實現):Sorted Set 多了一個權重參數 Score,集合中的元素能夠按 Score 進行排列。可以做排行榜應用,取 TOP N 操作。

Redis 的數據過期策略

Redis 中數據過期策略采用定期刪除 + 惰性刪除策略

定期刪除策略:Redis 啟用一個定時器定時監視所有的 key,判斷 key 是否過期,過期的話就刪除。這種策略可以保證過期的 key 最終都會被刪除,但是也存在嚴重的缺點:每次都遍歷內存中所有的數據,非常消耗 CPU 資源,并且當 key 已過期,但是定時器還處于未喚起狀態,這段時間內 key 仍然可以用。

惰性刪除策略:在獲取 key 時,先判斷 key 是否過期,如果過期則刪除。這種方式存在一個缺點:如果這個 key 一直未被使用,那么它一直在內存中,其實它已經過期了,會浪費大量的空間。

這兩種策略天然的互補,結合起來之后,定時刪除策略就發生了一些改變,不再是每次掃描全部的 key 了,而是隨機抽取一部分 key 進行檢查,這樣就降低了對 CPU 資源的損耗,惰性刪除策略互補了未檢查到的 key,基本上滿足了所有要求。但是有時候就是那么的巧,既沒有被定時器抽取到,又沒有被使用,這些數據又如何從內存中消失?沒關系,還有內存淘汰機制,當內存不夠用時,內存淘汰機制就會上場。淘汰策略分為:當內存不足以容納新寫入數據時,新寫入操作會報錯。(Redis 默認策略)當內存不足以容納新寫入數據時,在鍵空間中,移除最近最少使用的 Key。(LRU 推薦使用)當內存不足以容納新寫入數據時,在鍵空間中,隨機移除某個 Key。當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,移除最近最少使用的 Key。這種情況一般是把 Redis 既當緩存,又做持久化存儲的時候才用。當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,隨機移除某個 Key。當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,有更早過期時間的 Key 優先移除。

Redis 的 set 和 setnx

Redis 中 setnx 不支持設置過期時間,做分布式鎖時要想避免某一客戶端中斷導致死鎖,需設置 lock 過期時間,在高并發時 setnx 與 expire 不能實現原子操作,如果要用,得在程序代碼上顯示的加鎖。使用 SET 代替 SETNX,相當于 SETNX+EXPIRE 實現了原子性,不必擔心 SETNX 成功,EXPIRE 失敗的問題。

Redis 的 LRU 具體實現:

傳統的 LRU 是使用棧的形式,每次都將最新使用的移入棧頂,但是用棧的形式會導致執行 select * 的時候大量非熱點數據占領頭部數據,所以需要改進。Redis 每次按 key 獲取一個值的時候,都會更新 value 中的 lru 字段為當前秒級別的時間戳。Redis 初始的實現算法很簡單,隨機從 dict 中取出五個 key, 淘汰一個 lru 字段值最小的。在 3.0 的時候,又改進了一版算法,首先第一次隨機選取的 key 都會放入一個 pool 中(pool 的大小為 16),pool 中的 key 是按 lru 大小順序排列的。接下來每次隨機選取的 keylru 值必須小于 pool 中最小的 lru 才會繼續放入,直到將 pool 放滿。放滿之后,每次如果有新的 key 需要放入,需要將 pool 中 lru 最大的一個 key 取出。淘汰的時候,直接從 pool 中選取一個 lru 最小的值然后將其淘汰。

Redis 如何發現熱點 key

憑借經驗,進行預估:例如提前知道了某個活動的開啟,那么就將此 Key 作為熱點 Key。

服務端收集:在操作 redis 之前,加入一行代碼進行數據統計。

抓包進行評估:Redis 使用 TCP 協議與客戶端進行通信,通信協議采用的是 RESP,所以自己寫程序監聽端口也能進行攔截包進行解析。

在 proxy 層,對每一個 redis 請求進行收集上報。

Redis 自帶命令查詢:Redis4.0.4 版本提供了 redis-cli –hotkeys 就能找出熱點 Key。(如果要用 Redis 自帶命令查詢時,要注意需要先把內存逐出策略設置為 allkeys-lfu 或者 volatile-lfu,否則會返回錯誤。進入 Redis 中使用 config set maxmemory-policy allkeys-lfu 即可。)

Redis 的熱點 key 解決方案

服務端緩存:即將熱點數據緩存至服務端的內存中.(利用 Redis 自帶的消息通知機制來保證 Redis 和服務端熱點 Key 的數據一致性,對于熱點 Key 客戶端建立一個監聽,當熱點 Key 有更新操作的時候,服務端也隨之更新。)

備份熱點 Key:即將熱點 Key+ 隨機數,隨機分配至 Redis 其他節點中。這樣訪問熱點 key 的時候就不會全部命中到一臺機器上了。

如何解決 Redis 緩存雪崩問題

使用 Redis 高可用架構:使用 Redis 集群來保證 Redis 服務不會掛掉

緩存時間不一致,給緩存的失效時間,加上一個隨機值,避免集體失效

限流降級策略:有一定的備案,比如個性推薦服務不可用了,換成熱點數據推薦服務

如何解決 Redis 緩存穿透問題

在接口做校驗

存 null 值(緩存擊穿加鎖, 或設置不過期)

布隆過濾器攔截:將所有可能的查詢 key 先映射到布隆過濾器中,查詢時先判斷 key 是否存在布隆過濾器中,存在才繼續向下執行,如果不存在,則直接返回。布隆過濾器將值進行多次哈希 bit 存儲,布隆過濾器說某個元素在,可能會被誤判。布隆過濾器說某個元素不在,那么一定不在。

Redis 的持久化機制

Redis 為了保證效率,數據緩存在了內存中,但是會周期性地把更新的數據寫入磁盤或者把修改操作寫入追加的記錄文件中,以保證數據的持久化。Redis 的持久化策略有兩種:

RDB:快照形式是直接把內存中的數據保存到一個 dump 的文件中,定時保存,保存策略。當 Redis 需要做持久化時,Redis 會 fork 一個子進程,子進程將數據寫到磁盤上一個臨時 RDB 文件中。當子進程完成寫臨時文件后,將原來的 RDB 替換掉。

AOF:把所有的對 Redis 的服務器進行修改的命令都存到一個文件里,命令的集合。

使用 AOF 做持久化,每一個寫命令都通過 write 函數追加到 appendonly.aof 中。aof 的默認策略是每秒鐘 fsync 一次,在這種配置下,就算發生故障停機,也最多丟失一秒鐘的數據。缺點是對于相同的數據集來說,AOF 的文件體積通常要大于 RDB 文件的體積。根據所使用的 fsync 策略,AOF 的速度可能會慢于 RDB。Redis 默認是快照 RDB 的持久化方式。對于主從同步來說,主從剛剛連接的時候,進行全量同步(RDB);全同步結束后,進行增量同步(AOF)。

Redis 的事務

Redis 事務的本質是一組命令的集合。事務支持一次執行多個命令,一個事務中所有命令都會被序列化。在事務執行過程,會按照順序串行化執行隊列中的命令,其他客戶端提交的命令請求不會插入到事務執行命令序列中。總結說:redis 事務就是一次性、順序性、排他性的執行一個隊列中的一系列命令。

Redis 事務沒有隔離級別的概念,批量操作在發送 EXEC 命令前被放入隊列緩存,并不會被實際執行,也就不存在事務內的查詢要看到事務里的更新,事務外查詢不能看到。

Redis 中,單條命令是原子性執行的,但事務不保證原子性,且沒有回滾。事務中任意命令執行失敗,其余的命令仍會被執行。

Redis 事務相關命令

watch key1 key2 … : 監視一或多個 key, 如果在事務執行之前,被監視的 key 被其他命令改動,則事務被打斷(類似樂觀鎖)

multi : 標記一個事務塊的開始(queued)

exec : 執行所有事務塊的命令(一旦執行 exec 后,之前加的監控鎖都會被取消掉)

discard : 取消事務,放棄事務塊中的所有命令

unwatch : 取消 watch 對所有 key 的監控

Redis 和 memcached 的區別

存儲方式上:memcache 會把數據全部存在內存之中,斷電后會掛掉,數據不能超過內存大小。redis 有部分數據存在硬盤上,這樣能保證數據的持久性。

數據支持類型上:memcache 對數據類型的支持簡單,只支持簡單的 key-value,,而 redis 支持五種數據類型。

用底層模型不同:它們之間底層實現方式以及與客戶端之間通信的應用協議不一樣。redis 直接自己構建了 VM 機制,因為一般的系統調用系統函數的話,會浪費一定的時間去移動和請求。

value 的大小:redis 可以達到 1GB,而 memcache 只有 1MB。

Redis 的幾種集群模式

主從復制

哨兵模式

cluster 模式

Redis 的哨兵模式

哨兵是一個分布式系統, 在主從復制的基礎上你可以在一個架構中運行多個哨兵進程, 這些進程使用流言協議來接收關于 Master 是否下線的信息, 并使用投票協議來決定是否執行自動故障遷移, 以及選擇哪個 Slave 作為新的 Master。

每個哨兵會向其它哨兵、master、slave 定時發送消息, 以確認對方是否活著, 如果發現對方在指定時間 (可配置) 內未回應, 則暫時認為對方已掛(所謂的”主觀認為宕機”)。

若“哨兵群“中的多數 sentinel, 都報告某一 master 沒響應, 系統才認為該 master 徹底死亡 (即: 客觀上的真正 down 機), 通過一定的 vote 算法, 從剩下的 slave 節點中, 選一臺提升為 master, 然后自動修改相關配置。

Redis 的 rehash

Redis 的 rehash 操作并不是一次性、集中式完成的,而是分多次、漸進式地完成的,redis 會維護維持一個索引計數器變量 rehashidx 來表示 rehash 的進度。

這種漸進式的 rehash 避免了集中式 rehash 帶來的龐大計算量和內存操作,但是需要注意的是 redis 在進行 rehash 的時候,正常的訪問請求可能需要做多要訪問兩次 hashtable(ht[0],ht[1]),例如鍵值被 rehash 到新 ht1,則需要先訪問 ht0,如果 ht0 中找不到,則去 ht1 中找。

Redis 的 hash 表被擴展的條件

哈希表中保存的 key 數量超過了哈希表的大小.

Redis 服務器目前沒有在執行 BGSAVE 命令(rdb)或 BGREWRITEAOF 命令,并且哈希表的負載因子大于等于 1.

Redis 服務器目前在執行 BGSAVE 命令(rdb)或 BGREWRITEAOF 命令,并且哈希表的負載因子大于等于 5.(負載因子 = 哈希表已保存節點數量 / 哈希表大小,當哈希表的負載因子小于 0.1 時,對哈希表執行收縮操作。)

Redis 并發競爭 key 的解決方案

分布式鎖 + 時間戳

利用消息隊列

Redis 的管道 pipeline

對于單線程阻塞式的 Redis,Pipeline 可以滿足批量的操作,把多個命令連續的發送給 Redis Server,然后一一解析響應結果。Pipelining 可以提高批量處理性能,提升的原因主要是 TCP 連接中減少了“交互往返”的時間。pipeline 底層是通過把所有的操作封裝成流,redis 有定義自己的出入輸出流。在 sync() 方法執行操作,每次請求放在隊列里面,解析響應包。

Redis 與 Mysql 雙寫一致性方案

先更新數據庫,再刪緩存。數據庫的讀操作的速度遠快于寫操作的,所以臟數據很難出現。可以對異步延時刪除策略,保證讀請求完成以后,再進行刪除操作。

感謝各位的閱讀!關于“Redis 面試題的示例分析”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!

向 AI 問一下細節

正文完
 
丸趣
版權聲明:本站原創文章,由 丸趣 2023-12-04發表,共計5194字。
轉載說明:除特殊說明外本站除技術相關以外文章皆由網絡搜集發布,轉載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 大厂| 琼海市| 连云港市| 鹤峰县| 元阳县| 诏安县| 潜江市| 开远市| 宜宾市| 盐城市| 虎林市| 岫岩| 吉安市| 讷河市| 伊吾县| 嘉峪关市| 焦作市| 扎囊县| 阿城市| 兴业县| 伊吾县| 安图县| 南昌县| 威信县| 台北市| 宝坻区| 达拉特旗| 大荔县| 安平县| 汤原县| 交城县| 湖口县| 长子县| 富川| 民和| 灵宝市| 泰州市| 临洮县| 剑川县| 开封县| 育儿|