前言:
之前看了Casa大神的架構設計文章,醍醐灌頂,一直想開個系列文章記錄一下(這次就做個小小搬運工,別打臉),公司項目實在太忙,最近稍好些,就開始著手做這件事,這個系列共以下幾篇:
1. 搭建優質的App框架
2. view層的組織和調用方案(常用架構模式-MVC、MVCS、MVVM)
3. 網絡層設計方案
4. 數據持久化設計方案及動態部署
5. 組件化方案
在項目架構時,做數據持久化方案的設計是很重要的核心工作之一。數據持久化無論在服務器端和移動客戶端都是非常重要的技術工作。但是客戶端和服務器端持久化的側重點不同,在服務端,持久化方案的優劣往往都會在一定程度上影響到產品的性能。然而在客戶端,只有為數不多的業務需求會涉及持久化方案,而且在大多數情況下,持久化方案對性能的要求并不是特別苛刻。我在移動端這邊做持久化方案設計的時候,我更考慮的是以下幾點:
****用戶第一,做持久化希望解決用戶的問題****
1.在正常網絡下,快速提供給用戶必要的展示數據,提高APP的用戶體驗。
2.在網絡異常,甚至無網絡情況下,能讓應用提供基本功能。
3.在必要時無網絡情況下,用戶可進行必要操作,在有網情況下,同步數據。
4.減少對同一URL的請求次數,甚至只從服務器下載更新過或更改過的資源。節約用戶流量,并且也可以減少服務器請求壓力。
5.還有確保用戶敏感數據的安全。
****作為架構師做持久化還需關注的問題****
1.方案的長期可維護性和拓展性
2.持久化方案對APP的性能影響優化
3.方案對業務開發工程師是否友好
4.不同需求的緩存目錄的選擇
5.數據庫的讀寫隔離
6.數據庫的多線程實現和線程安全
7.數據庫的版本升級和遷移
****作為架構師做持久化需要了解APP的個別需求****
1.根據APP的特點采取不同的持久化方案
2.是否需要支持多用戶切換,以及多用戶切換帶來的數據庫遷移操作變化
3.是否有重要的敏感信息需要加密
****可供緩存方案的技術手段****
每個APP的功能需求不同,導致需要持久化的功能也有差異,面對不同的持久化需求,我們應該胸有成竹,手中有貨。作為架構師必須要知道的幾種持久化手段:
1.內存緩存
內存緩存主要為了節約用戶流量,避免相同URL請求多次相同的數據。內存緩存需要根據業務的更新的頻率和用戶請求數據的頻率來覺得內存緩存數據的有效期。實現內存緩存的技術手段有蘋果官方提供了NSURLCache,還有優秀的開源緩存庫YYCache(國內牛人開發)、PinCache(Pinster公司維護)。
2.磁盤緩存
- NSUserDefault
一般來說,小規模數據,弱業務相關數據,都可以放到NSUserDefault里面,內容比較多的數據,強業務相關的數據就不太適合NSUserDefault了。 - keychain
Keychain是蘋果提供的帶有可逆加密的存儲機制,普遍用在各種存密碼的需求上。另外,由于App卸載只要系統不重裝,Keychain中的數據依舊能夠得到保留,以及可被iCloud同步的特性,大家都會在這里存儲用戶唯一標識串。所以有需要加密、需要存iCloud的敏感小數據,一般都會放在Keychain。 - 文件存儲
文件存儲包括了Plist、archive、Stream等方式,一般結構化的數據或者需要方便查詢的數據,都會以Plist的方式去持久化。Archive方式適合存儲平時不太經常使用但很大量的數據,或者讀取之后希望直接對象化的數據,因為Archive會將對象及其對象關系序列化,以至于讀取數據的時候需要Decode很花時間,Decode的過程可以是解壓,也可以是對象化,這個可以根據具體<NSCoding>中的實現來決定。Stream就是一般的文件存儲了,一般用來存存圖片啊啥的,適用于比較經常使用,然而數據量又不算非常大的那種。 - 數據庫存儲
數據庫存儲的話,花樣就比較多了。蘋果自帶了一個Core Data,當然業界也有無數替代方案可選,不過真正用在iOS領域的除了Core Data外,就是FMDB比較多了。數據庫方案主要是為了便于增刪改查,當數據有狀態和類別的時候最好還是采用數據庫方案比較好,而且尤其是當這些狀態和類別都是強業務相關的時候,就更加要采用數據庫方案了。因為你不可能通過文件系統遍歷文件去甄別你需要獲取的屬于某個狀態或類別的數據,這么做成本就太大了。當然,特別大量的數據也不適合直接存儲數據庫,比如圖片或者文章這樣的數據,一般來說,都是數據庫存一個文件名,然后這個文件名指向的是某個圖片或者文章的文件。如果真的要做全文索引這種需求,建議最好還是掛個API丟到服務端去做。
3.應該用哪種緩存技術
在眾多可以本地保存數據的技術中,有三種脫穎而出:URL緩存、數據模型緩存(利用NSKeyedArchiver)和 SQLLite。假設你正在開發一個應用,需要緩存數據以改善應用表現出的性能,你應該實現按需緩存(使用數據模型緩存或URL緩存)。另一方面,如果需要數據能夠離線訪問,而且具有合理的存儲方式以便離線編輯,那么就用高級序列化技術(如Core Data,SQLLite)。
****緩存需求的種類****
- 按需緩存
獲取數據的速度比數據本身重要。 按需緩存是指把從服務器獲取的內容以某種格式存放在本地文件系統,之后對于每次請求,檢查緩存中是否存在這塊數據,只有當數據不存在(或者過期)的情況下才從服務器獲取。這樣的話,緩存層就和處理器的高速緩存差不多。 - 預緩存
預緩存是把內容放在本地以備將來訪問。數據對用戶離線情況下也非常有意義。對預緩存來說,數據丟失或者緩存出現問題是不可接受的,會給用戶帶來非常差的感官。實現預緩存可能需要一個后臺線程訪問數據并以有意義的格式保存,以便本地緩存無需重新連接服務器即可被編輯。編輯可能是“標記記錄為已讀”或“加入收藏”,或其他類似的操作。這里有意義的格式是指可以用這種方式保存內容,不用和服務器通信就可以在本地作出上面提到的修改,并且一旦再次連上網就可以把變更發送回服務器。 - 區分APP持久化需求的分類方法
選擇使用按需緩存還是預緩存的一個簡便方法是判斷是否需要在下載數據之后處理數據。后期處理數據可能是以用戶產生編輯的形式,也可能是更新下載的數據。如果一個應用需要做上面提到的任何后期處理,就必須實現預緩存。
****持久化設計方案****
- 按需緩存
對于按需緩存,因為這部分數據并不需要精確的管理,我們有很多的第三方框架解決,現在比較著名的有YYCache(國產精品),PinCache,TMCache(已經不再維護)。他們的共同點就是輕量級、內存和磁盤緩存支持、多線程和線程安全支持,也支持過期時間設置。 - 預緩存
預緩存的數據我們希望為用戶精確存儲,以方便增刪改查操作。因此我們可以使用CoreData、FMDB、Realm等解決方案。我個人覺得CoreData過度封裝和設計,導致靈活性不足,而且使用起來也是很麻煩的。相對而言我更喜歡FMDB,它給了我們更大的設計自由度,但為了達到更好的面向對象直接操作數據庫(目標要超越CoreData的方便,并且提供后期擴展到靈活性),我推薦大家可以使用第三方開源FSModel、LKDBHelper、JSONModel等框架。 - 解決方案
/****第三方庫****/
pod 'FMDB/SQLCipher', '~> 2.5'//自動導入FMDB和SQLCipher 實現數據庫操作和加密
pod 'LKDBHelper', '~> 2.1.9'//對FMDB的封裝,實現ORM面向對象操作數據庫
pod 'YYCache', '~> 1.0.2'//支持內存和磁盤緩存