CDX一期上線的那天是我來公司最緊張的一天,由於這一天我要負責公司近5000張車型圖的導入工做。雖然在完成上傳和導入的代碼以後測試了不少遍,可是真正到了正式環境,卻真的很怕出問題。內搜、gift、以及本地和線上數據庫的同步,哪個環節出了問題都會影響上線的時間。如今一期上了線,也對本身圖片上傳導入這部分作一些總結,還有對現有方法不足之處的一些思考。web
其實一張圖的上傳邏輯仍是比較簡單的:spring
1. 上傳圖片到gift服務器。數據庫
2. 保存圖片信息到線上數據庫。瀏覽器
3. 將圖片信息按固定格式推送給內搜,便於以後檢索。服務器
如今公司有幾千張圖片,不可能人工的一張一張在頁面上傳,這就須要我來作一個批量上傳導入的腳本,實現邏輯大概以下:app
1. 從設計部門拷貝資源庫素材到本地。性能
2. 遍歷本地資源文件夾,取出全部的素材文件。測試
3. 把全部素材文件歸類,將對應路徑格式化爲標籤,作文件名的正則校驗,篩選出知足要求的素材。優化
4. 把取到的全部素材文件依次上傳到gift,壓縮圖傳到public空間,原圖傳到private空間。ui
5. 將上傳成功的素材信息,標籤等寫入本地數據庫。
6. 將圖片發佈,信息推送到內搜系統的隊列中。
7. 完成這個過程後,將本地數據庫新增的數據和線上數據庫進行同步。
看完這個過程,可能本身都會有疑問,爲何有一個本地和線上數據庫同步的步驟?這是因爲線上數據庫的鏈接地址vip只能線上服務器訪問,而本地並沒有權限,而且又不能把素材包和導入腳本通通放到線上環境去跑。這就致使了在這個過程當中間會產生短暫的不一致現象:展示在web端就是,搜索發現有了這個圖(由於內搜已經消費了推送數據),可是點開詳情卻發現無此圖片。
但這個問題仍是小問題,有個問題更沒法忽視:數據庫的主鍵是自增的,那如何保證數據庫同步的過程當中不會出現主鍵的衝突?這些都是我在下面想說的。
1. 批量上傳代碼的實現中的要點:
2. 導出過程錯誤日誌的配置:
在這些圖片導入的過程當中,若是某個圖片在某一環節拋了異常,有可能會出現內搜,gift,數據庫三方數據不一致的狀況,這是咱們絕對不容許的。因此必定要作錯誤日誌的記錄,導入完成去查看錯誤日誌,定位到某個圖片,從而解決對應的不一致數據。這裏的日誌配置以下:
<!-- 圖片導入環境 --> <springProfile name="import"> <logger name="com.xiaojukeji" level="error" /> <appender name="console" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>${normal-pattern}</pattern> <charset>${encoding}</charset> </encoder> </appender> <root level="error"> <appender-ref ref="console"/> </root> </springProfile>
能夠看到,我是新建了一個import的spring.profiles,在這個模式下,我只記錄錯誤的日誌信息,而且我這裏試輸出到了控制檯,便於我及時發現問題。(事實上,正式導入過程很順利,沒有出現任何問題~)
3. 數據庫同步的問題和思考
剛剛說到在全部圖片都導入gift和內搜的正式環境以後,須要把數據庫的新增信息同步到線上數據庫。因爲主鍵是自增的,實現的時候會有主鍵衝突的可能性。這裏暫時處理的方法並很差:取了一段主鍵間隔,並按歷史數據分析不會出現上傳量大於間隔的狀況,而後來避免這一衝突。(事實上,理論上仍是存在衝突的可能性)
那關於這一點的改進,我也想過一些方法。
首先想到的是但願用全局惟一的主鍵uuid代替自增主鍵。可是innodb的自增主鍵確實性能高,大多時候仍是須要採用的,反觀uuid,因爲長度很長,考慮因素頗多,致使其性能一直是人們詬病的地方。
而後看到部門的代碼腳手架中有一個IDGeneratorUtils,是公司內的一個主鍵生成器,裏面的思想相似於uuid,也會包含時間戳、機器碼等信息,可是實現比較輕量級,性能也會更好。
寫在最後:除了以上所說,這部分導入功能還包含了線程池,內存io等細節,不少地方都是能夠做爲優化點的。但願有時間有機會能夠採用這種方案進行改進,而且經過代碼的重構使得圖片導入的這個過程更加智能和方便。