曾做過一些系統,對於圖片上傳的相關設計有些疑惑,經過後續的各方面研究,現有了能去除心中困惑的解決方案。
先說說以前做系統時遇到的設計問題:
有業務對象A,A中有各種屬性,這其中包括附加圖片的屬性,而A可以關聯多張圖片。當要新增一個對象A時,怎麼保存這些圖片信息呢?
當初想到了兩個方案:
①在點擊保存時,將對象A的全部屬性上傳,這包括所有圖片,然後在後臺將所有圖片整理後,將對應地址賦值給對象A,最後保存對象A。
②每選擇一張圖片時,會先上傳到服務器,然後返回相關圖片地址給前端頁面對象,當點擊保存時,頁面傳遞的就是對象A所有的屬性,此時關聯的是圖片在服務器的地址,此步驟並沒有上傳圖片。
對於這兩種種保存,可能會有失敗情況,怎麼解決數據的一致性問題?
對於①由於不可能使用事務來確保數據的一致,那麼只能使用try catch ,在拋出異常時,進行手動刪除相關的圖片。對於②同理,在保存對象失敗時,根據上傳的圖片地址進行刪除相關數據,但其實還是不能做到100%的確保,比如中途斷電情況,這些情況是忽略的,我們能做到的就是盡最大可能做到數據的一致性。
孰優孰劣
其實都不優,兩種方案處理數據一致性這個問題上並不好,而且①這種方案可能會存在併發問題。so...我想到了 定時任務 這種方案能解決數據一致性問題。最終方案是在②的基礎上增加定時任務,但怎麼設計呢?請聽吾慢慢分解:
①首先是數據庫表的設計:圖片對應的表,這裏叫image表吧,這個表除了記錄圖片的一些基本信息,還要增加一個過期時間的字段expired_time,用來記錄圖片過期的時間。
②在新增一個業務對象A時,每選擇一張圖片,都會先上傳到服務器,然後返回關聯的圖片對象信息(可以是保存的此條image記錄,用於顯示到頁面,在保存業務對象A時,保存與圖片的關聯關係)。此過程會保存圖片相關基本信息,對於expired_time這個字段的值爲當前時間(new Date())。
③在業務對象A保存成功後,注意:需要更新關聯的image記錄 ,將expired_time設置爲空。這兩個動作使用事務,若保存失敗,則expired_time不爲空。
④下面就是開始定時任務了,定時任務在凌晨將過期時間不爲空的記錄清空,同時刪除上傳的文件。
到這,以上方案基本很好地解決了圖片上傳的一些相關問題。enjoy it !