日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
四種緩存的避坑總結(jié)

背景

分布式、緩存、異步和多線程被稱為互聯(lián)網(wǎng)開發(fā)的四大法寶。今天我總結(jié)一下項目開發(fā)中常接觸的四種緩存實際項目中遇到過的問題。

創(chuàng)新互聯(lián)專注于企業(yè)營銷型網(wǎng)站建設(shè)、網(wǎng)站重做改版、潁上網(wǎng)站定制設(shè)計、自適應(yīng)品牌網(wǎng)站建設(shè)、成都h5網(wǎng)站建設(shè)商城網(wǎng)站開發(fā)、集團公司官網(wǎng)建設(shè)、外貿(mào)網(wǎng)站制作、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁設(shè)計等建站業(yè)務(wù),價格優(yōu)惠性價比高,為潁上等各大城市提供網(wǎng)站開發(fā)制作服務(wù)。

JVM 堆內(nèi)緩存

JVM 堆內(nèi)緩存因為可以避免 Memcached、Redis 等集中式緩存網(wǎng)絡(luò)通信故障問題,目前還在項目中廣泛使用。

堆內(nèi)緩存需要注意 GC 的問題。假如我們的設(shè)計是定時的從遠程來拉取數(shù)據(jù)更新本地緩存。一定要注意兩點:第一不要全量拉取覆蓋,第二不要把一個大對象整體替換為新對象。

先說全量拉取覆蓋。全量拉取會有很大的網(wǎng)絡(luò)開銷,會造成網(wǎng)絡(luò)流量尖刺。有人說沒事,我們帶寬很足,內(nèi)網(wǎng)訪問,不怕不怕。但是穩(wěn)定性需要修煉的一項是削峰填谷。讓系統(tǒng)在平穩(wěn)的環(huán)境中運行。不然,在拉取大緩存新數(shù)據(jù)的數(shù)據(jù)突然來了個突發(fā)流量?根據(jù)墨菲定律,凡是有幾率會發(fā)生的事情就一定會發(fā)生。編程需謹慎。

再說大對象整體替換的問題,這會造成 GC 問題。偽代碼如下:

List oldList = initList();

public void refresh() {

List newList = dataFromNetworkService.getAll();

oldList = new List();

for(POJO pojo : newList) {

oldList.add(pojo);

}

}

如果從網(wǎng)上拉取的數(shù)據(jù)和在緩存里存儲的數(shù)據(jù),對象類型沒有發(fā)生改變。引起的轉(zhuǎn)換開銷還稍微小點。因為比如對象 POJO 存在一個列表里。這個列表雖然很大,但是里面存的都是對象的引用。實際的 POJO 并沒有發(fā)生變化。上面?zhèn)未a雖然新建一個 List 對象,遍歷添加新對象比直接 oldList=newList 要傻些。但是遍歷過程實際上 POJO  對象沒有發(fā)生改變。所以這里影響 GC 的只是 oldList 這個對象(不包括從網(wǎng)絡(luò)上拉取回來數(shù)據(jù)的過程)。

但是如果代碼這樣寫:

List oldList = initList();

public void refresh() {

List newList = dataFromNetworkService.getAll();

oldList = new List();

for(POJO2 pojo : newList) {

oldList.add(Beanutils.copy(new POJO2(), pojo));

}

}

遍歷過程將會將原來的 POJO1 全部新建一遍,這些對象一般情況下全部先進入堆內(nèi)存的新生代,再經(jīng)過數(shù)次 Young GC 后進入老年代。會造成GC頻繁。

我所做過的項目,一般認為一天一到兩次 Full GC 為合理值。這樣,如果比如預(yù)先知道某個時間點有大促,可通過提前觸發(fā) GC 等方式避免高峰期爆發(fā) Full GC。Young GC 至少是 5 分鐘一次,甚至更久觸發(fā)認為是正常。這樣可以通過控制避過秒殺等場景。

JVM 堆外緩存

