后臺系統可擴展性學習筆記(十三)緩存

文章目錄

  • 在哪兒加緩存
  • 緩存什么內容
    • 緩存原始查庫結果
    • 緩存數據對象
  • 怎么查詢緩存結果
    • 預留緩存模式
    • 直讀模式
    • 直寫模式
    • 回寫式緩存
    • 繞寫式緩存
    • 提前刷新模式
  • 緩存滿了如何處理
  • 參考

讀寫分離、分庫分表、反范式化、采用 NoSQL……如果這些擴展手段全都上了,數據響應依舊越來越慢,還有什么解決辦法嗎?
有,加緩存。 利用緩存層來吸收不均勻的負載和流量高峰

在哪兒加緩存

理論上,在數據層之前的任意一層加緩存都能夠阻擋流量,減少最終抵達數據庫的操作請求:
在這里插入圖片描述
按緩存所處位置分為 4 種:

  • 客戶端緩存:包括HTTP 緩存、瀏覽器緩存等
  • Web 緩存:例如CDN、反向代理服務等
  • 應用層緩存:例如Memcached、Redis等鍵值存儲
  • 數據庫緩存:一些數據庫提供了內置的緩存支持,比如查詢緩存(query cache)

為了減輕數據庫的負載,我們在應用程序和數據存儲之間加個鍵值存儲作為緩沖層:通過內存中緩存的數據來響應一部分請求,而不必實際執行查庫操作,從而提升數據響應速度。

緩存什么內容

  • Cached Database Queries:緩存原始查庫結果
  • Cached Objects:緩存應用程序中的數據模型,比如重新組裝過的數據集,或者整個數據模型類實例

緩存原始查庫結果

根據查詢語句生成key,將查庫結果緩存起來,例如:

key = "user.%s" % user_id
user_blob = memcache.get(key)
if user_blob is None:user = mysql.query("SELECT * FROM users WHERE user_id=\"%s\"", user_id)if user:memcache.set(key, json.dumps(user))return user
else:return json.loads(user_blob)

這種模式的主要缺陷在于難以處理緩存過期,因為數據與key(即查詢語句)之間并沒有明確的關聯,數據發生變化后,很難精確地刪掉緩存中的所有相關條目。試想,一個單元格發生變化,會影響哪些查詢語句?
盡管如此,這仍然是最常用的緩存模式,因為可以做出妥協,比如:

  • 只緩存與查詢語句有直接關聯的數據,排序、統計、篩選之類的計算結果統統都不存了
  • 不求精確,把所有可能受影響的緩存條目都刪掉

緩存數據對象

另一種思路是將應用程序中的數據模型對象緩存起來,這樣原始數據與緩存之間就有了邏輯關聯,從而輕松解決緩存更新的難題。
無論數據是如何查詢,如何加工轉換的,只把最終得到的數據模型對象緩存起來,原始數據發生變化時,直接把相應的數據對象整個移除。對應用程序而言,數據對象比原始數據更容易管理和維護,因此,建議緩存數據對象,而不是原始數據。

怎么查詢緩存結果

常見的緩存數據訪問策略有 6 種:

  • Cache-aside/Lazy loading:預留緩存
  • Read-through:直讀式
  • Write-through:直寫式
  • Write-behind/Write-back:回寫式
  • Write-around:繞寫式
  • Refresh-ahead:刷新式

預留緩存模式

在這里插入圖片描述
數據請求優先走緩存,未命中緩存時才查庫,并把結果緩存起來,所以緩存是按需的(Lazy loading),只有實際訪問過的數據才會被緩存起來。緩存與數據庫之間沒有直接關系(緩存位于一旁,所以叫 Cache-aside),由應用程序將需要的數據從數據庫中讀出并填充到緩存中。
主要問題在于:

  • 未命中緩存時需要 3 步,延遲不容忽視(對于冷啟動可以手動預熱)
  • 緩存可能會變舊(一般通過設置 TTL 來強制更新)

直讀模式

在這里插入圖片描述
直讀模式下,緩存擋在數據庫之前,應用程序不與數據庫直接交互,而是直接從緩存中讀取數據。
未命中緩存時,由緩存負責查庫,并自己緩存起來。與預留緩存唯一的區別在于查庫的工作由緩存來完成,而不是應用程序。

直寫模式

在這里插入圖片描述
類似于直讀模式,緩存也擋在數據庫之前,數據先寫到緩存,再寫入數據庫。
也就是說,所有寫操作必須先經過緩存。
一般與直讀式緩存相結合,雖然寫操作多過一層緩存(存在額外的延遲),但保證了緩存數據的一致性(避免緩存變舊)。此時,緩存就像數據庫的代理,讀寫都走緩存,緩存再查庫或將寫操作同步到數據庫。

