YYCache深入学习
深知,源碼還是一點點讀,加點讀書筆記,才可以深入挖掘,因此還是覺得每次讀源碼都記錄一番,無論好壞,如有寫錯,請斧正
簡介
YYCahce 是作為 ibireme 大神開源的一個YYkit組件庫中的一部分,YYCache提供了內存緩存,和持久性的硬盤緩存。
一個合理緩存應該有的設計
- 合理的增刪改查接口
- 高速緩存,提高常用緩存的返回性能和效率
- 低速緩存,磁盤大文件緩存
- 良好緩存限制策略
- 高性能,線程安全
基本設計思路
YYCache 提供對外的整合接口,YYMemoryCache 提供內存存儲緩存,通過lru算法進行處理,YYDiskCache提供file和sqlite3的兩種持久化存儲方式
YYMemoryCache
YYMemoryCahce 作為一個內存緩存,提供高速緩存,并且因為內存有限,需要進行一定的限制
線程安全
在頻率高的并發數據操作中,必須保證線程安全,不然拿到的數據不符合預期,或者導致讀寫沖突 在YYMemoryCache中,采用的pthread_mutex加鎖
pthread_mutex 定義了一組跨平臺的線程相關的 API,pthread_mutex 表示互斥鎖。互斥鎖的實現原理與信號量非常相似,不是使用忙等,而是阻塞線程并睡眠,需要進行上下文切換。
// 主要使用api pthread_mutex_lock(&mutex); // 申請鎖 // 臨界區pthread_mutex_unlock(&mutex); // 釋放鎖 復制代碼pthread_mutex支持遞歸鎖,遞歸鎖,就是在內部加鎖調用的時候,遞歸了自身,這樣子,會導致死鎖。
-
pthread_mutex則支持遞歸處理 attr PTHREAD_MUTEX_RECURSIVE
-
memory中使用pthread,在循環釋放的時候,通過pthread_mutex_trylock實現簡單的自旋鎖
原文:OSSpinLock 和 dispatch_semaphore 都不會產生特別明顯的死鎖,所以我也無法確定用 dispatch_semaphore 代替 OSSpinLock 是否正確。能夠肯定的是,用 pthread_mutex 是安全的。
LRU
最近使用優先,也就是認為,最近使用的,最大可能性會再次用到 里面實現用到一個雙向鏈表的結構進行處理,使用到的就會被移動到表頭 在刪除釋放的時候,就會從隊尾進行刪除釋放
通過創建鏈表節點node,進行間接操作數據
@interface _YYLinkedMapNode : NSObject {// 類似C中的private_extern,使用@private的話,限制太大,@package在類的鏡像外進行引用就會報錯// 使用@public @protect等的話,就沒什么限制的// 目的是,限制在本文件中使用@package__unsafe_unretained _YYLinkedMapNode *_prev; // 通過dic進行持有__unsafe_unretained _YYLinkedMapNode *_next; // 通過dic進行持有id _key;id _value;NSUInteger _cost;NSTimeInterval _time; } @end 復制代碼MemoryCache中使用的LRU的的算法進行刪除緩存,當超過一定的限制的時候,會進行循環清理,也就是說,memory里面的東西并不是存進去就會在app的生命周期中一直存在的,可能會被釋放掉。因此外部在使用的時候,需要判空處理的,如果為nil,則認為緩存已經失效,需要重新更新。
因此,YYMemoryCahce并不是數據在app的生命周期會被一直保留的,所以,在使用YYCahce最外層接口的時候,YYCache是會通過YYMemoryCache提供高速緩存,同時存入到低速緩存中。
獲取的時候,YYMemoryCache獲取不到,則會詢問YYDiskCache。
會在一段時間,自行檢查是否超過限制策略,超過則循環釋放。 YYMemoryCache默認在進入后臺的時候會進行檢查。 因為一次釋放太多,會導致資源消耗過大,因此,通過dispatch_aync block的方式,放到后臺線程釋放
YYDiskCache
disk中使用dispatch_semaphore信號量進行處理
dispatch_semaphore 是信號量,但當信號總量設為 1 時也可以當作鎖來。在沒有等待情況出現時,它的性能比 pthread_mutex 還要高,但一旦有等待情況出現時,性能就會下降許多。相對于 OSSpinLock 來說,它的優勢在于等待時不會消耗 CPU 資源。對磁盤緩存來說,它比較合適。
dispatch_semaphore是屬于閑等待,CPU不會消耗,因此,在做磁盤緩存的時候,用時較長,需要等待的話,會比較節省資源
- OSSpinLock 自旋鎖,不安全,所以使用了dispatch_semaphore進行處理,因為大文件,需要等待的情況較多
-
YYKVStorage 通過key value的一個封裝,實現增刪改查
-
YYKVStorage 實現細節:
- 提供對應的sqlite3的db增刪改查的接口,在操作的過程都做了防御式的操作
- 對sqlite的stmt也做了緩存,加速其性能
-
存儲方式有三個模式
- 文件
- sqlite3
- 混合 // 混合的情況有個閾值,大于閾值,則存文件
-
db sqlite3的使用細節
- sqlite3_stmt 操作數據的輔助數據接口,用于執行sql,并且返回結果
- stmt 也進行做了緩存,因為這個sql會重復不定期使用
-
優化: 可以升級最新版本的sqlite3,以此提高效率
YYCache
提供了增刪改查的API,底下調用的YYMemoryCache和YYDiskCache,封裝了一些基本邏輯。在save的時候,會保存到YYMemoryCache和YYDiskCache,讀取的時候,會優先讀取YYMemoryCache實現高速緩存,再讀取低速緩存。
參考
實際上在看的時候,下面這位大佬寫得更加清晰的,之所以我按自己的理解再寫一次,也是為了讓自己更好的研究,根據所有學習技巧來說,最重要的還是應用,因此有了這篇文章,希望之后能逐漸寫出一些更好blog
從 YYCache 源碼 Get 到如何設計一個優秀的緩存 - https://juejin.im/post/59f6e3b051882534af253d4a
ibireme blog - http://blog.ibireme.com/category/tec/ios-tec/
總結
以上是生活随笔為你收集整理的YYCache深入学习的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SpringMVC获取参数的几种方式
- 下一篇: nginx服务器配置/websocket