來公司有一年時間了,一直在馬不停蹄的做著新的業務,但要想做好新業務就不能過多將時間消耗在其它方面。剛來的半年時間,我們消耗了30%左右的時間在時間系統維護上。我們一邊做新業務,一邊天天需要花時間在系統維護上,難免會心力交瘁,前半年由於剛來公司,需要大量時間熟悉現在系統,分析優點缺點,努力去發現問題,期間有很多想做的事一直沒有推進。我前後經過近一年的時間,參與了開發我們組幾乎所有核心模塊的代碼,所以對其中的問題基本把握的比較准確,半年後花了近三個月時間來重構優化系統(當然不是團隊停下來專門做重構,只能在新業務中擠時間),小有成果,這裡分享很大家:
我先簡單介紹下我們主體業務的幾個模塊以及對應的問題:(有一部分問題是因為數據量大造成的,其余是系統設計問題)
看到上面的問題,可以歸納出,在數據量大的時候,系統的基本功能都不能保證正常運轉,那麼應對的方案按優先級訂為:
功能不能正常運轉問題:
先來看個小故事:去年的某月提單高峰日,線上出現用戶反饋提單失敗,網站響應速度非常慢。因為之前未出現過同類現象,所以我們下意識的認為不應該是程序問題,是否是服務器的問題,但查看服務器的負載並未發現問題,由於半夜都未解決問題,最終我們領導剛准備睡覺最終提起脫了一半的褲子又來到公司與我們一起奮戰。後來溝通才得知是一批新的用戶使用了系統,他們的特點就是一次性提交的訂單數據非常多(一次2000以上)。之前系統由於沒有經過大量訂單的考驗所以沒有暴露出問題來,知道情況後經過分析確認是程序面對大量訂單時比較脆弱。下面是解決的一些主要問題小集合:
下面的這類查詢需求,想必是比較常見的,查詢指定范圍內的數據,擴展的目的是為了調用方便,容易理解
下面是擴展的方法以及問題描述
我並沒有嘗試去解決這個表達式的問題,直接改成Contains就解決問題了。
訂單達到一定數量時,在更新數據庫時會生成大量的SQL語句,容易形成SQL傳輸的網絡堵塞最終產生數據庫操作超時(之前提交2000個訂單時,單表需要生成2000行SQL),解決方案是按批次來處理,比如500條數據一個批次操作數據庫,將大批次改成小批次來處理就不會有問題。
原方案:用戶在導入數據的時候,顯示一個滾動的圖片,但這個滾動的圖片不是真正的進度條,用戶無法知道導入的進程到底什麼時間能夠完成。
新方案:
最嚴重的當數這些與金額相關的數據,由於系統設計的不夠嚴謹,導致金額數據出現負數。為了徹底堵住這個漏洞,我在實體模型上做了霸王條款:
所以我們在設計數據庫以及實體模型時,一定要確保數據在可掌控范圍內,決不能允許出現錯誤數據。
比如購買了一個訂單,數據是100個,用戶可隨意使用,使用一個就在訂單上記錄一個已使用的數據,最終到已使用數據=原訂單數量,其中用戶如果做退款下線,那麼這個已使用數據還需要回補回來。問題有主要有兩個:
我個人並不推薦采用這種利用一個數據庫字段來記錄核心數據的方案,因為它總是基於一個中間狀態在做運算,其中只要出現一個錯誤,後面的運算都會出錯,最起碼我們應該有數據監控,以確保這個結果值是正常的。
數據一致性問題:
除了從系統角度去發現問題的本質並解決,另外就是采用一種亡羊補牢的方式:數據監控以及數據的自動修復。將核心的業務數據監控起來,當發現有異常時通過一種報警機制通過相關負責人。能夠確認的問題可通過一些工具實現數據的自動修改,比如某些服務臨時調用失敗,我們就可以自動的重新調用直到成功為止。
性能問題:
可采取一些工具或者純人工記錄日志的方式,這裡我使用了dottrace,專打出頭鳥:
列表頁有一個批量的訂單,它會包含多個訂單,但列表為了顯示的統一,給這個批量的訂單也會顯示它的價格以及狀態,它的價格是下面所有子訂單的價格總和,訂單的狀態是下面所有子訂單的狀態中最小的狀態,所以應用了一個遞歸來查詢,非常消耗時間。經常與業務方溝通後,確認這兩個我們花了大量去計算的數據對業務方其實並沒有什麼實質的作用,果斷去掉,性能提升感覺是從地獄到了天堂。
總結:我們的目的就是為了用戶能夠愉快的使用系統,為此我們持續不斷的進行重構優化。優化都是相對的,我們不一定要找到最完美的方案,但保證用戶體驗是最基本的要求。