當前位置:網站首頁>淺析緩存的讀寫策略
淺析緩存的讀寫策略
2022-07-23 07:11:05【軟件開發隨心記】
前言
提起緩存,我們首先想到緩存是一種存儲數據的組件,它的作用是讓對數據的請求能更快地返回。
我們一般會把不經常改變而且又需要快速訪問的數據進行緩存,常用的做法是將這些數據寫進內存中,當需要訪問的時候能快速地返回需要的結果。
實際上,凡是速度相差較大的兩種硬件之間,用於協調兩者數據傳輸差异的結構,都可以稱為緩存。
在日常開發過程中,我們就經常將數據放在的本地緩存(escache)或者外部緩存(Redis)中。
緩存的讀寫策略
緩存聽起來很簡單,無非就是優先讀緩存,緩存不命中就從數據庫中查詢,查詢到了再寫回緩存。但實際上,根據不同業務場景,緩存的讀寫策略也是不同。我們就以最常見的緩存+數據庫的場景來分析。
Cache Aside(旁路緩存)策略
Cache Aside是我們使用最多的策略,緩存不和數據庫直接進行交互,而是由應用程序來同時和緩存以及數據庫打交道。Cache Aside的名字正體現了這個模式,Cache在應用的一旁(aside)。
讀數據時
- 程序需要判斷緩存中是否已經存在數據
- 當緩存中已經存在數據(也就是緩存命中,cache hit),則直接從緩存中返回數據
- 當緩存中不存在數據(也就是緩存未命中,cache miss),則先從數據庫裏讀取數據,並且存入緩存,然後返回數據
寫數據時
- 先更新數據庫
- 再删除緩存中對應的數據
Read-Write Through (讀寫穿透)策略
Read/Write Through Pattern中服務端把緩存視為主要數據存儲,從中讀取數據並將數據寫入其中。緩存服務負責將此數據讀取和寫入 DB,從而减輕了應用程序的職責。
讀數據時 (Read Through)
- 從緩存中讀取數據,讀取到就直接返回 。
- 讀取不到的話,則由緩存組件先從數據庫加載,寫入到緩存後返回響應。
寫數據時 (Write Through)
- 先查緩存,緩存中不存在,直接更新數據庫。
- 緩存命中,則先更新緩存,然後緩存服務自己更新數據庫(同步更新緩存和數據庫)
在 Cache Aside下,發生讀請求的時候,如果 cache 中不存在對應的數據,是由客戶端自己負責把數據寫入 cache,而 Read-Through策略則是緩存服務自己來寫入緩存的,這對客戶端是透明的。
Read/Write Through策略的特點是由緩存節點而非用戶來和數據庫打交道,在我們開發過程中,這種策略比較少使用,原因在於我們一般使用的緩存組件(Redis或者Memcached)都不提供寫入數據庫的功能。只有本地緩存Guava Cache中的Loading Cache有Read Through策略的影子。
可以看出,由於Write Through寫數據時需要同時更新數據庫,對於性能會有比較大的影響。那麼我們可不可以异步更新數據庫呢?這就是接下來的Write Back策略。
Write-Back(异步緩存寫入)策略
Write-Back策略和Read-Write Through策略的共同點在於兩者都是由緩存服務來負責緩存和數據庫的讀寫。
不同點在於Write-Back將緩存作為可靠的數據源,每次都只寫入緩存,而寫入數據庫則采用异步的方式,比如當數據要被移除出緩存的時候再存儲到數據庫或者一段時間之後批量更新數據庫。
優點:在於讀寫速度非常快,因為都是從緩存中直接讀取和寫入。對於服務中數據庫不可用有一定的容忍度,當數據庫不可用時,也能正常處理結果,待數據庫恢複後再重新更新數據。同時也降低了數據庫壓力,寫數據庫操作可以放在業務流量較低的時候進行。
缺點:有數據丟失的風險,如果緩存服務掛掉而數據沒有及時寫入數據庫中,則數據會丟失。
適合場景: 數據經常變化又對數據一致性要求沒那麼高的場景,比如瀏覽量、點贊量
總結
這三種緩存讀寫策略各有優劣,需要我們根據具體的業務場景選擇更適合的。如果讀多寫少,且對於數據一致性要求高,可以使用Cache Aside策略。如果寫多讀少,且對於數據一致性要求不高,可以Read-Write Through或者Write-Back策略。
Ryan.ou
版權聲明
本文為[軟件開發隨心記]所創,轉載請帶上原文鏈接,感謝
https://cht.chowdera.com/2022/204/202207221942219785.html
邊欄推薦
猜你喜歡
隨機推薦
- TypeScript
- 開源工具 SAP UI5 Tools 介紹
- Lark教程指南
- 網絡安全——使用Evil Maid物理訪問安全漏洞進行滲透
- 網絡安全—使用Ubuntu本地提權漏洞進行滲透及加固
- JWT工具類編寫
- Day1 Running Sum of 1d Array/Find Pivot Index/用兩個棧實現隊列
- socket編程之常用api介紹與socket、select、poll、epoll高並發服務器模型代碼實現
- 深入研究容器隊列
- Bean的初始化回調方法和釋放資源的回調方法
- 爬蟲數據保存到mysql數據庫
- 通過SQL進行數據分發
- Redis 分布式鎖如何自動續期(經典解决方案)
- 虹科動態 | cippe2022即將舉辦,報名火熱進行中
- Kotlin之匿名內部類(object: xxxx)
- 面試突擊:truncate、delete和drop的6大區別
- Ubuntu安裝Docker及Docker的基本命令 安裝MySQL
- LeetCode--棧和隊列篇
- etcd 集群部署
- TCP/IP協議族中需要必知必會的十大問題
- 【STM32學習】(21)STM32實現步進電機
- 繪制帶有查詢條件變量的table【grafana】
- 認識接口
- LABVIEW:創建一個VI
- 界面開發框架DevExtreme Gantt控件——可導出PDF、排序任務
- MySQL命令行導出導入數據庫和數據錶
- 有數大數據基礎平臺之智能運維平臺EasyEagle介紹:集群隊列篇
- 你記住JS中offsetWidth、clientWidth、width、scrollWidth、clientX、screenX、offsetX、pageX嗎?
- 【Azure 事件中心】Azure Event Hub 新功能嘗試 -- 异地灾難恢複 (Geo-Disaster Recovery)
- unity 照片牆
- 影響持續交付的因素有哪些?
- 【快速上手教程7】瘋殼·開源編隊無人機-地面站上比特機的使用和介紹
- Redis配置詳解
- docker安裝MySQL、redis
- 【嵌入式】限幅電路和鉗比特電路 利用二極管的單向導電性
- [知識圖譜]cql與py2neo學習筆記
- C語言學習
- 列轉行與數據集連接在業務場景的組合應用
- MySQL5.6/ 5.7 SSL配置
- 【深度學習】損失函數(平均絕對誤差,均方誤差,平滑損失,交叉熵,帶權值的交叉熵,骰子損失,FocalLoss)