自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

留心那些潛在的系統(tǒng)設(shè)計(jì)問(wèn)題

開發(fā)
在系統(tǒng)設(shè)計(jì)階段考慮全面很難,有許多人傾向于把整個(gè)設(shè)計(jì)分成若干階段,在迭代中完成整個(gè)設(shè)計(jì),這本身是非常好的,但是,就如同“先做出來(lái),以后再優(yōu)化”這樣的經(jīng)典謊言一樣,本身并無(wú)錯(cuò),只是許多程序員都不習(xí)慣于真正的迭代設(shè)計(jì)和迭代優(yōu)化。

在系統(tǒng)設(shè)計(jì)階段考慮全面很難,有許多人傾向于把整個(gè)設(shè)計(jì)分成若干階段,在迭代中完成整個(gè)設(shè)計(jì),這本身是非常好的,但是,就如同“先做出來(lái),以后再優(yōu)化”這樣的經(jīng)典謊言一樣,本身并無(wú)錯(cuò),只是許多程序員都不習(xí)慣于真正的迭代設(shè)計(jì)和迭代優(yōu)化。舉例來(lái)說(shuō),有一個(gè)日益復(fù)雜的類,每個(gè)人都修改一點(diǎn)點(diǎn),一直到最后都沒(méi)有人愿意去做重構(gòu),大家的心態(tài)都是一樣的:“我只修改了一點(diǎn)點(diǎn),為什么要我去動(dòng)那么大的刀,于我沒(méi)有任何好處”。我不在這里談?wù)撨@一問(wèn)題的解決辦法,我倒是想說(shuō),在開始階段考慮清楚問(wèn)題在多數(shù)情況下還是很有好處的,設(shè)計(jì)考慮得越是清楚,在后續(xù)階段代碼可以承受越多的變更而不腐朽。

 

再做系統(tǒng)設(shè)計(jì)的時(shí)候,我們常常會(huì)這樣說(shuō):“一般情況下”、“99%”和“基本上”等等。如果你發(fā)現(xiàn)這是在悄悄地,或者潛意識(shí)地避談問(wèn)題,可就要小心了。有時(shí)候你可以找到根據(jù),“事情不會(huì)那么壞吧”,“不會(huì)那么不湊巧吧”,在系統(tǒng)設(shè)計(jì)階段盡把事情往好的方向想可未必是件好事;也許更多時(shí)候會(huì)覺(jué)得這是直覺(jué),總覺(jué)得某一處設(shè)計(jì)別扭,不合理卻有說(shuō)不出強(qiáng)硬的理由來(lái),最多只能抱怨一句“通常它不應(yīng)該是這樣設(shè)計(jì)的”。這種情況發(fā)生的時(shí)候,請(qǐng)千萬(wàn)不要放過(guò)它,很多次,在系統(tǒng)上線以后,最初的問(wèn)題或者潛在的問(wèn)題最終暴露出來(lái),而這樣的問(wèn)題很多在系統(tǒng)設(shè)計(jì)階段都是有端倪的。

例子1:用戶行為記錄的持久化

以前我參與做過(guò)這樣一個(gè)系統(tǒng),用戶的行為需要被記錄到數(shù)據(jù)庫(kù)里去,但是每條記錄發(fā)生的時(shí)候都寫一次數(shù)據(jù)庫(kù)覺(jué)得開銷太大,于是設(shè)計(jì)了一個(gè)鏈表:

  • 用戶的行為會(huì)首先被即時(shí)記錄到鏈表里面去;
  • 每十分鐘往數(shù)據(jù)庫(kù)里面集中寫一次數(shù)據(jù),然后清空鏈表內(nèi)的數(shù)據(jù)。

看起來(lái)確實(shí)可以實(shí)現(xiàn)需求,可是,這樣的設(shè)計(jì)有什么問(wèn)題?

