一、什么是緩存粒度
下面這個圖是很多項目關于緩存使用最常用的一個抽象,那么我們假設storage層為mysql, cache層為redis。

假如我現在需要對視頻的信息做一個緩存,也就是需要對select * from video where id=?的每個id在redis里做一份緩存,這樣cache層就可以幫助我抗住很多的訪問量(注:這里不討論一致性和架構等等問題,只討論緩存的粒度問題)。
我們假設視頻表有100個屬性(這個真有,有些人可能難以想象),那么問題來了,需要緩存什么維度呢,也就是有兩種選擇吧:
Java代碼

- (1)cache(id)=select * from video where id=#id
- (2)cache(id)=select importantColumn1, importantColumn2 .. importantColumnN from video where id=#id
其實這個問題就是緩存粒度問題,我們在緩存設計應該佮預估和考慮呢?下面我們將從通用性、空間、代碼維護三個角度進行說明。
二、全部數據和部分數據比較
1. 兩者的特點是顯而易見的:
數據類型 | 通用性 | 空間占用(內存空間 + 網絡碼率) | 代碼維護 |
全部數據 | 高 | 大 | 簡單 |
部分數據 | 低 | 小 | 較為復雜 |
2. 通用性:
如果單從通用性上看,全部數據是最優秀的,但是有個問題就是是否有必要緩存全部數據,認為以后會有這樣的需求,但是從經驗看除了非常重要的信息,那些不重要的字段基本不會在需求里出現,也就是說這種通用性 通常都是想象出來的。太多人覺得通用性是最重要的。vid拿一些基本信息,會想專輯明星。。要不要用通用性高的,于是加了全局的,通用性很重要,但是要想清楚。
3. 空間占用:
很顯然,緩存全部數據,會占用大量的內存,有人會說,不就費一點內存嗎,能有多少錢?而且已經有人習慣了把緩存當做下水道來使用,什么都框框的往里面放,但是我這里要說內存并不是免費的,可以說是很珍貴的資源。instagram21->4G的例子就說明了這個道理,好的程序員可以幫助公司節約大量的資源。
而且單個cache(id)也帶來兩個問題:序列化的開銷和網絡流量的開銷(QPS,百倍),都是無容忽視的。
4. 代碼維護:
代碼維護性,全部數據的優勢更加明顯,而部分數據一旦要加新字段就會修改代碼,而且還需要對原來的數據進行刷新。
三、總結:
緩存粒度問題是一個容易被忽視的問題,如果使用不當,可能會造成很多無用空間的浪費,可能會造成網絡帶寬的浪費,可能會造成代碼通用性較差等情況,必須學會綜合數據通用性、空間占用比、代碼維護性 三點評估取舍因素權衡使用。