回寫式緩存

在這里插入圖片描述
與直寫式唯一的區別在于異步寫入數據庫,進而允許批處理以及寫操作合并。同樣能夠與直讀式緩存結合使用,而且不存在直寫式中寫操作的性能問題,但僅保證最終一致性。

繞寫式緩存

所謂繞寫式緩存就是寫操作不經過(繞過)緩存,由應用程序直接寫入數據庫,僅緩存讀操作。可與預留緩存或直讀緩存結合使用:
在這里插入圖片描述

提前刷新模式

在這里插入圖片描述
提前刷新,在緩存過期之前,自動刷新(重新加載)最近訪問過的條目。甚至可以通過預加載來減少延遲,但如果預測不準反而會導致性能下降。

緩存滿了如何處理

當然,緩存空間是極其有限的,所以還要有逐出策略(Eviction Policy),從緩存中剔除一些不太可能用到的條目,常用策略如下:

  • LRU(Least Recently Used):最常用的一種策略,根據程序運行時的局部性原理,在一段時間內,大概率訪問相同的數據,所以將最近沒有用到的數據剔除出去
  • LFU(Least Frequently Used):根據使用頻率,將最不常用的數據剔除出去
  • MRU(Most Recently Used):在有些場景下,需要刪掉最近用過的條目
  • FIFO(First In, First Out):先進先出,剔除最早訪問過的數據

參考

http://www.ayqy.net/blog/caching/

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/376564.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/376564.shtml
英文地址,請注明出處:http://en.pswp.cn/news/376564.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

[linux]gdb調試

使用gdb可以在命令行方便地調試,并且能以命令程序的方式調試源代碼。 常用命令簡寫print-p,step-s,next-n 進入gdb //方式一 gdb test//test 為可執行文件,使用-g編譯得到 //方式二 gdb -q //不顯示版權信息 file test //file命令打開文件 退出gdb quit …

后臺系統可擴展性學習筆記(十四)異步機制與MQ

對于 Web 服務而言,提升可擴展性的主要途徑是將耗時的同步工作改成異步處理,從而允許將這些工作“外包”給多個 Worker 去做,或者提前完成能夠預知的部分。 異步機制與可擴展性之間的關系需要從(異步)并行處理的優勢說…

RegisterClientScriptBlock與 RegisterStartupScript區別

Page.ClientScript.RegisterClientScriptBlock而用Page.ClientScript.RegisterStartupScript是因為:RegisterStartupScript 把script放置在ASP.NET page的底部,而RegisterClientScriptBlock把script放置在ASP.NET page的頂部,用RegisterClien…

【Web后端筆記】SQL Server與java數據類型對應

編號數據庫類型JDBC類型JDBC索引描述1intjava.lang.Integer4 2varcharjava.lang.String12 3charjava.lang.String1 4ncharjava.lang.String1 5nvarcharjava.lang.String12 6textjava.lang.String-1 7ntextjava.lang.String-1 8tinyintjava.lang.Integer-6 9intjava.lang.Intege…

后臺系統可擴展性學習筆記

整理了一下筆記目錄,將以前學習的一些知識串聯起來了,比如cdn、負載均衡、中間件,以前只是各自了解了一點,現在大概理清了后臺系統設計中他們各自的作用。 后臺系統可擴展性學習筆記(一)概要 后臺系統可擴展…

TFS 強制刪除鎖定文件(數據庫)

TFS:TFS2010 VS:VS2012 OS:Windows2008 DB:Sqlserver2008 R2 我們在團隊開發當中,版本控制是一個不可忽略的工具。我們團隊使用的是TFS2010這個版本控制器。 但在團隊實際協作開發當中,團隊成員難免有電腦損壞或人員離職情況&…

【轉】Java:String、StringBuffer和StringBuilder的區別

1 String String:字符串常量,字符串長度不可變。Java中String是immutable(不可變)的。 String類的包含如下定義: [java]view plaincopy /** The value is used for character storage. */ private final char value[]…

Linux中exit與_exit的區別

在exit,_exit的區別 - exit()與_exit()函數的區別(Linux系統中)2012-03-20 15:19:53 分類: LINUX 注:exit()就是退出,傳入的參數是程序退出時的狀態碼,0表示正常退出,其他表示非正常退出&…

光標閃爍問題的解決辦法

