先上源碼鏈接https://github.com/ibireme/YYCache
簡介
YYCache 是提供用用戶使用的對象,內(nèi)部對 YYMemoryCache 和 YYDiskCache功能的整合封裝。為 YYMemoryCache提供了多線程功能,而YYDiskCache對象本身內(nèi)部封裝了異步讀寫功能。
YYCache分為兩部分:磁盤緩存、內(nèi)存緩存。
內(nèi)存緩存(YYMemoryCache)
存儲的單元是_YYLinkedMapNode,除了key和value外,還存儲了它的前后Node的地址_prev、_next。整個實現(xiàn)基于_YYLinkedMap,它是一個雙向鏈表,除了存儲了字典_dic外,還存儲了頭結(jié)點和尾節(jié)點。它實現(xiàn)的功能很簡單:有新數(shù)據(jù)了插入鏈表頭部,訪問過的數(shù)據(jù)結(jié)點移到頭部,內(nèi)存緊張時把尾部的結(jié)點移除。就這樣實現(xiàn)了淘汰算法。因為內(nèi)存訪問速度很快,鎖占用的時間少,所以用的速度最快的OSSpinLockLock硬盤緩存(YYDiskCache)
采用 文件和數(shù)據(jù)庫相互配合的方式。有一個參數(shù)inlineThreshold(默認值20KB),小于它存數(shù)據(jù)庫,大于它存文件,能獲得效率的提高。key:path,value:cache存儲在NSMapTable里,根據(jù)path獲得cache,進行一系列的set、get、remove操作。
更底層的是YYKVStorage,它能直接對sqlite和文件系統(tǒng)進行讀寫。每次內(nèi)存超過限制時,select key, filename, size from manifest order by last_access_time desc limit ?1會根據(jù)時間排序,來刪除最近不常用的數(shù)據(jù)。硬盤訪問的時間比較長,如果用OSSpinLockLock鎖會造成CPU消耗過大,所以用的dispatch_semaphore_wait來做。
基本使用
一、同步方式存取
1.初始化緩存對象
- (nullable instancetype)initWithName:(NSString *)name;
- (nullable instancetype)initWithPath:(NSString *)path;
+ (nullable instancetype)cacheWithName:(NSString *)name;
+ (nullable instancetype)cacheWithPath:(NSString *)path;
這幾個方法功能是一致的。
如:
YYCache *cache = [[YYCache alloc] initWithName:@"APP_CACHE"];
2.存
id data; // 需要存儲的數(shù)據(jù)
YYCache *cache = [YYCache cacheWithName:@"APP_CACHE"];
[cache setObject:data forKey:@"data_key"];
首先調(diào)用內(nèi)存緩存設置緩存API(setObject:forKey:),然后調(diào)用磁盤緩存異步設置API(setObject:forKey:)
3.判斷是否有緩存
YYCache *cache = [YYCache cacheWithName:@"APP_CACHE"];
BOOL isContains = [cache containsObjectForKey:@"data_key"]
先去內(nèi)存緩存中查找,如果沒有查找就去磁盤緩存中找,找到就返回 YES。
4.取
YYCache *cache = [YYCache cacheWithName:@"APP_CACHE"];
id data = [cache objectForKey:@"data_key"];
先去內(nèi)存緩存中查找,有就返回。如果沒有就去磁盤緩存中找,找到了,先把緩存存入內(nèi)存緩存中,然后再返回結(jié)果。
5.移除緩存
YYCache *cache = [YYCache cacheWithName:@"APP_CACHE"];
//根據(jù)key移除緩存
[cache removeObjectForKey:@"data_key"];
//移除APP所有緩存
[cache removeAllObjects];
首先調(diào)用內(nèi)存緩存的刪除接口(removeObjectForKey:),然后調(diào)用磁盤緩存的刪除接口(removeObjectForKey:)
二、異步方式
存
YYCache *cache = [YYCache cacheWithName:@"APP_CACHE"];
id data; // 需要存儲的數(shù)據(jù)
[cache setObject:data forKey:@"data_key" withBlock:^{
NSLog(@"save sucess");
}];
首先調(diào)用內(nèi)存緩存設置緩存API(setObject:forKey:),然后調(diào)用磁盤緩存異步設置API(setObject:forKey:)
判斷緩存是否存在
[cache containsObjectForKey:@"data_key" withBlock:^(NSString * _Nonnull key, BOOL contains) {
if(contains){
//...
}
}];
同步在內(nèi)存中查找緩存,如果找到了,使用異步返回。如果沒找到,就調(diào)用磁盤緩存的異步查找 API,并把查找結(jié)果異步回調(diào)。
取
[cache objectForKey:@"data_key" withBlock:^(NSString * _Nonnull key, id<NSCoding> _Nonnull object) {
if(object){
// 獲取成功
}
}];
同步在內(nèi)存中查找,如果找到了,使用異步返回。如果沒找到,就調(diào)用磁盤緩存的異步查找 API,找到了,先把緩存存入內(nèi)存緩存中,然后再返回結(jié)果。
移除
//根據(jù)key移除緩存
[cache removeObjectForKey:@"data_key" withBlock:^(NSString * _Nonnull key) {
NSLog(@"removeObjectForKey: %@",key);
}];
//移除APP所有緩存
[cache removeAllObjectsWithBlock:^{
NSLog(@"removeAllObjects sucess");
}];
首先調(diào)用內(nèi)存緩存刪除接口(removeObjectForKey:),然后調(diào)用磁盤緩存異步刪除接口(removeObjectForKey:withBlock:)
移除所有緩存帶進度
[cache removeAllObjectsWithProgressBlock:^(int removedCount, int totalCount) {
NSLog(@" 已移除數(shù) :%d , 移除總數(shù): %d",removedCount,totalCount);
} endBlock:^(BOOL error) {
if(!error){
NSLog(@"sucess");
}else{
NSLog(@"error");
}
}];
緩存/ 磁盤單獨操作
YYCache *cache = [YYCache cacheWithName:@"APP_CACHE"];
YYDiskCache *diskCache = cache.diskCache;
YYMemoryCache *memoryCache = cache.memoryCache;
存取方法與cache 一致
緩存LRU清理
LRU(Least Recently Used)算法翻譯過來就是“最近最少使用”。LRU緩存原理,簡單的說就是,緩存一定量的數(shù)據(jù),當超過設定的閾值時就把一些過期的數(shù)據(jù)刪除掉。
比如緩存10000條數(shù)據(jù),當數(shù)據(jù)小于10000時可以隨意添加;當超過10000時,就需要把新的數(shù)據(jù)添加進來,同時要把過期數(shù)據(jù)刪除,以確保我們最大緩存10000條。
那怎么確定刪除哪條過期數(shù)據(jù)?采用LRU算法實現(xiàn)的話就是將最老的數(shù)據(jù)刪掉。
YYCache磁盤LRU清理并不是及時清理,而是后臺開啟一個定時任務進行RLU清理操作,定時默認是60s。
YYCache *yyCache=[YYCache cacheWithName:@"LCJCache"];
[yyCache.memoryCache setCountLimit:50]; //內(nèi)存最大緩存數(shù)據(jù)個數(shù)
[yyCache.memoryCache setCostLimit:1*1024];//內(nèi)存最大緩存開銷 目前這個毫無用處
[yyCache.diskCache setCostLimit:10*1024];//磁盤最大緩存開銷
[yyCache.diskCache setCountLimit:50]; //磁盤最大緩存數(shù)據(jù)個數(shù)
[yyCache.diskCache setAutoTrimInterval:60];//設置磁盤lru動態(tài)清理頻率 默認 60秒
相關資料
https://blog.ibireme.com/2015/10/26/yycache/
https://www.cnblogs.com/machao/p/7086675.html
http://www.itdecent.cn/p/5a63bdca4a21