首先講講緩存數據的處理流程是怎樣的?
為什么要用 Redis/為什么要用緩存?
主要是為了提升用戶體驗以及應對更多的用戶。
緩存的有點:
高性能 :
假如用戶第一次訪問數據庫中的某些數據的話,這個過程是比較慢,畢竟是從硬盤中讀取的。但是,如果說,用戶訪問的數據屬於高頻數據並且不會經常改變的話,那么我們就可以很放心地將該用戶訪問的數據存在緩存中。那就是保證用戶下一次再訪問這些數據的時候就可以直接從緩存中獲取了。操作緩存就是直接操作內存,所以速度相當快。換句話說內存比磁盤快
注意:要保持數據庫和緩存中的數據的一致性。 如果數據庫中的對應數據改變的之后,同步改變緩存中相應的數據!
高並發:
一般像 MySQL這類的數據庫的 QPS(QPS(Query Per Second):服務器每秒可以執行的查詢次數;) 大概都在 1w 左右(4核8g) ,但是使用 Redis 緩存之后很容易達到 10w+,甚至最高能達到30w+(就單機redis的情況,redis 集群的話會更高)。
直接操作緩存能夠承受的數據庫請求數量是遠遠大於直接訪問數據庫的,所以我們可以考慮把數據庫中的部分數據轉移到緩存中去,這樣用戶的一部分請求會直接到緩存這里而不用經過數據庫。進而,我們也就提高的系統整體的並發。
緩存可以用在哪里:
如下圖,緩存的使用可以出現在1~4的各個環節中,每個環節的緩存方案與使用各有特點
緩存的特征:
- 命中率
命中率=返回正確結果數/請求緩存次數,命中率問題是緩存中的一個非常重要的問題,它是衡量緩存有效性的重要指標。命中率越高,表明緩存的使用率越高。
- 最大元素(最大空間)
緩存中可以存放的最大元素的數量,一旦緩存中元素數量超過這個值(或者緩存數據所占空間超過其最大支持空間),那么將會觸發緩存啟動清空策略根據不同的場景合理的設置最大元素值往往可以一定程度上提高緩存的命中率,從而更有效的時候緩存。
- 清空策略
如上描述,緩存的存儲空間有限制,當緩存空間被用滿時,如何保證在穩定服務的同時有效提升命中率?這就由緩存清空策略來處理,設計適合自身數據特征的清空策略能有效提升命中率。常見的一般策略有:
-
- FIFO(first in first out)
先進先出策略,最先進入緩存的數據在緩存空間不夠的情況下(超出最大元素限制)會被優先被清除掉,以騰出新的空間接受新的數據。策略算法主要比較緩存元素的創建時間。在數據實效性要求場景下可選擇該類策略,優先保障最新數據可用。
-
- LFU(less frequently used)
最少使用策略,無論是否過期,根據元素的被使用次數判斷,清除使用次數較少的元素釋放空間。策略算法主要比較元素的hitCount(命中次數)。在保證高頻數據有效性場景下,可選擇這類策略。
-
- LRU(least recently used)
最近最少使用策略,無論是否過期,根據元素最后一次被使用的時間戳,清除最遠使用時間戳的元素釋放空間。策略算法主要比較元素最近一次被get使用時間。在熱點數據場景下較適用,優先保證熱點數據的有效性。
除此之外,還有一些簡單策略比如:
-
- 根據過期時間判斷,清理過期時間最長的元素;
- 根據過期時間判斷,清理最近要過期的元素;
- 隨機清理;
- 根據關鍵字(或元素內容)長短清理等。
緩存介質分類:
雖然從硬件介質上來看,無非就是內存和硬盤兩種,但從技術上,可以分成內存、硬盤文件、數據庫。
-
- 內存:將緩存存儲於內存中是最快的選擇,無需額外的I/O開銷,但是內存的缺點是沒有持久化落地物理磁盤,一旦應用異常break down而重新啟動,數據很難或者無法復原。
- 硬盤:一般來說,很多緩存框架會結合使用內存和硬盤,在內存分配空間滿了或是在異常的情況下,可以被動或主動的將內存空間數據持久化到硬盤中,達到釋放空間或備份數據的目的。
- 數據庫:前面有提到,增加緩存的策略的目的之一就是為了減少數據庫的I/O壓力。現在使用數據庫做緩存介質是不是又回到了老問題上了?其實,數據庫也有很多種類型,像那些不支持SQL,只是簡單的key-value存儲結構的特殊數據庫(如BerkeleyDB和Redis),響應速度和吞吐量都遠遠高於我們常用的關系型數據庫等。
緩存種類:
-
本地緩存:指的是在應用中的緩存組件,其最大的優點是應用和cache是在同一個進程內部,請求緩存非常快速,沒有過多的網絡開銷等,在單應用不需要集群支持或者集群情況下各節點無需互相通知的場景下使用本地緩存較合適;同時,它的缺點也是應為緩存跟應用程序耦合,多個應用程序無法直接的共享緩存,各應用或集群的各節點都需要維護自己的單獨緩存,對內存是一種浪費。
-
分布式緩存:指的是與應用分離的緩存組件或服務,其最大的優點是自身就是一個獨立的應用,與本地應用隔離,多個應用可直接的共享緩存。
參考文檔:
https://tech.meituan.com/2017/03/17/cache-about.html
https://github.com/Snailclimb/JavaGuide/blob/master/docs/database/Redis/redis-all.md