在調用Windows API函數SetCursor設置光標時,可能會碰到閃爍的問題:移動鼠標,光標在Class Cursor(即注冊窗口類時指定的Cursor)與預設Cursor之間閃爍。 在MSDN上有關SetCursor函數的備注中強調,如果Class Cursor非空,那…

視頻編解碼基礎

文章目錄前戲編解碼技術流程主流視頻編碼標準視頻傳輸面臨的問題視頻傳輸差錯控制視頻傳輸Qos質量保證參數人類視覺系統HVS 以及相應編碼措施正餐編碼層次與碼流結構PB幀編碼IBBP序列編碼結構圖像編碼結構條帶編碼結構宏塊編碼結構塊編碼結構預測技術碼率控制實例H264前戲 編解…

XShell 屏幕鎖定的恢復方法(Ctrl+Q)

操作XShell過程中很多時間大家會習慣性的按CtrlS進行保存. CtrlS在XShell的作用是屏幕鎖定,很多朋友會無法操作,會直接把窗口關閉。 解決方法: 快捷鍵 CtrlQ 即能完成解鎖!轉載于:https://www.cnblogs.com/liangle/p/3173475.html

adb端口被占用

程序不能執行,kill掉任務管理器里面adb服務,重新連接設備仍然有錯 查到可能是adb端口被占用 查看adb用的是哪個端口:C:\Users\wanglin>adb nodaemon server 查看誰占用了這個端口:C:\Users\wanglin>netstat -ano | findstr …

實時語音通訊丟包補償技術

文章目錄基于發送端丟包補償技術原理與媒體無關的前向差錯糾正媒體相關前向差錯糾正交織技術基于接受端丟包補償技術基于插入方法基于插值方法基于重構的方法應用建議非交互式交互式拓展閱讀參考丟包補償技術可以分為兩類:基于發送端補償、基于接受端補償 基于發送…

取得裝置可以顯示頁面的寬度

利用html中的div元素取得<div id"divGetWidth" width100%></div>Jquery:var width$(#divGetWidth).width(); //獲取元素寬度 Javascript:var objdocument.getElementById(divGetWidth);var width obj.offsetWidth轉載于:https://www.cnblogs.…

Xcode添加靜態庫以及編譯選項配置常見問題

本文轉載至 http://www.cnblogs.com/Quains/archive/2013/08/22/3276425.html 一,Xcode編譯出現Link錯誤,出現"duplicate symbols for architecture i386 clang"提示.問題:鏈接時,項目有重名文件.解決:根據錯誤提示,做如下檢查:1.Taraget->Build Settings->Li…

關于并發概念的一些筆記

目錄1、基于鎖的并發數據結構1、并發計數器2、懶惰計數器3、并發鏈表4、并發隊列5、并發散列表總結2、條件變量使用&#xff08;POSIX&#xff09;生產者/消費者 &#xff08;有界緩沖區問題&#xff09;覆蓋條件擴展3、信號量使用二值信號量&#xff08;鎖&#xff09;0值信號…

MYSQL常見出錯代碼 mysql error number

1016錯誤&#xff1a;文件無法打開&#xff0c;使用后臺修復或者使用phpmyadmin進行修復。1044錯誤&#xff1a;數據庫用戶權限不足&#xff0c;請聯系空間商解決1045錯誤&#xff1a;數據庫服務器/數據庫用戶名/數據庫名/數據庫密碼錯誤&#xff0c;請聯系空間商檢查帳戶。105…

建立apk定時自動打包系統第三篇——代碼自動更新、APP自動打包系統

我們的思路是每天下班后團隊各成員在指定的時間&#xff08;例如下午18:30&#xff09;之前把各自的代碼上傳到SVN&#xff0c;然后服務器在指定的時間&#xff08;例如下午18:30&#xff09;更新代碼、執行ant 打包命令、最后將apk包存放在指定目錄&#xff08;或者上傳指定ft…

對于線程并發模型與事件并發模型的思考

這里將以對話的形式進行&#xff1a; A&#xff1a; 普通的線程是可以被其他線程中斷掉的&#xff0c;而基于select、epoll的事件處理函數實際上是不可以被其他事件&#xff08;線程&#xff09;中斷的。 我這個理解對嗎&#xff1f; B&#xff1a; 圖片里的應該是對是否…

Cache 總結

這一文&#xff0c;讓我們分析一下&#xff0c;《淺談 Cache》 一文中的奇怪現象&#xff0c;事實上如今來看也并不奇怪了。在什么情況下 r1 和 r2 都為 0 呢&#xff1f;細致看代碼&#xff0c;你會發現&#xff0c;兩個線程分別被執行在不同的 CPU 核上&#xff0c;而且在線程…