前言
部門培訓(xùn)的時(shí)候讓我講緩存,然而平時(shí)用緩存也比較少,這邊特意整理下相關(guān)的資料,僅概念性的,不深入
一、什么是緩存
緩存就是數(shù)據(jù)交換的緩沖區(qū),位于速度相差較大的兩種硬件/軟件之間的,用于協(xié)調(diào)兩者數(shù)據(jù)傳輸速度差異的結(jié)構(gòu)。
軟件中的緩存就是指,將會(huì)被頻繁使用的數(shù)據(jù)保存到內(nèi)存上,加快讀取速度。
二、為什么要使用緩存
- 減少交互的通訊量——緩存數(shù)據(jù)能有效減少在進(jìn)程和機(jī)器間的傳輸量
- 降低系統(tǒng)中的處理量——減少處理次數(shù)
- 降低需要做的磁盤訪問次數(shù)——比如緩存在內(nèi)存中的數(shù)據(jù)
IO的讀寫速度相對(duì)內(nèi)存來說是比較慢的,通常一個(gè)web應(yīng)用的瓶頸就出現(xiàn)在磁盤IO的讀寫上。
一般情況下,一個(gè)網(wǎng)站或者應(yīng)用的形式是這樣的,用戶的請(qǐng)求通過用戶層來到業(yè)務(wù)層,業(yè)務(wù)層再從數(shù)據(jù)層獲取數(shù)據(jù),返回給用戶層。在用戶量和數(shù)據(jù)量不大的情況下,這個(gè)系統(tǒng)運(yùn)行得很順暢。但是隨著用戶量越來越大,數(shù)據(jù)庫中的數(shù)據(jù)越來越多,系統(tǒng)的響應(yīng)速度就越來越慢。系統(tǒng)的瓶頸一般都在數(shù)據(jù)庫訪問上。

