成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

四種緩存的避坑總結

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

背景

分布式、緩存、異步和多線程被稱為互聯網開發的四大法寶。今天我總結一下項目開發中常接觸的四種緩存實際項目中遇到過的問題。

JVM 堆內緩存

JVM 堆內緩存因為可以避免 Memcached、Redis 等集中式緩存網絡通信故障問題,目前還在項目中廣泛使用。

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

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

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

List<POJO> oldList = initList();

public void refresh() {

List<POJO> newList = dataFromNetworkService.getAll();

oldList = new List();

for(POJO pojo : newList) {

oldList.add(pojo);

}

}

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

但是如果代碼這樣寫:

List<POJO2> oldList = initList();

public void refresh() {

List<POJO1> newList = dataFromNetworkService.getAll();

oldList = new List();

for(POJO2 pojo : newList) {

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

}

}

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

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

JVM 堆外緩存

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

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

Linux 的 buffers/cached

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

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

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

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

集中式緩存

Redis 緩存其實也有本機代理,可以緩存一些活躍的數據在本機上,本機可以在取 不 到數據時不需要跨網絡通信。但是因為 Redis 本質是 key-value 的結構。如果需要根據通配符取數據全量,如果網絡出現故障,可能會影響數據的完整性。

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

總結

貝爾實驗室的面向對象編程專家 Tom Cargill 說:

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

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

每周持續投入 5% 的學習時間,10% 的思考時間,再用 100% 的時間去完成 100% 的開發。

責任編輯:張燕妮 來源: 編程一生
相關推薦

2009-11-23 15:57:51

PHP偽靜態

2022-07-04 07:09:55

架構

2019-10-24 07:42:28

Java引用GC

2017-07-06 15:40:19

DevOps核心能力

2012-09-11 09:55:26

編程HTML5編程能力

2011-03-16 09:05:53

NATiptables

2011-11-24 16:34:39

Java

2010-01-20 10:56:14

VB.NET Main

2021-10-24 08:37:18

網絡監控網絡架構網絡

2023-08-30 23:41:16

AI框架項目

2020-05-19 20:13:04

物聯網計算類型IOT

2021-06-04 10:45:31

軟件架構分布式

2023-05-22 08:03:28

JavaScrip枚舉定義

2022-03-25 14:47:24

Javascript數據類型開發

2010-08-19 11:16:30

虛擬化

2021-08-24 08:01:15

死鎖工具多線編程

2010-07-28 13:54:42

Flex數據綁定

2022-07-04 12:07:57

智慧城市智能建筑物聯網

2011-06-01 17:35:35

Android Activity

2017-04-17 19:31:03

Android多線程
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产欧美日韩在线观看 | 亚洲视频在线观看免费 | 精品免费国产视频 | 久久中文字幕一区 | 五月激情综合 | 天天操天天射天天 | 午夜手机在线视频 | 日本黄色免费视频 | 黄色国产 | 亚洲人成网亚洲欧洲无码 | 日韩一区二区三区视频 | 亚洲高清一区二区三区 | 国产三级一区二区 | 精品久久九 | 天天操网 | 亚洲一区二区三区四区五区午夜 | 黄网站免费在线观看 | 九一国产精品 | 国产精品久久久久久中文字 | 黑人一级片视频 | 国产日韩欧美 | 欧美日韩综合精品 | 天天狠狠| 一色一黄视频 | 久久免费视频观看 | 中国黄色毛片视频 | 一级片网址 | 在线播放中文字幕 | 国产欧美精品区一区二区三区 | 一级黄a视频 | 午夜免费福利电影 | 午夜专区 | 成人欧美一区二区三区黑人孕妇 | 在线免费看91 | 精品久久久久久久人人人人传媒 | 韩国精品一区 | 亚洲一区精品在线 | 精品一区国产 | www国产成人免费观看视频,深夜成人网 | 91视视频在线观看入口直接观看 | 欧美video|