天天看點

資料庫緩存政策

資料庫

指持久化資料庫,如

  • mysql
  • mongodb

緩存

指記憶體型的資料存儲,如

  • redis
  • memcached

一個良好的緩存政策需兼顧

  • 命中率
  • 緩存資料與資料庫資料的一緻性

對命中率的兼顧

多大的命中率是好的?

用數學知識來分析這個問題,先設定幾個關鍵的參數

  • T(c):讀一次緩存所需時間
  • T(d):讀一次資料庫所需時間
  • G:緩存命中率

一次資料讀取所需的時間的期望值為:

T(c)*G + (T(c)+T(d))*(-G)
           

增加資料庫緩存的目标為提高資料讀取速度,可以歸結為一個表達式

T(c)*G + (T(c)+T(d))*(-G) < T(d)
           

等同于

T(c) - T(d)*G < 
           

讀取速度提升的比值為

(T(d)*G - T(c))/T(d)
           

假如,T(d)=50ms,T(c)=10ms,G=0.6,讀取速度提升比值為

(* - )/ = 
           

化為百分比也就是40%。

假如,T(d)=50ms,T(c)=10ms,G的值必須大于

G = T(c)/T(d) = 
           

才能期望讀取速度得到提升。

可以看出

加入緩存不一定能夠提升讀取性能,這取決于緩存讀取速度、資料庫讀取速度以及緩存的命中率。

對資料一緻性的兼顧

這裡隻探讨對資料一緻性有高要求的場景,可以總結為

隻要資料庫有更新,就要使和已更新資料相關的所有緩存失效。

最終的政策

先從緩存的key入手

為了確定緩存資料的唯一性,key的字首可以是這樣的

<server_name>:<db_name>:<table_name>
           
  • server_name 伺服器名稱
  • db_name 資料庫名稱
  • table_name 表名稱

還要區分簡單查詢與複雜查詢

  • 簡單查詢:根據主鍵進行的查詢
  • 複雜查詢:除簡單查詢外的都是複雜的

key字首加上查詢類型

<server_name>:<db_name>:<table_name>:<query_type>
           

舉個例子

對app伺服器上的資料庫做簡單查詢

對應的緩存key

app:homestead:users:simple:{,,}
           

複雜查詢

對應的緩存key

app:homestead:users:complex:{select * from homestead.users where age > }
           

緩存失效政策

假定sql-1更新了id為3,4,5的資料庫記錄

#sql-1
update homestead.users set age=age+ where age>
           

更新完成後需失效的緩存

  • 緩存類型為複雜查詢的
  • 緩存類型為簡單查詢的,且id包含3、4、5的

緩存選型

以上的政策需要緩存支援key的模糊查詢,例如查詢id包含3的類型為簡單查詢的緩存key。

Redis自1.0.0版本開始支援根據模式查詢緩存中的key,例如

KEYS app:homestead:users:simple:{*,,*}
           

可以看出,1.0.0及以上版本的Redis滿足該政策的需求。

不夠幸運的是,memcached暫時不滿足需求。