【redis】redis應用場景,緩存的各種問題解析

来源:https://www.cnblogs.com/ztfjs/archive/2019/08/21/redis-cache.html
-Advertisement-
Play Games

如果你還不知道redis的基本命令與基本使用方法,請看 【redis】redis基礎命令學習集合 緩存 redis還有另外一個重要的應用領域——緩存 引用來自網友的圖解釋緩存在架構中的位置 預設情況下,我們的服務架構如下圖,客戶端請求service,然後service去讀取mysql資料庫 問題存在 ...


如果你還不知道redis的基本命令與基本使用方法,請看 

【redis】redis基礎命令學習集合

緩存

redis還有另外一個重要的應用領域——緩存

引用來自網友的圖解釋緩存在架構中的位置

預設情況下,我們的服務架構如下圖,客戶端請求service,然後service去讀取mysql資料庫

avatar

問題存在於,資料庫性能不夠用,資料庫是整個架構中最重要的一個環節,它在高併發,高寫入頻次的時候非常容易崩掉,這是一般的資料庫本身的特性所決定的,它們的架構模式註定了不可以承受較大的併發量,所以就有了緩存:

avatar

service與高速的緩存進行交互,如果緩存中有數據直接返回客戶端,如果沒有才會從MySql中去查詢。減小資料庫的壓力,提升效率,避免宕機。

例如上面章節提到的,超賣問題,有可能瞬間的流量高達上萬,我們不可能把這些請求都響應到資料庫上,這樣速度慢不說,還隨時可能宕機。

提到緩存,就不得不說下麵的四大緩存名場面,幾乎是做緩存必須面對的問題。

緩存擊穿

想象一個場景,現在在一個xx辦事大廳

張三、李四、王五、趙六、錢錢、劉八、陳九 七個人正在排隊

辦事處有一個視窗,有一些自動業務機,視窗裡面的同志一下子只能接待一個人,而自動業務機因為速度很快可以很快接待很多人。

現在,突然、自動業務機都壞了... 所有人都排到了視窗,這下忙死了視窗裡面的同志,直接撂挑子不幹了!

這個例子中,自動業務機就像是緩存,起了一個緩衝的作用,業務員就像是資料庫,處理能力比自動機器慢,而且很容易炸毛。

緩存擊穿就是這樣,當某個緩存故障、或者在高峰期緩存突然無效了,就會導致所有請求都跑到資料庫去排隊,就造成了緩存擊穿。

 

緩存相當於給資料庫加了一層保護能量罩,敵人進來的時候如果某個地方沒有能量,那麼如果這個地方的敵人特別多,就會導致緩存擊穿。當從緩存中查詢不到我們需要的數據就要去資料庫中查詢了。如果被黑客利用,或者高峰流量,頻繁去訪問緩存中沒有的數據,那麼緩存就失去了存在的意義,瞬間所有請求的壓力都落在了資料庫上,這樣會導致資料庫連接異常。

解決方案:

  • 後臺設置定時任務,主動的去更新緩存數據。這種方案容易理解,就是在自動業務機旁邊加了一個維護員,壞了趕緊修好,但是機器多了就比較複雜,維護員不一定能搞得定,當key比較分散的時候,操作起來還是比較複雜的

  • 分級緩存。什麼意思呢,就是放兩台業務機器,平時用第一臺,第一臺壞了馬上用第二台,用第二台的時候修第一臺,設置兩層緩存保護層,1級緩存失效時間短,2級緩存失效時間長。有請求過來優先從1級緩存中去查找,如果在1級緩存中沒有找到相應數據,則對該線程進行加鎖,這個線程再從資料庫中取到數據,更新至1級和2級緩存。其他線程則直接從2級線程中獲取

緩存穿透

緩存穿透本質上和緩存擊穿所面臨的問題一樣,大量請求落到資料庫中。

