最可能限制系統擴展能力的瓶頸

1. 二階提交

通常當數據庫中的數據有變化時,它會被寫入本地服務器的內存和磁盤中。但是,當數據庫是集羣或者分佈式系統的話,一個提交不僅會發生在本地,還會發生在遠程。二階提交意味着必須等待遠程服務確認。然後由於網絡和其他的延遲問題,這樣的提交相比單機數據庫的提交要慢很多。

主從的同步複製也有這樣的問題,因此,MySQL的解決辦法是半同步(semi-synchronous:MySQL5.5纔有的特性,半同步只需要等待slave寫成功日誌響應即可,並不需要等待slave完成真正的提交),這實際上是二階提交的妥協。

2. 串行處理

當顧客在等待擁有10臺收銀機的超市結賬時,這是並行工作的。如果有9個收銀員正在休息午餐,只有1個收銀機是開放的,那就變成串行的了。突然,超市就會因爲收銀機問題而排起長長的隊伍,讓顧客非常沮喪。

WEB應用一定要不惜一切代價避免串行,典型的串行比如分佈式鎖。否則,有串行處理的地方就會成爲你整個系統的瓶頸。

3. 內存不足

對於每一層來說,內存都是非常重要的。緩存最合適的地方有哪些呢?接下來舉幾個栗子。

  • 瀏覽器

瀏覽器緩存似乎遙不可及,直到您意識到瀏覽器直接從Web服務器獲取它渲染頁面需要的數據。因此,如果頁面中包含的對象有很長的過期時間,瀏覽器就能否把它們緩存起來,而不需要多次重複抓取。不僅對用戶體驗更快更好,而且也減輕了服務端的壓力。

  • 頁面緩存

