JavaGuide知識點整理——Redis面試題總結(下)

Redis事務

如何使用Redis事務?

Redis可以通過multi,exec,discard和watch等命令來實現事務功能。
使用multi命令後可以輸入多個命令。Redis會將這些命令放到隊列中,調用了exec命令後執行所有命令(隊列中的命令按照FIFO順序執行)。
而discard則可以清除隊列中的所有命令。
watch命令用於監聽指定的鍵。當調用exec命令執行事務時,如果一個被watch命令監視的鍵被修改的話,整個事務都不會執行,直接返回失敗。

Redis支持原子性麼?

事務的四大特性:原子性,隔離性,一致性,持久性。
而Redis事務在運行錯誤的情況下,除了執行過程中出現錯誤的命令外,其它命令都能正常執行。並且Redis不支持回滾,因爲Redis事務其實不滿足原子性。
你可以將Redis事務理解成:Redis事務提供了一種將多個命令請求打包的功能。然後再按順序執行打包的所有命令,並且不會被中途打斷。

如何解決Redis事務的缺陷?

redis從2.6版本開始支持Lua腳本,它的功能和事務非常類似。我們可以利用Lua腳本來批量執行多條Redis命令。這些Redis命令會被提交到Redis服務器一次性執行完成,減小了網絡開銷。
Lua腳本運行出錯時,出錯之後的命令不會執行,但是之前的命令無法撤銷,所以其實Lua腳本也是不滿足原子性的。

Redis性能優化

Redis Bigkey

簡單來說,如果一個key對應的value所佔用的內存比較大,那麼這個key可以看作是bigkey。String類型超過10kb,複合類型value包含的元素超過5k個就算是bigkey。
bigkey除了會消耗更多的內存空間,對性能也會有比較大的影響。因爲我們要避免寫入bigkey。
可以使用Redis自帶的** --bigkeys**參數來查找
這個命令會掃描Redis中的所有key,會對性能有一點影響。並且這種方式只能找出每種數據結構的第一個bigkey。
也可以分析RDB文件,前提是Redis採用了RDB持久化。網上有現成的代碼/工具可以拿來用:

  • redis-rdb-tools :Python 語言寫的用來分析 Redis 的 RDB 快照文件用的工具
  • rdb_bigkeys : Go 語言寫的用來分析 Redis 的 RDB 快照文件用的工具,性能更好。

大量key集中過期問題

對於過期key,redis採用定期刪除+惰性刪除策略。
定期刪除執行過程中,如果突然遇到大量過期的key的話,客戶端請求必須等待定期清理過期key任務線程執行完成。因爲這個定期任務線程是Redis主線程中執行的,這就導致客戶端請求沒有辦法即使處理,響應速度會比較慢。
有兩種方法解決:

  1. 給key設置隨機過期時間
  2. 開啓惰性刪除/延遲釋放。這個是Redis4.0引入的,指的是讓Redis採用異步方式延遲釋放key使用的內存。將該操作交給單獨的子線程處理,避免阻塞主線程。

Redis生產問題

緩存穿透

什麼是緩存穿透?
緩存穿透簡單說就是大量請求的key不存在於緩存中,導致請求直接到了數據庫上,根本沒經過緩存這一層。
有哪些解決辦法?
最近本的就是首先做好參數校驗,一些不合法的參數請求直接拋出異常信息。比如數據庫id不能小於0,傳入的郵箱格式不對直接返回等。

  • 緩存無效key
    如果緩存和數據庫都查不到某個key的數據,就寫一個到Redis中並設置過期時間。這種情況可以解決請求的key變化不頻繁的情況下。如果黑客攻擊每次構建不同的請求key,會導致Redis中緩存大量無效的key,很明顯折中方案不能從根本上解決這個問題。如果非要用這種方式,我們可以儘量把過期時間設置短一點。
  • 布隆過濾器
    這是一個神奇的數據結構,我們可以非常方便的判斷給定數據是否存在於海量數據中,我們需要的就是判斷key是否合法。如果不合法直接返回。


緩存雪崩

什麼是緩存雪崩?
緩存在同一時間大面積的失效,後面的請求都直接落到數據庫上,造成了數據庫短時間承受大量請求。這就好比雪崩一樣。
舉個例子,如果緩存模塊宕機了,造成所有的訪問都要走數據庫。
還有一種場景是:有一些被大量訪問的熱點數據在某一時刻大面積失效。導致對應的請求直接落到數據庫上。
有哪些解決辦法?
針對服務不可用,可以:

  1. 採用Redis集羣,避免單機出現問題而整個緩存服務都沒辦法使用
  2. 限流,避免同時處理大量的請求

針對熱點緩存失效,可以:

  1. 設置不同的失效時間(比如隨機失效時間)
  2. 緩存永不失效

如何保證緩存和數據庫的一致性?

其實這個方法很多,但是引入緩存以後,爲了短時間的不一致讓系統更復雜的話沒必要,所以下面說一種比較簡單直接的方法:Cache Aside Pattern(旁路緩存模式).
其實簡單來說,如果數據庫中數據更新,直接刪除緩存。
而如果刪除緩存這一步失敗的話,有兩個解決方案:

  1. 緩存失效時間設置很短(治標不治本,如果能接收短時間不一致可以)
  2. 增加緩存更新重試機制:如果刪除失敗則隔一段時間就重試一下。或者把失敗的key加入隊列中,等緩存服務器可用後再把對應的key刪除。

本篇筆記就記到這裏,如果稍微幫到你了記得點個喜歡點個關注。也祝大家工作順順利利!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章