這樣的設(shè)計(jì)當(dāng)時(shí)居然沒(méi)有受到系統(tǒng)設(shè)計(jì)評(píng)審的人的質(zhì)疑,我實(shí)在覺(jué)得奇怪。我想很多人都可以看得出潛在的問(wèn)題:

  • 清空鏈表數(shù)據(jù)是使用時(shí)間條件觸發(fā)的任務(wù)來(lái)完成,換言之,無(wú)論這十分鐘內(nèi)如果事件暴增,也無(wú)法觸發(fā)鏈表清空的行為,鏈表很容易變得非常大;
  • 清空鏈表的任務(wù)如果執(zhí)行過(guò)程中出了異常,甚至僅僅是處理速度受到阻塞,將直接導(dǎo)致鏈表數(shù)據(jù)無(wú)法得到清空;
  • 如果往數(shù)據(jù)庫(kù)里寫數(shù)據(jù)和清空鏈表的行為需要鎖定鏈表,倘若鏈表很大,或者寫數(shù)據(jù)庫(kù)過(guò)慢,都會(huì)導(dǎo)致鏈表寫行為被阻塞。

這些問(wèn)題當(dāng)然在明確的情況下可以得到規(guī)避,但是毫無(wú)疑問(wèn),這樣的設(shè)計(jì)充滿了潛在的危險(xiǎn)。事實(shí)上,最終這樣的問(wèn)題也確實(shí)發(fā)生了,導(dǎo)致的結(jié)果是鏈表巨大,撐死了整個(gè)系統(tǒng),OOM,系統(tǒng)失去響應(yīng)。

例子2:HashMap并發(fā)訪問(wèn)導(dǎo)致死循環(huán)

非常常見(jiàn)的并發(fā)訪問(wèn)HashMap的問(wèn)題,我也遇到過(guò)。有潛在的危險(xiǎn)導(dǎo)致HashMap死循環(huán),表現(xiàn)就是CPU占用100%,而且這樣的問(wèn)題是不可逆的,問(wèn)題的原因分析我相信大家可以在網(wǎng)上搜得到很多文章,我就不啰嗦了。我印象深刻的是當(dāng)時(shí)定位完問(wèn)題,向犯下錯(cuò)誤的程序員解釋原因的時(shí)候,他居然還說(shuō):“這個(gè)HashMap的讀寫很不頻繁,哪有那么巧的事?”,這就是僥幸心理,即便知道了問(wèn)題依然不愿意做出修正。

例子3:摘要算法的沖突問(wèn)題

類似的問(wèn)題還有,使用摘要算法的時(shí)候,比如MD5,我在做一個(gè)系統(tǒng),使用一個(gè)中心集群緩存,使用一個(gè)巨長(zhǎng)的字符串的MD5摘要來(lái)做key,好處在于key的長(zhǎng)度可以大大縮短,但我們都知道,任何摘要算法都會(huì)使得結(jié)果字符串存在沖突(重復(fù))的可能,即源字符串不同,但是摘要字符串相同,雖說(shuō)用統(tǒng)計(jì)的話來(lái)說(shuō),單純兩個(gè)字符串發(fā)生這種情況的概率低到幾乎不可能發(fā)生。但是我們依然需要謹(jǐn)慎,尤其是在數(shù)據(jù)量巨大的情況下,一旦發(fā)生沖突,要有解決辦法(比如把源字符串放在緩存條目的結(jié)果對(duì)象中,在緩存條目命中,正式取出返回前,再進(jìn)一步比較源字符串以確定100%的準(zhǔn)確性),或者至少必須要能夠承擔(dān)風(fēng)險(xiǎn)。

例子4:文件處理后續(xù)流程的兩個(gè)問(wèn)題

最近有一位同事向我們介紹了他最近處理的一個(gè)問(wèn)題,這個(gè)問(wèn)題是,用戶會(huì)上傳一個(gè)多行的文件,比如文件有一萬(wàn)行,每一行都代表一條待處理的數(shù)據(jù),在數(shù)據(jù)正確的時(shí)候,一切都正常;倘若有一行數(shù)據(jù)處理發(fā)生錯(cuò)誤,會(huì)自動(dòng)發(fā)送一封郵件通知,看起來(lái)似乎很不錯(cuò)的系統(tǒng)。但是這個(gè)時(shí)候問(wèn)題來(lái)了,有一次文件的處理錯(cuò)誤過(guò)多,導(dǎo)致一口氣發(fā)送了幾千封郵件,變成了郵件洪水。而在他介紹這個(gè)系統(tǒng)設(shè)計(jì)的時(shí)候,我們留意到了其中存在一個(gè)時(shí)間條件觸發(fā)的任務(wù),任務(wù)基于兩個(gè)數(shù)據(jù)庫(kù)的數(shù)據(jù)執(zhí)行,這兩個(gè)數(shù)據(jù)庫(kù)的數(shù)據(jù)同步是單獨(dú)完成的,因此可能存在數(shù)據(jù)不一致的情況,并且在這里假定在數(shù)據(jù)更新的一小時(shí)以后,兩個(gè)庫(kù)的數(shù)據(jù)就會(huì)一致了。這其實(shí)就涉及到了兩個(gè)問(wèn)題或者隱患,一個(gè)是郵件處理和發(fā)送的數(shù)量缺乏控制,另一個(gè)是用假定的時(shí)間來(lái)保證數(shù)據(jù)的一致性。

