1. <tr id="33chb"><label id="33chb"></label></tr>
  2. <pre id="33chb"></pre>
    當前位置:首頁 > 短網址資訊 > 正文內容

    從代碼層面優化系統性能的解決方案


    我們以前看到的很多架構變遷或者演進方面的文章大多都是針對架構方面的介紹,很少有針對代碼級別的性能優化介紹。本文將針對一些代碼細節方面的東西進行介紹,歡迎大家吐槽以及提建議。
    寫在前面

    上一篇 我們主要介紹了所遇到問題的五點,那么今天接下來討論剩下的問題,我們先再回顧一下之前討論的問題:

    1. 單臺 40TPS,加到 4 臺服務器能到 60TPS,擴展性幾乎沒有。

    2. 在實際生產環境中,經常出現數據庫死鎖導致整個服務中斷不可用。

    3. 數據庫事務亂用,導致事務占用時間太長。

    4. 在實際生產環境中,服務器經常出現內存溢出和 CPU 時間被占滿。

    5. 程序開發的過程中,考慮不全面,容錯很差,經常因為一個小 bug 而導致服務不可用。

    6. 程序中沒有打印關鍵日志,或者打印了日志,信息卻是無用信息沒有任何參考價值。

    7. 配置信息和變動不大的信息依然會從數據庫中頻繁讀取,導致數據庫 IO 很大。

    8. 項目拆分不徹底,一個 tomcat 中會布署多個項目 WAR 包。

    9. 因為基礎平臺的 bug,或者功能缺陷導致程序可用性降低。

    10. 程序接口中沒有限流策略,導致很多 vip 商戶直接拿我們的生產環境進行壓測,直接影響真正的服務可用性。

    11. 沒有故障降級策略,項目出了問題后解決的時間較長,或者直接粗暴的回滾項目,但是不一定能解決問題。

    12. 沒有合適的監控系統,不能準實時或者提前發現項目瓶頸。

    優化解決方案
    緩存優化方案

    針對配置信息和變動不大的信息可以放到緩存中,提高并發能力也能夠降低 IO 緩存,具體緩存優化策略可以參考我之前寫的:

    http://www.jianshu.com/p/d96906140199

    程序容錯優化方案

    在這一塊我要先舉一個程序的例子說明一下什么才是容錯,先看程序:


    注:

    那么如果 service 層的方法調用 dao 層的方法,一旦數據插入失敗,那么這種異常處理的方式是容錯嗎?

    把異常給吃掉了,在 service 層調用的時候,雖然沒有打印報錯信息,但是這能是容錯嗎?

    所謂容錯是指在故障存在的情況下計算機系統不失效,仍然能夠正常工作的特性。

    我們拿使用緩存來作為一個案例講解,先看一個圖:

    這是一個最簡單的圖,應用服務定期從 redis 中獲取配置信息,可能會有朋友認為這樣已經很穩定了,但是如果 Redis 出現問題呢?可能會有朋友說,Redis 會是集群,分片或者主從,確保不會出現問題。其實我是這樣的認為的,雖然應用服務程序盡量的保持輕量級是不錯的,但是不能因此而把希望全部寄托在中間組件上面,換句話說,如果此時的 Redis 是單點,那么后果會是什么樣的,那么隨著大量的并發請求到來的時候,程序中會報大量的錯誤,同時正常的流程也不能進行下去了業務也可能由此而中斷。

    那么在此種場景下我的解決方案是,要把緩存的使用分級別,有的緩存同步要求時效性非常高,比如支付限額配置,在后臺修改完成以后前臺立刻就能夠獲得感知,并且能夠成功切換,這種情況只能實時的從 Redis 中獲取最新數據,但是每次獲取完最新的數據后都可以同步更新本地緩存,當單點的 Redis 掛掉后,應用程序至少還能從本地讀取信息而不至于服務瞬間掛掉。有的緩存對時效性要求不高,允許有一定延遲,那么在這種情況下我采用的方案是,利用本地緩存和遠程緩存相結合的方式,如下圖所示:

    方案一:

    這種方式通過應用服務器的 Ehcache 定時輪詢 Redis 緩存服務器更同步更新本地緩存,缺點是因為每臺服務器定時 Ehcache 的時間不一樣,那么不同服務器刷新最新緩存的時間也不一樣,會產生數據不一致問題,對一致性要求不高可以使用。

    方案二:

    通過引入了 MQ 隊列,使每臺應用服務器的 Ehcache 同步偵聽 MQ 消息,這樣在一定程度上可以達到 準同步 更新數據,通過 MQ 推送或者拉取的方式,但是因為不同服務器之間的網絡速度的原因,所以也不能完全達到強一致性?;诖嗽硎褂?Zookeeper 等分布式協調通知組件也是如此。

    部分項目拆分不徹底

    拆分前

    注:

    一個 Tomcat 中布署多個應用 war 包,彼此之間互相牽制在并發量非常大的情況下性能降低非常明顯。

    拆分后

    注:

    拆分前的這種情況其實還是挺普遍,之前我一直認為項目中不會存在這種情況但是事實上還是存在了。解決的方法很簡單,每一個應用 war 只布在一個 tomcat 中,這樣應用程序之間就不會存在資源和連接數的競爭情況,性能和并發能力提交較為明顯。

    因基礎平臺組件功能不完善導致性能下降

    先看一段代碼:


    注:

    首先我們先不說這段代碼的格式如何如何,先看功能實現,使用 Future 來做超時控制,這是為何呢?原因其實是在我們調用的 Dubbo 接口上面,因為是 Dubbo 已經經過二次封裝,結果把自帶的 timeout 給淹沫了,程序員只能通過這種方式來控制超時,可以看到這種用法非常差勁,對程序性能造成一定的影響。

    如何快速定位程序性能瓶頸

    我相信在定位程序性能問題的時候,大家有很多種辦法,比如用 jdk 自帶的命令,如 Jcmd,Jstack,jmap,jhat,jstat,iostat,vmstat 等等命令,還可以用 VisualVM,MAT,JRockit 等可視化工具,我今天想說的是利用一個最簡單的命令就能夠定位到哪段程序可能存在性能問題,請看下面介紹:

    一般我們會通過 top 命令查看各個進程的 cpu 和內存占用情況,獲得到了我們的進程 id,然后我們將會通過 pstack 命令查看里邊的各個線程 id 以及對應的線程現在正在做什么事情,分析多組數據就可以獲得哪些線程里有慢操作影響了服務器的性能,從而得到解決方案。示例如下:


    由此可以判斷出來在 LWP 30222 這個線程產生了性能問題,執行時間長達 31.4 毫秒的時間,再觀察無非就是下面的幾個語句出現的問題,只需要簡單排查就知道了問題瓶頸。

    關于索引的優化

    組合索引的原則是偏左原則,所以在使用的時候需要多加注意;

    索引的數量不需要過多的添加,在添加的時候要考慮聚集索引和輔助索引,這二者的性能是有區別的;

    索引不會包含有 NULL 值的列:只要列中包含有 NULL 值都將不會被包含在索引中,復合索引中只要有一列含有 NULL 值,那么這一列對于此復合索引就是無效的。所以我們在數據庫設計時不要讓字段的默認值為 NULL。

    MySQL 索引排序:MySQL 查詢只使用一個索引,因此如果 where 子句中已經使用了索引的話,那么 order by 中的列是不會使用索引的。因此數據庫默認排序可以符合要求的情況下不要使用排序操作;盡量不要包含多個列的排序,如果需要最好給這些列創建復合索引。

    使用索引的注意事項

    以下操作符可以應用索引:

    • 大于等于

    • Between

    • IN

    • LIKE 不以 % 開頭

    以下操作符不能應用索引:

    • NOT IN

    • LIKE %_ 開頭

    索引技巧

    • 同樣是 1234567890,數值類型存儲遠比字符串節約存儲空間。

    • 節約存儲就是節約 IO,減少 IO 就是提升性能

    • 通常對數字的索引和檢索要比對字符串的索引和檢索效率更高。

    使用 Redis 需要注意的一些點
    • 在增加 key 的時候盡量設置過期時間,不然 Redis Server 的內存使用會達到系統物理內存的最大值,導致 Redis 使用 VM 降低系統性能

    • Redis Key 設計時應該盡可能短,Value 盡量不要使用復雜對象。

    • 將對象轉換成 JSON 對象(利用現成的 JSON 庫)后存入 Redis,

    • 將對象轉換成 Google 開源二進制協議對象(Google Protobuf,和 JSON 數據格式類似,但是因為是二進制表現,所以性能效率以及空間占用都比 JSON 要??;缺點是 Protobuf 的學習曲線比 JSON 大得多)

    • Redis 使用完以后一定要釋放連接,如下圖示例:

    不管是返回到連接池中還是直接釋放掉,總之就是要將連接還回去。

    關于長耗時方法的拆分

    我們拆分長耗時方法的一般技巧是:

    • 尋找業務的冗余點,代碼中有很多重復性的代碼,可以適當簡化。

    • 檢查庫表索引是否合理加入。

    • 利用單元測試或者壓力測試長耗時的操作進行算法級別優化,比如從庫中大批量讀取數據,或者長時間循環操作,或者死循環操作等等。

    • 尋找業務的拆分點,根據業務需求拆分同步操作為異步,比如可以使用消息隊列或者多線程異步化。

    經過以上幾個分析后如果方法執行時間仍然非常的長,這樣可能就是業務方面的需求使然,如下圖:

    那么我們是否可以考慮將一個長耗時方法進行拆分,拆分為多個短耗時方法由發起端分別調用,這樣在高并發的情況下不會造成某一個方法的長時間阻塞,在一定程度上能夠提高并發能力,如下圖:

    掃描二維碼推送至手機訪問。

    版權聲明:本文由短鏈接發布,如需轉載請注明出處。

    本文鏈接:http://www.virginiabusinesslawupdate.com/article_433.html

    標簽: 系統優化
    分享給朋友:

    相關文章

    FT12短網址:帶你走近比特幣背后的技術世界

    第一個要跟我們分享的是“私鑰”,這是暗碼學領域的一個概念。一般我們登錄微信、QQ 等都需求暗碼,這兒的“暗碼”實質上是一種口令、一種憑據。而“私鑰”則是非對稱暗碼體制的一部分,是能夠進行加解密計算、數字簽名認證的。跟 QQ 暗碼類似,私鑰是...

    攜程和餓了么隔空回懟 美團點評觸動了什么?

    攜程和餓了么隔空回懟 美團點評觸動了什么?

    2015年,王興帶領下的美團點評開始打破邊界,開疆拓土,當越來越多的友商抱怨“公牛闖進瓷器店”時,王興卻拋出了“互聯網下半場共存是常態”的新理論,“不冒進,廣交朋友,永不稱霸”。而600多年前,同樣內涵的話是這么說的:高筑墻,廣積糧,緩稱王...

    騰訊url.cn團隊移動App的網絡優化:短鏈接打開速度優化到原來15%歷程

    騰訊url.cn團隊移動App的網絡優化:短鏈接打開速度優化到原來15%歷程

    導讀:在移動應用開發中,應用上線了只是一個開始,噩夢在后面:手機越用越卡為哪般?手機發燙是為何?誰偷走了用戶的錢包?如何瘦成一道閃電?這些問題解決起來都是非常麻煩的,騰訊移動品質中心(url.cn)成立了專項測試團隊來解決這些問題。最近幾年...

    當蜜桃臀遇上緊身衣,這樣的小姐姐簡直無法抗拒!

    當蜜桃臀遇上緊身衣,這樣的小姐姐簡直無法抗拒!

    炎炎夏日當蜜桃臀搭配緊身胸衣是怎樣一種體驗?這大概是一種讓人血脈噴張的···超強體驗!所以在這個季節,我們特意為你準備了超實用超清涼的,蜜桃臀小姐姐健身教學小視頻!點開看吧INS超級火的SOMMER RAY健身妹子KATYA HENRY絕美...

    在線教育企業7成虧損,15%瀕臨倒閉,你如何突圍?

    在線教育企業7成虧損,15%瀕臨倒閉,你如何突圍?

    [ 億歐導讀 ] 四月暮春,又到了一年一度在線教育公司交作業的時期,無論是自己曬成績,還是第三方機構出評估,我們看到報表里的在線教育行業都是欣欣向榮、前景喜人,但真實情況如何?在線教育市場規模增幅迅猛,2019年將達2692.6億...

    幸存者偏差:實現成功不是復制成功者,而是學習失敗者

    幸存者偏差:實現成功不是復制成功者,而是學習失敗者

    轉眼2018年已即將接近尾聲,新的2019即將到來。時間飛逝,是否今年還未來得及回憶?還是徘徊在自己的一事無成中?FT12短網址的小編今天分享一篇心靈雞湯,預祝大家的即將到來的2019年能否有所成就。1英國著名魔術師和催眠師德倫·布朗在一個...

    發表評論

    訪客

    ◎歡迎參與討論,請在這里發表您的看法和觀點。
    一本色综合网久久
    1. <tr id="33chb"><label id="33chb"></label></tr>
    2. <pre id="33chb"></pre>