頁面緩存(不是操作系統層面的pagecache)需要用到比如Varnish(https://www.varnish-cache.org/,淘寶和拼多多都有用過該技術)這樣的技術組件。它不能像Apache那樣處理複雜的頁面,但是它相比Apache能更好的處理簡單的頁面,因此它一般會被部署在Apache前面用來先處理簡單的頁面。

  • 對象緩存

一般會用redis(或者memcache)來處理對象緩存,對象先序列化成比如json,然後保存到redis中。我們的應用在訪問數據庫前,先訪問redis看是否有我們需要的對象,如果Redis中有,那麼從Redis中獲取對象的速度是MySQL數據庫的幾十倍甚至上百倍。從而能提高服務的響應速度,一眨眼就返回用戶請求的所有數據,讓用戶體驗更好。

4. 監控和指標不足

監控應該是如此基礎的東西,你無法想象沒有它的工作。 然而,有些公司和項目就是沒有,或者不足,沒有足夠的監控,一些服務器或關鍵組件被遺漏了。

隨着時間的推移,收集系統和服務器級數據以及應用程序和業務級可用性的數據同樣重要。

5. 日誌不足

日誌和監控關係非常密切,尤其當你定位問題或者調試的時候,你恨不得需要更多的日誌。無論是服務器系統日誌,Apache和MySQL日誌,緩存日誌等。而且需要做好日誌滾動,以及歷史日誌備份或者清理。

6. 數據庫單點

你的數據庫至少應該有一個slave,它的好處是當master出現問題後,slave頂上來能更快的恢復數據庫從而提供服務。哪怕你的slave不承擔讀的壓力,你也應該有一個冷備份的slave。

7. 把數據庫當作隊列

MySQL數據庫很擅長存儲關係型的表數據。不幸的是,它不太擅長作爲隊列服務。儘管如此,很多開發者依然有一些不好的使用習慣,例如:你的應用有一些JOB任務表,也許有一個狀態列,這個列的值有這些:INIT,PROCESSING,INQUEUE,FINISHED等。如果是這樣,那麼你無形之中把數據庫表當作隊列來使用了。

由於鎖爭奪以及掃描和輪詢以便找到更多可執行任務,這種解決方案最終會遇到可伸縮性問題,而且這種狀態列不太適合創建索引。如果有隊列方面的需求,更推薦使用RabbitMQ或者kafka。

8. 使用數據庫全文檢索

對任何一個應用來說,搜索都是非常重要的功能。儘管MySQL有全文檢索功能,但是它的前提是表必須是MyISAM引擎。然而MyISAM表沒有事務特性,而且它的性能和體驗都非常差。

成熟的方案都會藉助於專業的搜索服務,比如:Solr和ElasticSearch。而且這些專業的搜索服務客戶端支持非常多的語言,訪問速度也非常快。而且彈性伸縮能力都做的很好。

9. ORM

ORM有助於快速原型設計,並允許那些不擅長SQL的開發人員讀寫數據庫。它們更快,更乾淨,並提供更快的功能交付。

然後,當DBA發現一個運行緩存的SQL,並要你的團隊修復時,你會發現使用ORM框架的話,排查問題是非常困難的。但是,對於開發人員來說,排查並優化問題SQL是經常要做的事情。如果你的項目使用的是ORM,就會帶來巨大的技術債,而且替換的代價也非常大。所以建議項目使用MyBatis這樣的框架。

10. 沒有儀表盤

汽車如果沒有儀表盤,你將沒辦法開車。同樣的,如果你的應用沒有儀表盤,也會帶來很多阻礙。應用儀表盤能夠暴露應用程序內部工作的信息。他們記錄時間並提供有關應用程序花費時間的反饋。

一個非常流行的Web服務儀表盤解決方案是New Relic(http://newrelic.com/),它提供了吸引所有人的可視化儀表板 - 項目經理,開發人員,運營團隊,甚至業務部門都可以在圖表中查看並查看 發生了什麼。

11. 沒有代碼倉庫或者版本控制

儘管在今天來說,這樣的情況是非常罕見的。總之,你的公司千萬不要在這個方面成爲“鶴立雞羣”的那一家,一定要把代碼放到代碼倉庫中,強烈推薦Git+Gitlab組合管理。

如果你不用版本控制和代碼倉庫,那麼當你的項目越來越複雜時,欠下的技術債就會越來越多,最終導致整個迭代舉步維艱。

12. 單點問題

如果你的數據只存在某一單實例數據庫,這就是一個單點問題。如果你的服務全部部署在一臺服務器上或者一塊磁盤上,這也是單點問題。

這些單點問題必須不惜一切代價徹底消除它們。此外,意識到系統的單點問題也比較困難。比如,依賴單一的雲廠商,這實際上也是單點問題。因爲假如你的服務全部在AWS上,當AWS出問題時,你的服務是完全不可用的。AirBNB就在AWS出現故障時避免了這個問題,欲知更多,請戳鏈接:http://www.iheavy.com/2012/10/23/airbnb-didnt-have-to-fail/。

13. 預覽模式缺失

如果你嘗試在頭條上發表評論,或者在微信上發送一條朋友圈動態。你可能會收到這樣的提示信息:“對不起,請稍後再試!”。或者你在淘寶上只能預覽商品,但是不能下單。

這種現象就是指,應用允許你讀,但不允許你寫。這可能是master庫宕機了,但是slave庫還健在。我們的系統需要具備這種能力,當master庫宕機後,slave能正常的處理讀取操作,只是寫操作暫時受到影響。

14. 缺少溝通

在這裏談論溝通可能有點奇怪。但是強大的溝通渠道是非常有必要的,團隊成員必須知道在遇到麻煩時應該去找哪些人。而良好的溝通需要自信和知識淵博的領導力,以及傾聽和改進的開放性。

15. 缺乏文檔

文檔發生在Web應用程序的許多層中,比如:前端、UI、後端、運維等。開發人員需要設計文檔,以便爲查看該代碼的後來者提供提示和參考。運營團隊需要爲配置文件添加註釋,以便在事情中斷時提供更改歷史記錄和洞察力。並且應該在公司的wiki中記錄業務流程和關係,以幫助人們找到自己問題的解決方案。

文檔在各個層面都非常有幫助,寫文檔是每個人都應該具備的習慣。

16. 缺少故障演練

故障演練總是被一推再推。團隊可能會說,“我們有備份,我們能cover住這個事情。” 沒錯,直到他們嘗試根據備份恢復時才並發現它們不完整,可能丟失了一些配置文件或關鍵數據。

故障演練能夠幫助團隊在他們真正需要之前完成動作。您的公司應該把它當作運營團隊的一部分日常工作,每年幾次故障恢復整個應用程序。而且使用雲服務器會讓這個事情變得更容易。在這個過程中,您將瞭解需要多長時間,困難的步驟在哪裏,以及需要注意什麼。從而在當故障真正來臨時,能夠做到從容應對!

17. 魯莽行爲

你騎着快馬進入小鎮,帶着槍走進沙龍,你覺得你會交朋友嗎?不,你只會嚇唬所有人。信心很好,但最好與團隊合作,團隊的智慧比任何個人都要強。

團隊之間需要傳達正在改變的東西,以管理的方式進行溝通,任何意外等等都應該有應對計劃。謹慎才能贏得了勝利。並且始終有一個B計劃(Plan B),做的事情做好有回退的辦法,要知道哪些命令具有破壞性,哪些命令無法撤銷。

18. 日益增長的技術債

隨着應用程序多年來不斷髮展,團隊可能會花費越來越多的時間來維護歷史代碼,解決歷史問題。因此,他們沒有多少時間投入新功能。如果您發現技術債不斷增加,可能是時候咬緊牙關來一次重構了。重構需要時間,而且重構不會和開發新功能、滿足客戶需求一樣帶來立竿見影的效果,但從長遠來看,這是非常值得去做的。

 

本文翻譯自:http://highscalability.com/blog/2013/8/28/sean-hulls-20-biggest-bottlenecks-that-reduce-and-slow-down.html

發佈了71 篇原創文章 · 獲贊 159 · 訪問量 59萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章