例子5:?jiǎn)吸c(diǎn)故障問(wèn)題

單點(diǎn)故障問(wèn)題也是很常見(jiàn)的會(huì)導(dǎo)致服務(wù)失去的問(wèn)題,出了問(wèn)題所有人都知道原因,但是有時(shí)候就是很難在系統(tǒng)設(shè)計(jì)階段識(shí)別出來(lái)。以前我們給電信運(yùn)營(yíng)商提供服務(wù),很多電信運(yùn)營(yíng)商通常有錢(比如國(guó)內(nèi)的三家壟斷巨頭),不太在乎成本。服務(wù)器用的單板幾萬(wàn)塊錢一塊,備了幾十塊,文件存儲(chǔ)是一個(gè)大型的磁盤陣列,數(shù)據(jù)庫(kù)是IBM小型機(jī)雙機(jī)備份(PS:IBM的設(shè)備其實(shí)挺不可靠的,聽維優(yōu)的同學(xué)說(shuō),保修期內(nèi)屁事兒沒(méi)有,保修期一到一臺(tái)臺(tái)IBM的機(jī)器開始?jí)?,搞得像定時(shí)炸彈似的),當(dāng)時(shí)唯獨(dú)忽略了單點(diǎn)的負(fù)載分擔(dān)硬件——F5,F(xiàn)5掛掉的時(shí)候,工程師都傻了眼。

例子6:文件不斷寫入導(dǎo)致磁盤滿的問(wèn)題

文件寫滿磁盤導(dǎo)致空間不夠的例子也非常常見(jiàn),絕大多數(shù)寫文件的場(chǎng)景大家都會(huì)留意到,并且在系統(tǒng)設(shè)計(jì)評(píng)審的時(shí)候都會(huì)有人站出來(lái)問(wèn),“xxx的文件寫入是否是可控的?”。但是,由于文件寫入的場(chǎng)景非常多,還是有很多情況被忽略。比如JVM的GC日志的打印,這樣的文件可以協(xié)助定位問(wèn)題,但是如果不設(shè)置文件上限大小參數(shù),就有導(dǎo)致磁盤空間不足的風(fēng)險(xiǎn);還有日志文件,絕大多數(shù)系統(tǒng)都有日志文件壓縮或者日志文件轉(zhuǎn)移的腳本,但是和前面提到的例子1一樣,一方是生產(chǎn)者,一方是消費(fèi)者,消費(fèi)者出了問(wèn)題,就會(huì)導(dǎo)致數(shù)據(jù)堆積。如果這樣的文件處理腳本執(zhí)行出現(xiàn)問(wèn)題,或者在系統(tǒng)壓力大以及系統(tǒng)異常情況頻繁的時(shí)候,日志瘋漲,來(lái)不及及時(shí)把日志文件轉(zhuǎn)移出去,導(dǎo)致日志文件把磁盤撐滿。通常對(duì)于要求比較高的服務(wù),磁盤空間監(jiān)控是必要的。

例子7:服務(wù)器掉電以后的快恢復(fù)

