缓存过期策略设计
- 定时过期:
- 为每个缓存数据项设置一个固定的过期时间。例如,当缓存一个用户信息时,记录其缓存时间为当前时间加上设定的有效期(如30分钟)。在缓存数据存入缓存时就计算好过期时间并保存。
- 惰性过期:
- 只有在访问缓存数据时,才检查该数据是否过期。如果过期,则从缓存中移除。比如,在获取某个API响应的缓存数据时,先检查其过期时间,若已过期则重新请求API并更新缓存。
- 定期过期:
- 每隔一段时间,检查缓存中一定比例的数据项是否过期,并移除过期的数据。例如,每10分钟遍历缓存中20%的数据,检查其过期情况并处理。
程序中缓存过期的检测与处理实现
- 定时过期实现:
- 在缓存数据结构中添加一个属性记录过期时间,如
NSDate *expirationDate
。例如:
@interface CacheObject : NSObject
@property (nonatomic, strong) id data;
@property (nonatomic, strong) NSDate *expirationDate;
@end
@implementation CacheObject
@end
- (id)fetchCachedDataForKey:(NSString *)key {
CacheObject *cacheObj = [self.cacheDictionary objectForKey:key];
if (cacheObj && [cacheObj.expirationDate compare:[NSDate date]] != NSOrderedDescending) {
// 未过期,返回数据
return cacheObj.data;
} else {
// 过期,移除缓存
[self.cacheDictionary removeObjectForKey:key];
return nil;
}
}
- 惰性过期实现:
- 同样在缓存数据结构中记录过期时间。在获取缓存数据的方法中进行过期检查,如上述
fetchCachedDataForKey:
方法,在每次获取数据时检查是否过期,过期则移除。
- 定期过期实现:
- 使用
NSTimer
或GCD
定期执行检查任务。例如,使用NSTimer
:
- (void)startPeriodicExpirationCheck {
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:600 target:self selector:@selector(checkCacheForExpiration) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
}
- (void)checkCacheForExpiration {
NSArray *keys = [self.cacheDictionary allKeys];
NSInteger count = keys.count;
NSInteger checkCount = count * 0.2;
for (NSInteger i = 0; i < checkCount; i++) {
NSString *key = keys[i];
CacheObject *cacheObj = [self.cacheDictionary objectForKey:key];
if (cacheObj && [cacheObj.expirationDate compare:[NSDate date]] != NSOrderedDescending) {
[self.cacheDictionary removeObjectForKey:key];
}
}
}
高并发情况下保证过期处理的准确性和高效性
- 使用锁机制:
- 在对缓存进行读、写以及过期检查操作时,使用锁(如
NSLock
或dispatch_semaphore
)来保证线程安全。例如,使用NSLock
:
@interface CacheManager : NSObject
@property (nonatomic, strong) NSLock *cacheLock;
@property (nonatomic, strong) NSMutableDictionary<NSString *, CacheObject *> *cacheDictionary;
@end
@implementation CacheManager
- (instancetype)init {
self = [super init];
if (self) {
self.cacheLock = [[NSLock alloc] init];
self.cacheDictionary = [NSMutableDictionary dictionary];
}
return self;
}
- (id)fetchCachedDataForKey:(NSString *)key {
[self.cacheLock lock];
CacheObject *cacheObj = [self.cacheDictionary objectForKey:key];
if (cacheObj && [cacheObj.expirationDate compare:[NSDate date]] != NSOrderedDescending) {
// 未过期,返回数据
[self.cacheLock unlock];
return cacheObj.data;
} else {
// 过期,移除缓存
[self.cacheDictionary removeObjectForKey:key];
[self.cacheLock unlock];
return nil;
}
}
@end
- 优化数据结构:
- 采用哈希表(如
NSMutableDictionary
)来存储缓存数据,这样可以在O(1)的时间复杂度内进行数据的查找、插入和删除操作,提高过期处理效率。同时,可以考虑将缓存数据按照一定规则分区,减少锁的竞争范围。
- 异步处理:
- 对于过期数据的移除等耗时操作,可以使用
GCD
的异步队列来处理,避免阻塞主线程。例如,在检查到过期数据后,将移除操作放到异步队列中执行:
- (void)checkCacheForExpiration {
NSArray *keys = [self.cacheDictionary allKeys];
NSInteger count = keys.count;
NSInteger checkCount = count * 0.2;
for (NSInteger i = 0; i < checkCount; i++) {
NSString *key = keys[i];
CacheObject *cacheObj = [self.cacheDictionary objectForKey:key];
if (cacheObj && [cacheObj.expirationDate compare:[NSDate date]] != NSOrderedDescending) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self.cacheLock lock];
[self.cacheDictionary removeObjectForKey:key];
[self.cacheLock unlock];
});
}
}
}