原文博客:Doi技術(shù)團(tuán)隊(duì)
鏈接地址:https://blog.doiduoyi.com
初心:記錄優(yōu)秀的Doi技術(shù)團(tuán)隊(duì)學(xué)習(xí)經(jīng)歷
本系列介紹
本系列《剖析緩存系列》诗鸭,由淺到深的對緩存進(jìn)行分析介紹,從緩存形式参滴,更新策略,常見問題锻弓,以及JAVA緩存使用(JCache,Spring cache,Ehcache)和緩存服務(wù)器redis
系列目錄
緩存
緩存形式
緩存形式分為種靜態(tài)資源砾赔,動態(tài)資源,數(shù)據(jù)緩存
靜態(tài)資源
靜態(tài)資源一般指js、css暴心、img 等非服務(wù)器動態(tài)運(yùn)行生成的文件妓盲,該文件變更頻率很低。
瀏覽器緩存(HTTP緩存)
瀏覽器緩存目的是為了節(jié)約網(wǎng)絡(luò)的資源加速瀏覽和服務(wù)器壓力专普。把一個已經(jīng)請求過的資源拷貝一份存儲起來悯衬,當(dāng)下次需要該資源時,瀏覽器會根據(jù)緩存機(jī)制決定直接使用緩存資源還是再次向服務(wù)器發(fā)送請求
瀏覽器緩存又分為強(qiáng)制緩存和協(xié)商緩存
- 強(qiáng)制緩存
瀏覽器訪問一資源的時候檀夹,會先判斷資源請求頭的header字段信息筋粗,根據(jù)兩個字段
Expires/Cache-Control
判斷是否命中緩存。如果命中緩存炸渡,那么就不會向服務(wù)器請求資源
兩個header字段:
- Expires:
資源過期時間娜亿,0代表已過期。http1.0版本蚌堵,已不推薦使用
示例:Expires: Wed, 21 Oct 2015 07:28:00 GMT
- Cache-Control:
通過指定指令來實(shí)現(xiàn)緩存機(jī)制买决。http1.1版本新增的字段。
Cache-Control的請求header命令列表
字段名稱 | 說明 |
---|---|
max-age=seconds | 緩存最大時間 |
max-stale[=seconds] | 接受超過緩存時間secondes秒的資源 |
min-fresh=seconds | 接收在secondes內(nèi)刷新過的資源 |
no-cache | 不使用緩存 |
no-store | 內(nèi)存不會存在臨時文件中 |
no-transform | 接收沒有被轉(zhuǎn)換的數(shù)據(jù)吼畏,例如沒有被壓縮的數(shù)據(jù) |
only-if-cached | 只接受已緩存的響應(yīng) |
Cache-Control的響應(yīng)header命令列表
字段名稱 | 說明 |
---|---|
public | 表明響應(yīng)可以被任何對象(包括:發(fā)送請求的客戶端督赤,代理服務(wù)器,等等)緩存 |
private | 表明響應(yīng)只能被單個用戶緩存泻蚊,不能作為共享緩存(即代理服務(wù)器不能緩存它) |
proxy-revalidate | 接收在secondes內(nèi)刷新過的資源 |
no-cache | 不使用緩存 |
no-store | 內(nèi)存不會存在臨時文件中 |
no-transform | 接收沒有被轉(zhuǎn)換的數(shù)據(jù)躲舌,例如沒有被壓縮的數(shù)據(jù) |
max-age=seconds | 設(shè)置緩存存儲的最大周期,超過這個時間緩存被認(rèn)為過期(單位秒) |
s-maxage=seconds | 設(shè)置緩存最大周期藕夫,覆蓋max-age或者Expires頭 |
- 協(xié)商緩存
如果強(qiáng)制緩存沒有命中或者已經(jīng)過期孽糖,覽器攜帶緩存標(biāo)識請求服務(wù)器,當(dāng)服務(wù)器返回200狀態(tài)碼瀏覽器會重新請求資源毅贮,當(dāng)返回304狀態(tài)碼瀏覽器會重新使用該緩存办悟。在這個過程中304狀態(tài)碼就是與服務(wù)器協(xié)商是否要重新更新緩存,雖然多了一次請求滩褥,但卻不用重新請求資源病蛉,節(jié)省了請求資源的帶寬。
協(xié)商緩存的header字段
-
Last-Modified或者Etag:第一次請求資源時瑰煎,會帶上該字段
- Last-Modified:比較服務(wù)器文件修改時間是否一致铺然,如果一致,認(rèn)為文件并沒有修改酒甸,不需要重新請求資源魄健。可能存在文件沒修改內(nèi)容插勤,但是修改時間變了沽瘦,導(dǎo)致瀏覽器重新請求資源革骨。
- Etag:會對文件計算出一個唯一標(biāo)識符,判斷這個唯一標(biāo)識符是否一致得知文件是否被修改析恋。
-
If-Modified-Since或者If-None-Match :后續(xù)的請求良哲,都會帶上這個字段
- If-Modified-Since 是一個條件式請求首部,服務(wù)器只在所請求的資源在給定的日期時間之后對內(nèi)容進(jìn)行過修改的情況下才會將資源返回助隧,狀態(tài)碼為 200筑凫。如果請求的資源從那時起未經(jīng)修改,那么返回一個不帶有消息主體的304 響應(yīng)并村,而在 Last-Modified 首部中會帶有上次修改時間巍实。If-Modified-Since 只可以用在 GET 或 HEAD 請求中。
-
If-None-Match 是一個條件式請求首部橘霎。對于 GETGET 和 HEAD 請求方法來說蔫浆,當(dāng)且僅當(dāng)服務(wù)器上沒有任何資源的 ETag 屬性值與這個首部中列出的相匹配的時候,服務(wù)器端會才返回所請求的資源姐叁,響應(yīng)碼為 200 瓦盛。對于其他方法來說,當(dāng)且僅當(dāng)最終確認(rèn)沒有已存在的資源的 ETag 屬性值與這個首部中所列出的相匹配的時候外潜,才會對請求進(jìn)行相應(yīng)的處理原环。
例:
刷新緩存行為,導(dǎo)致緩存方式都不一樣
-
在URI輸入欄中輸入然后回車/通過書簽訪問
如下圖处窥,可以看到該資源是直接從緩存中讀取嘱吗,并沒有發(fā)起請求
-
F5/點(diǎn)擊工具欄中的刷新按鈕/右鍵菜單重新加載
如下圖,刷新頁面滔驾,瀏覽器會去請求服務(wù)器資源谒麦,但是由于服務(wù)器資源沒有修改,會返回304
-
Ctl+F5 強(qiáng)行刷新緩存
如下圖哆致,瀏覽器首先不會理會本地是否有緩存绕德,而且也不會去比較服務(wù)器的緩存資源是否有修改,而是直接請求資源(為了服務(wù)器不會返回304摊阀,瀏覽器會將header的If-None-Match表示去掉)
緩存實(shí)踐:
- 通常會使用Cache-Control代替Expires耻蛇。
- 對于所有可緩存資源,指定一個Cache-Control max-age以及一個Last-Modified或ETag至關(guān)重要。因?yàn)?strong>Cache-Control max-age不需要每次都發(fā)起一次請求來校驗(yàn)資源時效性,Last-Modified或ETag保證當(dāng)資源未出現(xiàn)修改的時候不需要重新發(fā)送該資源戈钢。
- 有時候Cache-Control的過期時間很難控制。對于長期不會改變的資源寂呛,設(shè)置時間短了,會頻繁請求服務(wù)器返回304。所以通常會將過期設(shè)置設(shè)置很長,通過在文件名或參數(shù)帶上一串md5或時間標(biāo)記符蚊惯。文件沒有變動的時候愿卸,瀏覽器不用發(fā)起請求直接可以使用緩存文件;而在文件有變化的時候截型,由于文件版本號的變更,導(dǎo)致文件名變化儒溉,請求的url變了宦焦,自然文件就更新了。例如:
https://doi.io/topic/index.js?43d3ea2083f1e631dbc4
服務(wù)器緩存
服務(wù)器緩存通常指的是將資源放在專門緩存服務(wù)器上顿涣,為了減輕業(yè)務(wù)服務(wù)器的壓力波闹。
此篇簡單介紹一下CDN緩存和Nginx緩存
- CDN緩存:CDN服務(wù)商將源站的資源緩存到遍布全國的高性能加速節(jié)點(diǎn)上,當(dāng)用戶訪問相應(yīng)的業(yè)務(wù)資源時涛碑,用戶會被調(diào)度至最接近的節(jié)點(diǎn)最近的節(jié)點(diǎn)ip返回給用戶
- Nginx 靜態(tài)資源緩存: 目前很多項(xiàng)目都是前后端分離精堕,前端項(xiàng)目會部署在Nginx服務(wù)器,對于站點(diǎn)中不經(jīng)常修改的靜態(tài)內(nèi)容(如圖片蒲障,JS歹篓,CSS),可以在Nginx服務(wù)器中設(shè)置expires過期時間揉阎,控制瀏覽器緩存庄撮,達(dá)到有效減小帶寬流量,降低服務(wù)器壓力的目的
nginx配置例子
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ {
#過期時間為30天毙籽,
#圖片文件不怎么更新洞斯,過期可以設(shè)大一點(diǎn),
#如果頻繁更新坑赡,則可以設(shè)置得小一點(diǎn)烙如。
expires 30d;
}
location ~ .*\.(js|css)$ {
expires 10d;
}
動態(tài)緩存
是在新內(nèi)容發(fā)布以后,并不預(yù)先生成相應(yīng)的靜態(tài)頁面毅否,直到對相應(yīng)內(nèi)容發(fā)出請求時亚铁,如果前臺緩存服務(wù)器找不到相應(yīng)緩存,就向后臺內(nèi)容管理服務(wù)器發(fā)出請求搀突,例如數(shù)據(jù)庫刀闷,后臺系統(tǒng)會生成相應(yīng)內(nèi)容的靜態(tài)頁面,用戶第一次訪問頁面時可能會慢一點(diǎn)仰迁,但是以后就是直接訪問緩存了甸昏。例如:對動態(tài)頁面.jsp、.asp/.aspx徐许、.php施蜜、.js(nodejs)等動態(tài)頁面緩存。通常動態(tài)頁面一般都會涉及動態(tài)計算雌隅、數(shù)據(jù)庫緩存翻默、數(shù)據(jù)庫操作缸沃,所以每一次訪問同一個頁面,所獲得的數(shù)據(jù)可能都有所不同修械。所以動態(tài)緩存并適合所有的場景趾牧。
詳細(xì)鏈接
數(shù)據(jù)緩存
數(shù)據(jù)緩存通常是把計算量大,訪問耗時肯污,請求頻率高的數(shù)據(jù)放在內(nèi)存中翘单,主要提高計算效率,減少請求響應(yīng)時間蹦渣,減少無謂的數(shù)據(jù)庫和網(wǎng)路的訪問哄芜。數(shù)據(jù)緩存是本系列的重點(diǎn),以下篇幅都是圍繞數(shù)據(jù)緩存展開柬唯。
緩存的成本和收益
- 計算量,縮短請求流程(減少網(wǎng)絡(luò)io或者硬盤io)
- 減少用戶請求的帶寬和減少服務(wù)器壓力
優(yōu)點(diǎn):
優(yōu)點(diǎn) | 描述 |
---|---|
縮短請求流程(減少網(wǎng)絡(luò)io或者硬盤io) | 瀏覽器緩存认臊,cdn緩存,可以減少請求資源的過程锄奢,加快響應(yīng)速度 |
降低后端負(fù)載 | 對耗時高的請求失晴,可以很大程度降低了后端的負(fù)載 |
缺點(diǎn) | 描述 |
---|---|
對硬件要求高 | 一般緩存都是放在內(nèi)存中,內(nèi)存是稀缺資源 |
數(shù)據(jù)不一致問題 | 相當(dāng)于增加了一個數(shù)據(jù)源斟薇,當(dāng)數(shù)據(jù)發(fā)生變化师坎,會出現(xiàn)臟數(shù)據(jù)現(xiàn)象 |
維護(hù)成功高 | 加入緩存后,需要同時處理緩存層和存儲層的邏輯堪滨,增加了開發(fā)者維護(hù)代碼的成本 |
動態(tài)緩存
是在新內(nèi)容發(fā)布以后胯陋,并不預(yù)先生成相應(yīng)的靜態(tài)頁面,直到對相應(yīng)內(nèi)容發(fā)出請求時袱箱,如果前臺緩存服務(wù)器找不到相應(yīng)緩存遏乔,就向后臺內(nèi)容管理服務(wù)器發(fā)出請求,例如數(shù)據(jù)庫发笔,后臺系統(tǒng)會生成相應(yīng)內(nèi)容的靜態(tài)頁面盟萨,用戶第一次訪問頁面時可能會慢一點(diǎn),但是以后就是直接訪問緩存了了讨。例如:對動態(tài)頁面.jsp捻激、.asp/.aspx、.php前计、.js(nodejs)等動態(tài)頁面緩存胞谭。通常動態(tài)頁面一般都會涉及動態(tài)計算、數(shù)據(jù)庫緩存男杈、數(shù)據(jù)庫操作丈屹,所以每一次訪問同一個頁面,所獲得的數(shù)據(jù)可能都有所不同伶棒。所以動態(tài)緩存并適合所有的場景旺垒。
詳細(xì)鏈接
數(shù)據(jù)緩存
數(shù)據(jù)緩存通常是把計算量大彩库,訪問耗時,請求頻率高的數(shù)據(jù)放在內(nèi)存中先蒋,主要提高計算效率骇钦,減少請求響應(yīng)時間,減少無謂的數(shù)據(jù)庫和網(wǎng)路的訪問竞漾。數(shù)據(jù)緩存是本系列的重點(diǎn)司忱,以下篇幅都是圍繞數(shù)據(jù)緩存展開。
緩存更新策略
策略 | 一致性 | 維護(hù)成本 |
---|---|---|
LRU/LIRS/FIFO算法剔除 | 最差 | 低 |
超時剔除 | 較差 | 較低 |
主動更新 | 強(qiáng) | 高 |
LRU/LIRS/FIFO算法剔除
LRU
將最近最少使用的數(shù)據(jù)清理掉畴蹭,這個算法很普通。Mysql的內(nèi)存中存儲數(shù)據(jù)就是使用LRU策略鳍烁,只存儲熱點(diǎn)數(shù)據(jù)
LFU
淘汰一定時期內(nèi)被訪問次數(shù)最少的數(shù)據(jù)
FIFO
前進(jìn)先出隊(duì)列叨襟,舊緩存先被清除
超時剔除
這種策略對數(shù)據(jù)一致性要求不高。
定時刪除
設(shè)置緩存的過期時間幔荒,當(dāng)時間到的時候糊闽,自動刪除緩存。例如redis的expire過期時間一樣爹梁。
缺點(diǎn):對應(yīng)業(yè)務(wù)項(xiàng)目如果使用定時刪除右犹,那么每個緩存都需要有一個定時器,或者一個監(jiān)聽線程姚垃,這樣會占用cpu資源念链,會導(dǎo)致cpu過度緊張。而且還需要開發(fā)和維護(hù)定時器积糯,提高了開發(fā)成本
懶惰刪除
設(shè)置一個過期時間掂墓,只有當(dāng)請求獲取這個緩存的時候,才會對這個緩存進(jìn)行過期檢查看成。如果過期君编,就會執(zhí)行過期策略(刪除或者刷新)。
例如 java的緩存框架guava cache就是用這種策略川慌。
優(yōu)點(diǎn):可以不占用新的資源去管理緩存
缺點(diǎn):對于過期的緩存吃嘿,無法即時釋放。過期緩存過多梦重,會占用大量的內(nèi)存
定期刪除
建立一個線程定期去掃描過期的緩存兑燥,將過期的緩存執(zhí)行策略
優(yōu)點(diǎn):占用小量的cpu資源,解決了過期緩存過多導(dǎo)致占用大量內(nèi)存的問題
缺點(diǎn):掃描時間設(shè)置要合理忍饰,否則也會造成cpu浪費(fèi)
主動更新
這種策略是對數(shù)據(jù)一致性要求比較高贪嫂。
- Cache Aside
最常用的一種模式。
- 失效:請求從緩存中獲取數(shù)據(jù)艾蓝,沒有得到力崇,則從數(shù)據(jù)庫中獲取
- 命中:應(yīng)用程序從緩存中獲取數(shù)據(jù)斗塘,返回
- 更新:先更新數(shù)據(jù)庫,成功后亮靴,再更新緩存
特點(diǎn):需要維護(hù)兩個數(shù)據(jù)源(緩存和數(shù)據(jù)庫)馍盟。更新數(shù)據(jù)庫的過程中,其他讀請求從緩存讀取的數(shù)據(jù)是舊的茧吊。
- Read/Write Through
只讓請求維護(hù)一個數(shù)據(jù)源贞岭,數(shù)據(jù)庫對請求來說是透明的
Read Through Pattern
讀取數(shù)據(jù)時的策略
當(dāng)緩存沒有命中(緩存中沒有得到數(shù)據(jù)),由緩存服務(wù)來加載數(shù)據(jù)搓侄。同時瞄桨,請求可能會阻塞等待或者返回。Write Through
更新數(shù)據(jù)時的策略
請求更新數(shù)據(jù)的時候讶踪,如果緩存沒有數(shù)據(jù)芯侥,直接更新數(shù)據(jù)庫,如果緩存有數(shù)據(jù)乳讥,直接更新緩存柱查,同時緩存服務(wù)會將緩存數(shù)據(jù)更新到數(shù)據(jù)庫中,當(dāng)數(shù)據(jù)庫更新成功云石,才認(rèn)為更新數(shù)據(jù)成功
特點(diǎn):代碼實(shí)現(xiàn)會比較復(fù)雜唉工。當(dāng)寫請求更新到緩存的時候,同時讀請求是可以在緩存中讀取到數(shù)據(jù)汹忠,提高了讀的效率淋硝。但是這會增加寫請求的響應(yīng)時間,因?yàn)閷懻埱笮枰戮彺婧蛿?shù)據(jù)庫错维。
- Write Behind
與Read/Write Through 模式相似奖地,但是更加最求響應(yīng)速度
當(dāng)更新緩存的時候,Write Through是同步更新數(shù)據(jù)庫赋焕,而Write Behind是異步更新數(shù)據(jù)庫参歹,寫請求只需要寫入到緩存就可以返回,緩存服務(wù)會異步同步到數(shù)據(jù)庫中隆判。
特點(diǎn):代碼實(shí)現(xiàn)復(fù)雜犬庇,需要考慮很多場景,例如 內(nèi)存不夠侨嘀,更新數(shù)據(jù)過多臭挽,更新線程還沒寫到持久層就宕機(jī)導(dǎo)致數(shù)據(jù)丟失等等
緩存數(shù)據(jù)格式
緩存是一個類map的key-value的數(shù)據(jù)格式。key-value通常都是非null的咬腕,key-value都可以是引用也可以是基本數(shù)據(jù)類型(字符串欢峰,數(shù)字等)。key在整個緩存中是唯一。
緩存常見現(xiàn)象
緩存穿透
緩存穿透是指緩存沒有發(fā)揮作用纽帖,導(dǎo)致請求需要讀取數(shù)據(jù)源數(shù)據(jù)宠漩。具體有兩種情況:
- 沒有命中緩存:
由于被訪問的數(shù)據(jù)是空數(shù)據(jù),不存在的懊直,所以緩存中不會存在扒吁。一般來說,訪問不存在的數(shù)據(jù)的請求不多室囊,不會對服務(wù)器造成很大的影響雕崩,但是如果有人惡意去訪問這些不存在的數(shù)據(jù),那么這些請求都會落到數(shù)據(jù)源中請求融撞,對數(shù)據(jù)源造成很大的壓力盼铁。
解決辦法:- 如果查詢存儲系統(tǒng)的數(shù)據(jù)沒有找到,則直接設(shè)置一個默認(rèn)值(可以是空值尝偎,也可以是具體的值)存到緩存中捉貌,這樣第二次讀取緩存時就會獲取到默認(rèn)值,而不會繼續(xù)訪問存儲系統(tǒng)冬念。
- 對這種請求,通過nginx或者網(wǎng)關(guān)層直接拒絕牧挣,或者添加ip白名單過濾掉
- 使用布隆過濾器急前,可以將不可能存在的數(shù)據(jù)在這個布隆過濾器中攔截掉
- 無法完全緩存數(shù)據(jù)
查詢的數(shù)據(jù)太大,無法完全緩存起來瀑构,因?yàn)闀加煤艽蟮膬?nèi)存空間裆针。例如分頁,很多用戶只會看前幾頁的數(shù)據(jù)寺晌,所以存儲前幾頁的數(shù)據(jù)才是最優(yōu)解世吨。
解決辦法:對應(yīng)這種場景,可以對數(shù)據(jù)進(jìn)行切割呻征,只緩存前幾頁的數(shù)據(jù)耘婚。如果遇到爬蟲或者惡意查詢,可以通過監(jiān)控服務(wù)器狀態(tài)陆赋,發(fā)現(xiàn)問題后及時處理沐祷。
緩存雪崩
緩存雪崩是指當(dāng)緩存失效(過期)后引起系統(tǒng)性能急劇下降的情況。當(dāng)緩存過期被清除后攒岛,業(yè)務(wù)系統(tǒng)需要重新生成緩存赖临,因此需要再次訪問數(shù)據(jù)源,再次獲取數(shù)據(jù)灾锯,這個處理步驟耗時幾十毫秒甚至上百毫秒(因?yàn)榇蟛糠志彺娴臄?shù)據(jù)都是耗時操作)兢榨。而對于一個高并發(fā)的業(yè)務(wù)系統(tǒng)來說,
QPS都是上百上千的,這些請求都會直接訪問數(shù)據(jù)源吵聪,導(dǎo)致數(shù)據(jù)源壓力瞬間增大凌那。
解決辦法:
鎖機(jī)制
這種策略很常見,在GuavaCache中就用到了這種策略暖璧。當(dāng)多個請求訪問這個(緩存失效)緩存時案怯,只允許一個線程去刷新緩存,其他線程則休眠等待或者返回空數(shù)據(jù)或者默認(rèn)值澎办。這種方法實(shí)現(xiàn)簡單嘲碱,但這是對于單機(jī)環(huán)境下來說的。
如果是在分布式環(huán)境下局蚀,幾百臺服務(wù)器麦锯,那么刷新緩存只能讓某臺服務(wù)器的單個線程去刷新緩存,這時候就需要分布式鎖琅绅。典型的分布式鎖有redis和zookeeper避免緩存失效
這種思路很巧扶欣,導(dǎo)致雪崩是因?yàn)榫彺娴氖В敲淳妥尵彺娌皇У耐瑫r也保證緩存的時效性千扶×响簦可以設(shè)置緩存永久存在,后臺起一個刷新緩存的線程澎羞,定期去刷新緩存髓绽,那么就不會存在緩存失效的問題。
但這也存在一個問題妆绞,就是緩存的主動更新問題顺呕,如果由該線程去完成,那么就需要有一個消息隊(duì)列來通知這個更新緩存線程去主動更新緩存括饶,實(shí)現(xiàn)邏輯也會變得復(fù)雜株茶。
后臺更新機(jī)制還適合業(yè)務(wù)剛上線的時候進(jìn)行緩存預(yù)熱。緩存預(yù)熱指系統(tǒng)上線后图焰,將相關(guān)的緩存數(shù)據(jù)直接加載到緩存系統(tǒng)启盛,而不是等待用戶訪問才來觸發(fā)緩存加載。緩存集群
這種方式涉及到分布式緩存技羔,為了防止可能因?yàn)榫彺娣?wù)宕機(jī)導(dǎo)致的緩存大量失效驰徊,可以使用memcache或者redis集群保證緩存高可用性
緩存降級
當(dāng)訪問量劇增,緩存服務(wù)扛不住這么大的訪問量的時候堕阔,這時候需要對某些非核心功能的業(yè)務(wù)緩存數(shù)據(jù)進(jìn)行降級棍厂,為了保證核心業(yè)務(wù)可用。
無底洞問題
當(dāng)分布式緩存連接效率下降超陆,就算添加緩存服務(wù)器也沒有好轉(zhuǎn)牺弹,這種情況就叫無底洞問題浦马。
分布式緩存就算將不同的緩存存儲在不同的服務(wù)器上,當(dāng)請求的時候张漂,通過計算定位緩存位置并向緩存服務(wù)器獲取緩存晶默。當(dāng)請求是批量操作的時候,請求的緩存在多臺緩存服務(wù)器上航攒,就會出現(xiàn)多次io請求磺陡,出現(xiàn)無法避免的耗時
解決方案:
- 針對業(yè)務(wù)的特點(diǎn),采取不同的緩存存儲方案漠畜,通常有兩種存儲方式:哈希存儲和順序存儲
分布方式 | 特點(diǎn) | 典型產(chǎn)品 |
---|---|---|
哈希分布 | 1.數(shù)據(jù)分散度高 2. key分布與業(yè)務(wù)無關(guān) 3. 無法順序訪問 4.支持批量操作 | 一致性哈希memcache |
順序分布 | 1. 數(shù)據(jù)分散度易傾斜 2. key分布與業(yè)務(wù)有關(guān) 3.可以順序訪問 4.支持批量操作 | BigTable Hbase |
- 利用不同批量操作的方法:串行mget币他,串行io,并行io憔狞,hash tags
- 串行mget:時間復(fù)雜度高蝴悉,操作時間=n次網(wǎng)絡(luò)時間+n次命令時間,基本沒有優(yōu)化瘾敢。
- 串行IO:對mget操作根據(jù)計算拍冠,算出查詢key對應(yīng)的節(jié)點(diǎn),對相同節(jié)點(diǎn)的key合并成一次mget請求(相當(dāng)于有mget涉及到多少個節(jié)點(diǎn)簇抵,就有多少個IO請求)庆杜。操作時間=node次網(wǎng)絡(luò)時間+n次命令時間
- 并行IO:在串行IO的基礎(chǔ)上,改為多線程請求緩存服務(wù)器碟摆。操作時間=1次網(wǎng)絡(luò)時間+n次命令時間
- hash-tag: 強(qiáng)行將一些key緩存到指定的節(jié)點(diǎn)上欣福,那么讀取緩存就只需要直接去該節(jié)點(diǎn)讀取就可以,例如redis 支持hash-tag操作焦履。操作時間=1次網(wǎng)絡(luò)時間+n次命令時間
歡迎關(guān)注我們團(tuán)隊(duì)的微信公眾號:【Doi多意】,獲取更多系列文章雏逾,包括前端嘉裤,后端,AI栖博,產(chǎn)品方向的系列屑宠。