那么,如果我們?cè)趦?nèi)存中建立一個(gè)存儲(chǔ)區(qū),將數(shù)據(jù)緩存起來,當(dāng)瀏覽器端由請(qǐng)求到達(dá)的時(shí)候,直接從內(nèi)存中獲取相應(yīng)的數(shù)據(jù),這樣一來可以降低服務(wù)器的壓力,二來,可以提高請(qǐng)求的響應(yīng)速度,提升用戶體驗(yàn)。
綜上,使用緩存是為了提高系統(tǒng)運(yùn)行速度,將用戶頻繁訪問的內(nèi)容存放在訪問速度快的地方,來提高系統(tǒng)的響應(yīng)速度。
三、緩存的屬性
命中率
命中率是指請(qǐng)求緩存次數(shù)和緩存返回正確結(jié)果次數(shù)的比例,比例越高,就證明緩存的使用率越高。最大元素
緩存中可以存放得最大元素得數(shù)量,一旦緩存中元素?cái)?shù)量超過這個(gè)值,那么將會(huì)起用緩存清空策略,根據(jù)不同的場(chǎng)景合理的設(shè)置最大元素值往往可以一定程度上提高緩存的命中率,從而更有效的時(shí)候緩存。清空策略
- FIFO ,first in first out ,最先進(jìn)入緩存得數(shù)據(jù)在緩存空間不夠情況下被首先清理出去。
- LFU , Less Frequently Used ,一直以來最少被使用的元素會(huì)被被清理掉。這就要求緩存的元素有一個(gè)hit 屬性,在緩存空間不夠得情況下,hit 值最小的將會(huì)被清出緩存。
- LRU ,Least Recently Used ,最近最少使用的,緩存的元素有一個(gè)時(shí)間戳,當(dāng)緩存容量滿了,而又需要騰出地方來緩存新的元素的時(shí)候,那么現(xiàn)有緩存元素中時(shí)間戳離當(dāng)前時(shí)間最遠(yuǎn)的元素將被清出緩存。
四、哪些數(shù)據(jù)需要被緩存
查詢比較高的熱點(diǎn)數(shù)據(jù)、可以允許丟失的。
比如:平臺(tái)管理中的平臺(tái)配置、配置文件里的配置項(xiàng)、熱門文章、點(diǎn)贊、閱讀數(shù)等。
五、實(shí)現(xiàn)緩存的方式
java應(yīng)用的緩存分兩種,一是進(jìn)程內(nèi)緩存,就是使用java應(yīng)用的虛擬機(jī)內(nèi)存來進(jìn)行緩存;另一個(gè)是進(jìn)程外緩存,比如:redis。
相比較而言,進(jìn)程內(nèi)緩存比進(jìn)程外緩存快很多,而且編碼也簡(jiǎn)單;但是,進(jìn)程內(nèi)緩存的存儲(chǔ)量有限,使用的是java應(yīng)用虛擬機(jī)的內(nèi)存,而且每個(gè)應(yīng)用都要存儲(chǔ)一份,有一定的資源浪費(fèi)。進(jìn)程外緩存相比進(jìn)程內(nèi)緩存,會(huì)慢些,但是,存儲(chǔ)空間可以橫向擴(kuò)展,不受限制。
5.1 進(jìn)程內(nèi)緩存
Ehcache
Cacheonix
ASimpleCache
JBoss Cache
Voldemort
5.2 進(jìn)程外緩存
Redis
Mencached
六、ehcache
EhCache 是一個(gè)純Java的進(jìn)程內(nèi)緩存框架,具有快速、精干等特點(diǎn),是Hibernate中默認(rèn)的CacheProvider。
主要的特性有:
- 快速、簡(jiǎn)單,提供多種緩存策略
- 緩存數(shù)據(jù)有兩級(jí):內(nèi)存和磁盤,因此無需擔(dān)心容量問題
- 緩存數(shù)據(jù)會(huì)在虛擬機(jī)重啟的過程中寫入磁盤
- 可以通過RMI、可插入API等方式進(jìn)行分布式緩存
- 具有緩存和緩存管理器的偵聽接口
- 支持多緩存管理器實(shí)例,以一個(gè)實(shí)例的多個(gè)緩存區(qū)域
七、Redis
redis是一個(gè)遠(yuǎn)程內(nèi)存數(shù)據(jù)庫,可以存儲(chǔ)鍵(key)與5種不同類型的值(value)之間的映射,可以將存儲(chǔ)在內(nèi)存中的鍵值對(duì)數(shù)據(jù)持久化到硬盤,可以使用復(fù)制特性擴(kuò)展讀性能,還可以使用客戶端分片來擴(kuò)展寫性能。
主要的特性有:
- redis的數(shù)據(jù)完全存儲(chǔ)在內(nèi)存中,磁盤只用于持久性,所以redis的速度非???;
- redis擁有較為豐富的數(shù)據(jù)類型;
- redis的操作都是原子性的,所以在異步的時(shí)候也是安全的;
- redis可以將數(shù)據(jù)復(fù)制到任意數(shù)量的從機(jī)。
7.1 redis數(shù)據(jù)類型
| 結(jié)構(gòu)類型 | 結(jié)構(gòu)存儲(chǔ)的值 | 結(jié)構(gòu)的讀寫能力 |
|---|---|---|
| STRING | 可以是字符串、整數(shù)或者浮點(diǎn)數(shù) | 對(duì)整個(gè)字符串或者字符串的其中一部分執(zhí)行操作;對(duì)整數(shù)和浮點(diǎn)數(shù)執(zhí)行自增或者自減 |
| LIST | 一個(gè)鏈表,鏈表上的每個(gè)節(jié)點(diǎn)都包含了一個(gè)字符串 | 從鏈表的兩端推入或者彈出元素;根據(jù)偏移量對(duì)鏈表進(jìn)行修剪;讀取單個(gè)或者多個(gè)元素;根據(jù)值查找或者移除元素 |
| SET | 包含字符串的無序收集器,并且被包含的每個(gè)字符串都是獨(dú)一無二、各不相同的 | 添加、獲取、移除單個(gè)元素;檢查一個(gè)元素是否存在于集合中;計(jì)算交集、并集、差集;從集合里面隨機(jī)獲取元素 |
| HASH | 包含鍵值對(duì)的無序散列表 | 添加、獲取、移除單個(gè)鍵值對(duì);獲取所有鍵值對(duì) |
| ZSET | 字符串成員與浮點(diǎn)數(shù)分值之間的有序映射,元素的排列順序由分值的大小決定 | 添加、獲取、刪除單個(gè)元素;根據(jù)分值范圍或者成員來獲取元素 |
7.2 使用場(chǎng)景
STRING
String是最常用的一種數(shù)據(jù)類型,普通的key/value存儲(chǔ)都可以使用此類型。比如分布式系統(tǒng)下,用戶登錄信息的共享,使用userguid
| 鍵 | 值 |
|---|---|
| userid | token |
LIST
List就是鏈表,可以存儲(chǔ)有先后順序的數(shù)據(jù),比如:文章列表、最新消息。也可以基于此實(shí)現(xiàn)消息隊(duì)列。
| 鍵 | 值 |
|---|---|
| msglist | {msg1, msg2,...} |
SET
與list類似是一個(gè)列表的功能,特殊之處在于set是可以自動(dòng)排重的,當(dāng)你需要存儲(chǔ)一個(gè)列表數(shù)據(jù),又不希望出現(xiàn)重復(fù)數(shù)據(jù)時(shí),set是一個(gè)很好的選擇。比如:用戶關(guān)注
| 鍵 | 值 |
|---|---|
| userid | [followid1, followid2,...] |
HASH
存儲(chǔ)一些結(jié)構(gòu)化的數(shù)據(jù),比如:用戶信息
| 鍵 | 值 |
|---|---|
| userid | {"name":"n", "age":"20"} |
ZSET
sorted set的使用場(chǎng)景與set類似,區(qū)別是set不是自動(dòng)有序的,而sorted set可以通過用戶額外提供一個(gè)優(yōu)先級(jí)(score)的參數(shù)來為成員排序,并且是插入有序的,即自動(dòng)排序。當(dāng)你需要一個(gè)有序的并且不重復(fù)的集合列表,那么可以選擇sorted set數(shù)據(jù)結(jié)構(gòu),比如:文章熱度排行
| 鍵 | 值 |
|---|---|
| hot_article | [(id1, 20), (id2, 30),...] |
附錄
測(cè)試代碼:https://github.com/muyi911/px