再說(shuō)一個(gè)問(wèn)題,這個(gè)問(wèn)題是從一個(gè)技術(shù)分享中流傳開來(lái)的。亞馬遜網(wǎng)站的數(shù)據(jù)都是頁(yè)面服務(wù)器先從緩存服務(wù)中獲取數(shù)據(jù),通常這個(gè)命中率很高,如果獲取不到數(shù)據(jù)或者數(shù)據(jù)過(guò)期以后再到數(shù)據(jù)庫(kù)里查詢。這樣的模式非常常見(jiàn),我們也總能看到很多技術(shù)報(bào)告里面寫平均的緩存命中率能夠達(dá)到百分之九十多,可以飆到多少多少的TPS,為此可以節(jié)約多少多少硬件成本。初看這樣的設(shè)計(jì)真不錯(cuò),但是很容易忽視的一點(diǎn)是,這樣的數(shù)據(jù)是建立在足夠長(zhǎng)時(shí)間,以及足夠多統(tǒng)計(jì)數(shù)據(jù)的基礎(chǔ)之上的,但是在單個(gè)時(shí)間段內(nèi),緩存命中率可以低到難以承受的地步,導(dǎo)致底層的數(shù)據(jù)服務(wù)直接被沖垮。有一次亞馬遜機(jī)房突然掉電,在恢復(fù)的時(shí)候把網(wǎng)頁(yè)服務(wù)器都通上電,這時(shí)候緩存服務(wù)還幾乎沒(méi)有緩存數(shù)據(jù),緩存命中率幾乎為零,于是大量的請(qǐng)求沖向數(shù)據(jù)庫(kù),直接把數(shù)據(jù)庫(kù)沖垮。外在的表現(xiàn)就是,掉電導(dǎo)致網(wǎng)站無(wú)法提供服務(wù),短期內(nèi)訪問(wèn)恢復(fù),隨后又喪失服務(wù)能力。

軟件當(dāng)中有些東西和經(jīng)驗(yàn)有密切關(guān)系,不像很相對(duì)容易提高的語(yǔ)言技能和算法,系統(tǒng)設(shè)計(jì)經(jīng)驗(yàn),尤其是對(duì)問(wèn)題的預(yù)估很需要時(shí)間和項(xiàng)目的磨煉。我不知道這樣的系統(tǒng)設(shè)計(jì)經(jīng)驗(yàn)怎樣才能快速積累,但是我想還是有一些常規(guī)模式可循,我不知道是否有比較經(jīng)典的資料可以學(xué)習(xí)。另一方面,系統(tǒng)設(shè)計(jì)真是一個(gè)細(xì)致和謹(jǐn)慎的活兒,不要隨意放過(guò)那些潛在的問(wèn)題,有時(shí)候甚至就是一點(diǎn)奇怪的感覺(jué),或者是設(shè)計(jì)圖看起來(lái)不那么協(xié)調(diào)和穩(wěn)當(dāng),細(xì)究下去,還真能發(fā)現(xiàn)陷阱。如果你也有類似的經(jīng)歷,不妨談一談。

原文鏈接:http://www.raychase.net/1615

責(zé)任編輯:林師授 來(lái)源: 四火的嘮叨
相關(guān)推薦

2015-10-12 15:40:48

容器容器存儲(chǔ)挑戰(zhàn)

2009-09-24 13:45:53

Hibernate性能

2015-02-28 15:22:15

2015-09-17 09:30:50

云架構(gòu)可伸縮性風(fēng)險(xiǎn)

2015-11-10 17:45:00

分布式系統(tǒng)設(shè)計(jì)開源模塊

2022-12-29 12:37:59

2011-12-19 14:28:14

Java設(shè)計(jì)模式

2012-07-10 15:55:55

移動(dòng)App應(yīng)用設(shè)計(jì)

2017-08-25 17:59:41

浮點(diǎn)運(yùn)算C語(yǔ)言

2020-06-22 14:03:39

物聯(lián)網(wǎng)以用戶為中心IOT

2012-09-10 10:59:49

網(wǎng)頁(yè)設(shè)計(jì)jQueryCSS

2015-06-16 09:53:48

swift蘋果開源

2021-05-08 10:36:31

開發(fā)Java Map

2021-03-26 00:00:05

?JavaMap設(shè)計(jì)

2012-03-12 13:55:22

交互設(shè)計(jì)

2017-01-03 19:12:56

數(shù)據(jù)中心冷卻機(jī)架

2020-04-21 15:18:11

財(cái)務(wù)信息化

2017-06-27 14:48:51

開發(fā)設(shè)計(jì)程序員

2019-12-20 13:51:30

加密劫持網(wǎng)絡(luò)攻擊漏洞

2018-02-27 16:49:07

比特幣激勵(lì)挖礦
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)