堆外緩存的內(nèi)存回收原理使用的是 Java 的虛引用 。這個設(shè)計可以避免 JVM 的 GC 問題,但是處理不好可能會造成更嚴重的后果:整個機器內(nèi)存被打滿,機器可能會掛掉。 其實掛掉一臺在一般企業(yè)的生產(chǎn)環(huán)境還好,因為一般都會有容災(zāi)的冗余機器。 但是更常見的一種情況是機器忙于 swap 內(nèi)存交換,機器活著但是響應(yīng)很慢。 屬于半死不活。 這個問題我沒在線上遇到過,但是我同事之前在超級大廠的時候遇到過。

有的同學(xué)說那我嚴格算好內(nèi)存,做好監(jiān)控。這里面要就要依賴人為的因素來做緊急處理。而人是穩(wěn)定性中最不可靠的。因為問題通常不發(fā)生在人清醒、手里事情很少的時候。而是一種雪上加霜的存在。比如大促時,流量上來了,線程數(shù)會增多,每個線程都會申請線程棧資源,系統(tǒng)處理 IO,這時候系統(tǒng)會申請更多的 buffers/cached 內(nèi)存。

Linux 的 buffers/cached

Linux 系統(tǒng)上運行一下 top 命令或者 free 命令,都能夠看到 buffers 和 cached 相關(guān)的數(shù)據(jù)。需要注意的是通常我們看到的監(jiān)控數(shù)據(jù)空閑內(nèi)存百分比,并非是下面顯示的 free/total,而是 (free+buffers+cached)/total。

buffers 在 Linux 系統(tǒng)中通常被作為與塊存儲的 IO 緩存使用。所謂塊存儲可簡單理解為將數(shù)據(jù)直接寫到裸磁盤。而 cached 則一般會用于文件系統(tǒng)的 IO 緩存。比如 page cache 這種內(nèi)存換頁功能。

聽不明白也沒關(guān)系,因為事實上它們兩個經(jīng)常配合使用。比如與磁盤交換數(shù)據(jù)、進行網(wǎng)絡(luò)通信時都會用。buffers 和 cached 是實實在在被操作系統(tǒng)的系統(tǒng)進程在使用的,但是如果用戶進程需要可以很快釋放。所以通常會將它算到剩余可用內(nèi)存里。

但是這個也要注意了。比如在 IO 密集型的系統(tǒng),如果 buffers/cached 被大幅占用,會降低 IO 速度,進而降低系統(tǒng)吞吐。甚至有可能一個請求幾秒才能到達應(yīng)用程序,造成請求超時。

集中式緩存

Redis 緩存其實也有本機代理,可以緩存一些活躍的數(shù)據(jù)在本機上,本機可以在取 不 到數(shù)據(jù)時不需要跨網(wǎng)絡(luò)通信。但是因為 Redis 本質(zhì)是 key-value 的結(jié)構(gòu)。如果需要根據(jù)通配符取數(shù)據(jù)全量,如果網(wǎng)絡(luò)出現(xiàn)故障,可能會影響數(shù)據(jù)的完整性。

但是 Redis 緩存最讓人擔(dān)心的是不規(guī)范的使用方法。比如存一個很大的 value。具體這個對網(wǎng)絡(luò)和存儲造成的問題就不詳細說了。可以想象下馬桶堵了的情景。

總結(jié)

貝爾實驗室的面向?qū)ο缶幊虒<?Tom Cargill 說:

最初 90% 的開發(fā)工作將會用去你最初 90% 的開發(fā)時間,剩下的 10% 的開發(fā)量將會用去你另外一個 90% 的開發(fā)時間。

我理解剩下 10% 占用了 90% 的時間是由于超出了原有知識貯備,需要臨時抱佛腳,甚至需要拿著錘子找釘子造成的。所以或者也可以這樣做:

每周持續(xù)投入 5% 的學(xué)習(xí)時間,10% 的思考時間,再用 100% 的時間去完成 100% 的開發(fā)。


分享名稱:四種緩存的避坑總結(jié)
分享URL:http://www.5511xx.com/article/ccshsgc.html