項目背景java
電商公司,核心服務重構,百億級數據遷移,服務必須保證7*24小時不中斷。mysql
遷移方案算法
A、數據轉換直接遷移到新庫sql
B、按分庫分表的shardId遷移數據庫
A方案在服務不中斷的時候存在兩個問題併發
一、遷移時數據更新很差處理分佈式
二、數據未遷移完成沒法切換到新系統,風險過大高併發
最終咱們選擇了B方案,每一個shardId下面的數據在一個事務中遷移,保證原子性、一致性。每一個shardId下的數據遷移完成後直接走新系統。性能
遷移耗時:5個小時測試
數據庫配置
阿里雲rds
原庫 MySql5.6 8核 16G 8000IOPS
新庫 MySql5.6 4核 8G 4000IOPS
數據庫方面的收穫
數據庫的性能主要包括了以下幾個方面
一、表設計
表設計的要求一般是知足三範式、列非空、合理的字段數據類型大小、適當冗餘。
二、sql語句調優
sql語句的性能一般應該控制在 10ms之內,以咱們千萬級別和億級別的表來講,單表查詢都是10ms之內。
其實sql的平均耗時5ms之內也並不過度。
sql語句調優一般就是建高效的索引了,注意索引的順序,聯合索引性能優於單個索引,explain查看執行計劃,索引的數據重複儘可能少。mysql除了memory存儲引擎,其餘都是隻支B+Tree算法。B+Tree 中每次Tree的節點發生變化,須要幾回操做從新構造樹,所以數據遷移的時候,能夠先刪除可有可無的索引。
三、數據庫的配置(IOPS,鏈接數,內存)
IOPS和鏈接數,內存做爲數據庫的配置以前瞭解不多,這些配置能夠給數據性能帶來顯著的提高。
一般8核 16G 8000IOPS 的數據庫每秒能支持 3000的qps。若是流量不集中,沒有高併發,徹底能夠承載千萬級的接口訪問量。固然數據庫內存大能減小數據庫的IO佔用,提升效率。而數據庫的鏈接數,雖然一般都支持2000,可是每一個應用可能都佔有數據庫鏈接,防止多用。另外
四、數據庫鏈接池的配置
數據庫鏈接池的配置,注意最小、最大鏈接數。一般一個應用不須要配過大的鏈接數,特別是對於集羣來講,若是每一個節點配置的最大鏈接數過大,可能超過數據庫的臨界值,並且會佔用數據庫的大量資源。
根據科特爾法則:每秒訪問頻率是3000 (W), 平均服務的時間5ms(λ), 那麼隊列的長度 L = λW =0.005*3000 =15。固然若是應用有流量高峯,也要防止數據庫忽然有大量請求。咱們系統的配置是最小5,最大30。
五、數據庫監控與併發支持。
注意要監控數據庫的性能和瓶頸,阿里雲的rds有很好的監控界面。若是數據庫的性能已達到瓶頸,不要認爲併發請求數據庫會帶來更好的性能。事實上,mysql對併發的支持並很差。還有要注意應用的併發和數據庫的併發是兩回事。mysql的監控最經常使用的是 SHOW FULL PROCESSLIST。對應mysql中的information_schema中的ProcessList表。
其餘注意的點:
一、沒有先進行單機測試,分佈式遷移功能浪費了開發時間。之後寫代碼仍是按正常流程來編寫。
由於數據大,開始想多臺機器,分佈式遷移。可是通過測試,瓶頸在數據庫上,一臺機器8核8G的機器已經知足要求了。
二、避免長事務、嵌套事務。這個應該儘可能杜絕,會帶來鎖等待和死鎖
三、線程池的配置,對於短小的任務能夠適當加大隊列的長度
四、數據遷移時爲其餘業務系統預留IO,防止某個應用大量佔用數據的IO。須要對數據遷移系統的線程池進行動態配置。java的線程池雖然提供了 setCorePoolSize()方法,可是默認只支持變大,不支持變小。 設置allowCoreThreadTimeOut能夠動態設置核心線程。