但是出發點略有不用,緩存穿透的問題是,在高併發下,查詢一個不存在的值時,緩存不會被命中,導致大量請求直接落到資料庫上,如活動系統裡面查詢一個不存在的活動。

也就是說,緩存擊穿是當數據是存在的,但沒有被緩存到,而緩存穿透是去訪問根本不存在的值。想象一個場景,黑客截取了一個已經過期的活動的數據介面,然後不斷的去請求它,這時候有可能因為這個活動本身已經過期了,緩存不會命中,請求就全部落地到資料庫了,這時候就造成了緩存穿透。

緩存穿透的問題解決方案也有很多

直接緩存NULL值

這個比較容易理解,就算是沒數據我也緩存一下,你下次過來命中的是空數據。

這種方法需要特別註意,為空的值不能緩存的太久,否則有可能在真的有數據的時候影響了業務正常流程。

布隆過濾器

什麼是布隆過濾器

布隆過濾器判斷一個值不存在,那麼這個值100%不存在

布隆過濾器判斷一個值存在,這個值90%是存在的

布隆過濾器本質是一個位數組,位數組就是數組的每個元素都只占用 1 bit 。每個元素只能是 0 或者 1。這樣申請一個 10000 個元素的位數組只占用 10000 / 8 = 1250 B 的空間。布隆過濾器除了一個位數組,還有 K 個哈希函數。

等一下,是不是有點繞,不太好理解。

我們知道hash函數可以根據一個值生成一個對應的數字,然後與一個長度可以取模可以得到一個下標值 (你不知道?看看HashMap的實現吧)

或者你根本不知道hash是怎麼實現的,沒關係,也可以先理解下麵的,我們先把這個函數假設為 int getIndex (String value), 根據值獲取到一個下標

假設我們現在有一個數組,長度是5,每個元素的值都是0

0 , 0 , 0 , 0 , 0

現在我們資料庫中一共有五個id

a , b , c , d , e

現在我們對id們執行getIndex函數可以得到

getIndex(a) = 0

getIndex(b) = 1

getIndex(c) = 1 // 假設函數有一些誤差

getIndex(d) = 2

getIndex(e) = 3

想一想,現在來了一個新元素,f 怎麼樣判斷在id裡面存在不存在呢?

我們把開始的數組和getIndex關聯起來, 將getindex的值作為下標,設置值為1,數組就會變成

1 , 1 , 1 , 1 , 0

然後我們再來判斷f是否存在,假設 getIndex(f) = 4

ok了,我們只需要判斷數組裡的下標4是否是1,是1就存在,0就不存在了嘛

那如果 getIndex(f) = 2 呢? 我們開了上帝視角,很明顯f不存在呀。

布隆過濾器不能100%判斷一個元素是否真的存在數組中,但能100%判斷它不存在與數組中,這取決於hash函數的演算法程度

布隆過濾器防止緩存穿透

通過對布隆過濾器的理解,我們能就過濾掉大部分的無效請求了,把資料庫中所有的id都getindex解析一次放到布隆過濾器中,請求過來的時候判斷,如果不存在就直接返回空就行了

緩存雪崩

如果緩存集中在一段時間內失效,發生大量的緩存穿透,所有的查詢都落在資料庫上,造成了緩存雪崩。

其實與緩存擊穿的理論差不多,都是突然失效導致的擊穿資料庫。

雪崩與擊穿的不同點在於雪崩強調集中失效兩個字

想象~ 我現在有三個緩存key存在redis中,過期時間是一天

一天後,由於key有可能是同時設置的緩存,導致這三個key同時失效了,即使我的緩存擊穿問題已經解決,這時候因為集中的key失效,也會造成擊穿!,這是量級發生了改變,就像x和y的關係, x表示key的多少,y表示請求的多少。。。

解決方案

  • 設置不同的過期時間

熱度數據

你永遠不可能每個緩存都能命中的。什麼是好的緩存策略,好的緩存策略是能夠識別熱點數據,併在熱點被讀取的時候能夠保證命中,這是一個好的緩存策略所必須的條件之一。

 

