如無必要,勿增實體。
過早的優化是萬惡之源。
背景
一個抽獎活動,要求在展示獎品股票時,顯示股票價格。開發在實現這個功能的時候,用redis緩存每只股票的價格,每兩小時調用行情服務更新一次。
問為什么要做個緩存,而不是直接訪問行情服務直接讀取,給出了幾個理由:
- 減少對行情的請求,直接訪問redis一次就能查很多。
- 用緩存速度快。
- 獎品展示、獲獎排行榜都要用行情數據,防止不一致。
- 用行情的地方很多,不用每次請求行情服務。
- 前端需要拉取的數據,在需求范圍內,可以接受兩小時不變,不用每次重新計算。
但是這些理由都站不住腳,直接訪問行情服務並不會有問題。
優化過渡,過早加了緩存,增加了代碼的復雜度,產生了數據的不一致性。
沒有解決具體的問題,看到的只是一些表象,看似解決了問題。
思考
逐條思考下上面的幾點理由。
理由1. 減少對行情的請求,直接訪問redis一次就能查很多。
說法是對的,確實減少了對行情的訪問。但是為什么要減少對行情的訪問呢?
行情的服務很穩定,而且性能也很好,並沒有什么問題。沒有解決具體問題。
理由2. 用緩存速度快。
如果直接訪問行情數據源速度是瓶頸嗎,有遇到性能問題嗎?沒有。行情也是內存訪問,速度不一定比redis慢的。而且開發也沒有數據支撐。
理由3. 獎品展示、獲獎排行榜都要用行情數據,防止不一致。
為什么要一致,不一致有什么問題?對於排行榜,大家都有預期,是一定時間才更新一次的,只要在排行榜界面有說明即可。就像游戲的排行榜,很多都是24小時更新一次。沒有必要為了和排行榜數據一致,而修改代碼。這個問題在產品形態上就能解決,也是個偽問題。
理由4. 用行情的地方很多,不用每次請求行情服務。
同理由1,多怎么了?正常訪問就可以了,如果性能瓶頸再優化。
理由5. 前端需要拉取的數據,在需求范圍內,可以接受兩小時不變,不用每次重新計算。
具體的產品形態,可以有加緩存的余地,但不意味着必須要加緩存。除非遇到有性能問題,否則代碼的可維護性、穩定性是最重要的。
再換個角度,如果行情的接口性能真的很慢,要怎么優化呢?
不是直接暴露redis接口的,有更好的方法。
把行情獲取部分單獨封裝成為一個獨立函數,對外不依賴具體的內部實現。
不管是直接訪問行情服務、讀緩存,還是訪問一個單獨封裝的優化行情服務模塊,對外接口都不變。
整理下常見的避免過渡優化場景:
1、能同步實現的代碼,就不要用異步;
2、能實時實現的代碼,就不要用定時;
3、能用數據源讀取的,就不要用緩存。
先保證程序簡潔,滿足性能要求,等遇到問題的時候,再去優化,避免過早優化,引入問題。
總結
解決問題前,先思考是否有問題,問題是什么,而不是直接去做。
「如無必要,勿增實體」代碼模塊中,在沒有遇到問題時,不要引入過多的模塊,緩存,增加代碼的復雜性。既不易於閱讀,也不易於維護。
遇到性能優化,不優化有問題,優化過渡,即使沒產生問題,也是浪費。
