前言
部門培訓(xùn)的時候讓我講緩存,然而平時用緩存也比較少,這邊特意整理下相關(guān)的資料愤钾,僅概念性的,不深入
一候醒、什么是緩存
緩存就是數(shù)據(jù)交換的緩沖區(qū)能颁,位于速度相差較大的兩種硬件/軟件之間的,用于協(xié)調(diào)兩者數(shù)據(jù)傳輸速度差異的結(jié)構(gòu)倒淫。
軟件中的緩存就是指伙菊,將會被頻繁使用的數(shù)據(jù)保存到內(nèi)存上,加快讀取速度敌土。
二镜硕、為什么要使用緩存
- 減少交互的通訊量——緩存數(shù)據(jù)能有效減少在進(jìn)程和機器間的傳輸量
- 降低系統(tǒng)中的處理量——減少處理次數(shù)
- 降低需要做的磁盤訪問次數(shù)——比如緩存在內(nèi)存中的數(shù)據(jù)
IO的讀寫速度相對內(nèi)存來說是比較慢的,通常一個web應(yīng)用的瓶頸就出現(xiàn)在磁盤IO的讀寫上返干。
一般情況下兴枯,一個網(wǎng)站或者應(yīng)用的形式是這樣的,用戶的請求通過用戶層來到業(yè)務(wù)層矩欠,業(yè)務(wù)層再從數(shù)據(jù)層獲取數(shù)據(jù)财剖,返回給用戶層。在用戶量和數(shù)據(jù)量不大的情況下癌淮,這個系統(tǒng)運行得很順暢躺坟。但是隨著用戶量越來越大,數(shù)據(jù)庫中的數(shù)據(jù)越來越多乳蓄,系統(tǒng)的響應(yīng)速度就越來越慢咪橙。系統(tǒng)的瓶頸一般都在數(shù)據(jù)庫訪問上。
那么,如果我們在內(nèi)存中建立一個存儲區(qū)美侦,將數(shù)據(jù)緩存起來店诗,當(dāng)瀏覽器端由請求到達(dá)的時候,直接從內(nèi)存中獲取相應(yīng)的數(shù)據(jù)音榜,這樣一來可以降低服務(wù)器的壓力,二來捧弃,可以提高請求的響應(yīng)速度赠叼,提升用戶體驗。
綜上违霞,使用緩存是為了提高系統(tǒng)運行速度嘴办,將用戶頻繁訪問的內(nèi)容存放在訪問速度快的地方,來提高系統(tǒng)的響應(yīng)速度买鸽。
三涧郊、緩存的屬性
命中率
命中率是指請求緩存次數(shù)和緩存返回正確結(jié)果次數(shù)的比例,比例越高,就證明緩存的使用率越高眼五。最大元素
緩存中可以存放得最大元素得數(shù)量妆艘,一旦緩存中元素數(shù)量超過這個值,那么將會起用緩存清空策略看幼,根據(jù)不同的場景合理的設(shè)置最大元素值往往可以一定程度上提高緩存的命中率批旺,從而更有效的時候緩存。清空策略
- FIFO 诵姜,first in first out 汽煮,最先進(jìn)入緩存得數(shù)據(jù)在緩存空間不夠情況下被首先清理出去。
- LFU 棚唆, Less Frequently Used 暇赤,一直以來最少被使用的元素會被被清理掉。這就要求緩存的元素有一個hit 屬性宵凌,在緩存空間不夠得情況下,hit 值最小的將會被清出緩存鞋囊。
- LRU ,Least Recently Used 瞎惫,最近最少使用的失暴,緩存的元素有一個時間戳,當(dāng)緩存容量滿了微饥,而又需要騰出地方來緩存新的元素的時候逗扒,那么現(xiàn)有緩存元素中時間戳離當(dāng)前時間最遠(yuǎn)的元素將被清出緩存。
四欠橘、哪些數(shù)據(jù)需要被緩存
查詢比較高的熱點數(shù)據(jù)矩肩、可以允許丟失的。
比如:平臺管理中的平臺配置、配置文件里的配置項黍檩、熱門文章叉袍、點贊、閱讀數(shù)等刽酱。
五喳逛、實現(xiàn)緩存的方式
java應(yīng)用的緩存分兩種,一是進(jìn)程內(nèi)緩存棵里,就是使用java應(yīng)用的虛擬機內(nèi)存來進(jìn)行緩存润文;另一個是進(jìn)程外緩存,比如:redis殿怜。
相比較而言典蝌,進(jìn)程內(nèi)緩存比進(jìn)程外緩存快很多,而且編碼也簡單头谜;但是骏掀,進(jìn)程內(nèi)緩存的存儲量有限,使用的是java應(yīng)用虛擬機的內(nèi)存柱告,而且每個應(yīng)用都要存儲一份截驮,有一定的資源浪費。進(jìn)程外緩存相比進(jìn)程內(nèi)緩存际度,會慢些侧纯,但是,存儲空間可以橫向擴展甲脏,不受限制眶熬。
5.1 進(jìn)程內(nèi)緩存
Ehcache
Cacheonix
ASimpleCache
JBoss Cache
Voldemort
5.2 進(jìn)程外緩存
Redis
Mencached
六、ehcache
EhCache 是一個純Java的進(jìn)程內(nèi)緩存框架块请,具有快速娜氏、精干等特點,是Hibernate中默認(rèn)的CacheProvider墩新。
主要的特性有:
- 快速贸弥、簡單,提供多種緩存策略
- 緩存數(shù)據(jù)有兩級:內(nèi)存和磁盤海渊,因此無需擔(dān)心容量問題
- 緩存數(shù)據(jù)會在虛擬機重啟的過程中寫入磁盤
- 可以通過RMI绵疲、可插入API等方式進(jìn)行分布式緩存
- 具有緩存和緩存管理器的偵聽接口
- 支持多緩存管理器實例,以一個實例的多個緩存區(qū)域
七臣疑、Redis
redis是一個遠(yuǎn)程內(nèi)存數(shù)據(jù)庫盔憨,可以存儲鍵(key)與5種不同類型的值(value)之間的映射,可以將存儲在內(nèi)存中的鍵值對數(shù)據(jù)持久化到硬盤讯沈,可以使用復(fù)制特性擴展讀性能郁岩,還可以使用客戶端分片來擴展寫性能。
主要的特性有:
- redis的數(shù)據(jù)完全存儲在內(nèi)存中,磁盤只用于持久性问慎,所以redis的速度非称继快;
- redis擁有較為豐富的數(shù)據(jù)類型如叼;
- redis的操作都是原子性的冰木,所以在異步的時候也是安全的;
- redis可以將數(shù)據(jù)復(fù)制到任意數(shù)量的從機笼恰。
7.1 redis數(shù)據(jù)類型
結(jié)構(gòu)類型 | 結(jié)構(gòu)存儲的值 | 結(jié)構(gòu)的讀寫能力 |
---|---|---|
STRING | 可以是字符串踊沸、整數(shù)或者浮點數(shù) | 對整個字符串或者字符串的其中一部分執(zhí)行操作;對整數(shù)和浮點數(shù)執(zhí)行自增或者自減 |
LIST | 一個鏈表挖腰,鏈表上的每個節(jié)點都包含了一個字符串 | 從鏈表的兩端推入或者彈出元素;根據(jù)偏移量對鏈表進(jìn)行修剪练湿;讀取單個或者多個元素猴仑;根據(jù)值查找或者移除元素 |
SET | 包含字符串的無序收集器,并且被包含的每個字符串都是獨一無二肥哎、各不相同的 | 添加辽俗、獲取、移除單個元素篡诽;檢查一個元素是否存在于集合中崖飘;計算交集、并集杈女、差集朱浴;從集合里面隨機獲取元素 |
HASH | 包含鍵值對的無序散列表 | 添加、獲取达椰、移除單個鍵值對翰蠢;獲取所有鍵值對 |
ZSET | 字符串成員與浮點數(shù)分值之間的有序映射,元素的排列順序由分值的大小決定 | 添加啰劲、獲取梁沧、刪除單個元素;根據(jù)分值范圍或者成員來獲取元素 |
7.2 使用場景
STRING
String是最常用的一種數(shù)據(jù)類型蝇裤,普通的key/value存儲都可以使用此類型廷支。比如分布式系統(tǒng)下,用戶登錄信息的共享栓辜,使用userguid
鍵 | 值 |
---|---|
userid | token |
LIST
List就是鏈表恋拍,可以存儲有先后順序的數(shù)據(jù),比如:文章列表藕甩、最新消息芝囤。也可以基于此實現(xiàn)消息隊列。
鍵 | 值 |
---|---|
msglist | {msg1, msg2,...} |
SET
與list類似是一個列表的功能,特殊之處在于set是可以自動排重的悯姊,當(dāng)你需要存儲一個列表數(shù)據(jù)羡藐,又不希望出現(xiàn)重復(fù)數(shù)據(jù)時,set是一個很好的選擇悯许。比如:用戶關(guān)注
鍵 | 值 |
---|---|
userid | [followid1, followid2,...] |
HASH
存儲一些結(jié)構(gòu)化的數(shù)據(jù)仆嗦,比如:用戶信息
鍵 | 值 |
---|---|
userid | {"name":"n", "age":"20"} |
ZSET
sorted set的使用場景與set類似,區(qū)別是set不是自動有序的先壕,而sorted set可以通過用戶額外提供一個優(yōu)先級(score)的參數(shù)來為成員排序瘩扼,并且是插入有序的,即自動排序垃僚。當(dāng)你需要一個有序的并且不重復(fù)的集合列表集绰,那么可以選擇sorted set數(shù)據(jù)結(jié)構(gòu),比如:文章熱度排行
鍵 | 值 |
---|---|
hot_article | [(id1, 20), (id2, 30),...] |