緩存一致性

 

資料庫的數據和緩存的數據是不可能一致的,數據分為最終一致和強一致兩類。

強一致 不可以使用緩存

緩存能做的只能保證數據的最終一致性。

我們能做的只能是儘可能的保證數據的一致性。

不管是先刪庫再刪緩存 還是 先刪緩存再刪庫,都可能出現數據不一致的情況,因為讀和寫操作是併發的,我們沒辦法保證他們的先後順序。

具體應對策略根據業務需求來制訂。

 

緩存過期和淘汰

 

Redis設置的過期時間。這個key過期時是怎麼刪除的?

Redis採用的是定期刪除,註意不是定時刪除,不可能為每一個key做一個定時任務去監控刪除,這樣會耗盡伺服器資源。

預設是每100ms檢測一次,遇到過期的key則進行刪除,這裡的檢測也不是順序檢測,而是隨機檢測。

另外為了防止有漏網之魚,例如在100ms檢查的中間間隙,某個key過期,但同時key訪問又進來了,這時觸發 惰性刪除策略 redis會在讀取時判斷是否已經過期,過期則直接刪除。

記憶體淘汰是指一部分key在記憶體不夠用的情況下會被Redis自動刪除,從而會出現從緩存中查不到數據的情況。

例如我們的伺服器記憶體為2G、但是隨著業務的發展緩存的數據已經超過2G了。但是這並不能影響我們程式的運行。所以redis會從key列表中抽取一定的熱度低的數據進行淘汰策略,騰出空間存儲新的key

 

...持續更新

 

github: https://github.com/294678380/redis-lerning


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 恢復內容開始 設計表的時候 1. 不同的表涉及同一個公共意義欄位不要使用不同的數據類型(可能導致索引不可用,查詢結果有偏差) 2. 不要一張表放太多的數據 主表20~30個欄位 其他表最好不超過20個 3. 最好不要有為Null的列,原因:https://mp.weixin.qq.com/s/U4R ...
  • 公司在Azure的Iaas虛擬機上部署有好幾台MySQL資料庫,至於沒有選擇Azure Database for MySQL,是因為預算有限(錢不夠啊!說多了也是淚,坑的還是DBA自己)。選擇了Iaas的話,DBA就必須考慮離線備份(offline backup),以預防災難性故障出現。我們選擇將歷... ...
  • 分享一篇關於實時流式計算的經典文章,這篇文章名為Streaming 101: The world beyond batch 那麼流計算如何超越批處理呢? 從這幾個方面說明:實時流計算系統,數據處理模式,還有大數據的未來。 一、實時流式計算系統 實時流式計算的意義: 1、企業渴望獲得更及時的數據,實時 ...
  • 所需補丁及高版本opatch上傳後將p6880880_112000_Linux-x86-64.zip解壓覆蓋$ORACLE_HOME/OPatch目錄即可[oracle@localhost OPatch]$ ./opatch versionOPatch Version: 11.2.0.3.16OPa... ...
  • 1.Redo Log The redo log is a disk-based data structure used during crash recovery to correct data written by incomplete transactions. During normal op ...
  • 轉載、節選於 https://dev.mysql.com/doc/refman/8.0/en/innodb-doublewrite-buffer.html The doublewrite buffer is a storage area located in the system tablespac ...
  • 概念介紹 CDH概覽 CDH是Apache Hadoop和相關項目的最完整、最受測試和最流行的發行版。CDH提供Hadoop的核心元素 可伸縮存儲和分散式計算 以及基於web的用戶界面和重要的企業功能。CDH是Apache許可的開放源碼,是唯一提供統一批處理、互動式SQL和互動式搜索以及基於角色的訪 ...
  • 本數據源來自 https://www.kafan.cn/edu/922556.html 目的為了備忘 把原來的sql server 2005直接裝成了2012,然後在建立鏈接伺服器鏈接一臺sql server 2000的伺服器時,報錯信息大概是“SQL Server Native Client 11 ...
一周排行
    -Advertisement-
    Play Games
  • Timer是什麼 Timer 是一種用於創建定期粒度行為的機制。 與標準的 .NET System.Threading.Timer 類相似,Orleans 的 Timer 允許在一段時間後執行特定的操作,或者在特定的時間間隔內重覆執行操作。 它在分散式系統中具有重要作用,特別是在處理需要周期性執行的 ...
  • 前言 相信很多做WPF開發的小伙伴都遇到過表格類的需求,雖然現有的Grid控制項也能實現,但是使用起來的體驗感並不好,比如要實現一個Excel中的表格效果,估計你能想到的第一個方法就是套Border控制項,用這種方法你需要控制每個Border的邊框,並且在一堆Bordr中找到Grid.Row,Grid. ...
  • .NET C#程式啟動閃退,目錄導致的問題 這是第2次踩這個坑了,很小的編程細節,容易忽略,所以寫個博客,分享給大家。 1.第一次坑:是windows 系統把程式運行成服務,找不到配置文件,原因是以服務運行它的工作目錄是在C:\Windows\System32 2.本次坑:WPF桌面程式通過註冊表設 ...
  • 在分散式系統中,數據的持久化是至關重要的一環。 Orleans 7 引入了強大的持久化功能,使得在分散式環境下管理數據變得更加輕鬆和可靠。 本文將介紹什麼是 Orleans 7 的持久化,如何設置它以及相應的代碼示例。 什麼是 Orleans 7 的持久化? Orleans 7 的持久化是指將 Or ...
  • 前言 .NET Feature Management 是一個用於管理應用程式功能的庫,它可以幫助開發人員在應用程式中輕鬆地添加、移除和管理功能。使用 Feature Management,開發人員可以根據不同用戶、環境或其他條件來動態地控制應用程式中的功能。這使得開發人員可以更靈活地管理應用程式的功 ...
  • 在 WPF 應用程式中,拖放操作是實現用戶交互的重要組成部分。通過拖放操作,用戶可以輕鬆地將數據從一個位置移動到另一個位置,或者將控制項從一個容器移動到另一個容器。然而,WPF 中預設的拖放操作可能並不是那麼好用。為瞭解決這個問題,我們可以自定義一個 Panel 來實現更簡單的拖拽操作。 自定義 Pa ...
  • 在實際使用中,由於涉及到不同編程語言之間互相調用,導致C++ 中的OpenCV與C#中的OpenCvSharp 圖像數據在不同編程語言之間難以有效傳遞。在本文中我們將結合OpenCvSharp源碼實現原理,探究兩種數據之間的通信方式。 ...
  • 一、前言 這是一篇搭建許可權管理系統的系列文章。 隨著網路的發展,信息安全對應任何企業來說都越發的重要,而本系列文章將和大家一起一步一步搭建一個全新的許可權管理系統。 說明:由於搭建一個全新的項目過於繁瑣,所有作者將挑選核心代碼和核心思路進行分享。 二、技術選擇 三、開始設計 1、自主搭建vue前端和. ...
  • Csharper中的表達式樹 這節課來瞭解一下表示式樹是什麼? 在C#中,表達式樹是一種數據結構,它可以表示一些代碼塊,如Lambda表達式或查詢表達式。表達式樹使你能夠查看和操作數據,就像你可以查看和操作代碼一樣。它們通常用於創建動態查詢和解析表達式。 一、認識表達式樹 為什麼要這樣說?它和委托有 ...
  • 在使用Django等框架來操作MySQL時,實際上底層還是通過Python來操作的,首先需要安裝一個驅動程式,在Python3中,驅動程式有多種選擇,比如有pymysql以及mysqlclient等。使用pip命令安裝mysqlclient失敗應如何解決? 安裝的python版本說明 機器同時安裝了 ...