ServiceStack:基于状态条件缓存对象的实现方案问询
针对体育赛事结果的ServiceStack条件缓存方案
这是个很常见的业务场景,直接用ServiceStack自带的ToOptimizedResultUsingCache确实满足不了这种“仅缓存已结束赛事”的需求,我给你两个实用的实现方案,你可以根据自己的代码风格选择:
方案一:在服务方法内直接做条件判断(简单直观)
这种方式最直接,在获取结果前先判断赛事状态,只对已结束的赛事启用缓存逻辑:
public object Get(GetEventResults request) { // 先从数据源获取赛事的基础状态信息 var eventInfo = GetEventDetails(request.EventId); if (eventInfo.IsCompleted) { // 赛事已结束,生成唯一缓存键(建议包含请求参数避免冲突) var cacheKey = $"EventResults_{request.EventId}_{request.Locale}"; // 使用缓存逻辑,这里设置24小时过期,可根据需求调整 return Request.ToOptimizedResultUsingCache( Cache, cacheKey, TimeSpan.FromHours(24), () => GetFinalizedEventResults(request.EventId) ); } else { // 赛事进行中,直接返回实时数据,不触发缓存 var liveResults = GetLiveEventResults(request.EventId); return Request.ToOptimizedResult(liveResults); } }
方案说明:
- 先通过
GetEventDetails确认赛事状态,确保只有已结束的赛事才走缓存流程 - 缓存键加入了
Locale参数作为示例,如果你有其他影响结果的请求参数,也应该加到缓存键里 - 进行中的赛事直接调用实时数据接口,并用
ToOptimizedResult做序列化优化,完全绕过缓存
方案二:自定义缓存过滤器(更优雅的属性式实现)
如果你习惯用ServiceStack的特性(Attribute)来管理缓存,可以自定义一个条件缓存特性,把状态判断逻辑封装起来:
首先,自定义缓存特性:
public class CacheCompletedEventsOnlyAttribute : CacheResponseAttribute { public override ICacheResponseDecorator CreateDecorator(IRequest req, IResponse res, object dto) { // 把请求DTO转成你的实际请求类型 var eventRequest = dto as GetEventResults; if (eventRequest == null) { return base.CreateDecorator(req, res, dto); } // 通过IOC获取赛事服务,查询赛事状态 var eventService = req.TryResolve<IEventService>(); var eventInfo = eventService.GetEventDetails(eventRequest.EventId); // 如果赛事未结束,返回一个不做缓存的装饰器 if (!eventInfo.IsCompleted) { return new NoCacheDecorator(); } // 赛事已结束,使用默认的缓存逻辑 return base.CreateDecorator(req, res, dto); } } // 自定义不缓存的装饰器,直接执行原方法逻辑 public class NoCacheDecorator : ICacheResponseDecorator { public object Execute(Func<object> invoke) => invoke(); public Task<object> ExecuteAsync(Func<Task<object>> invoke) => invoke(); }
然后在你的服务方法上使用这个特性:
// 设置缓存有效期为24小时(仅对已结束赛事生效) [CacheCompletedEventsOnly(Duration = 86400)] public object Get(GetEventResults request) { // 统一的结果获取逻辑,状态判断由过滤器处理 var results = GetEventResultsInternal(request.EventId); return Request.ToOptimizedResult(results); }
额外注意事项
- 缓存失效处理:如果已结束的赛事后续有数据修正(比如官方更新结果),记得手动调用
Cache.Remove(cacheKey)清除对应缓存,或者设置合理的过期时间让缓存自动刷新 - 状态判断可靠性:确保赛事状态的数据源是实时且可靠的,避免因为状态判断错误导致缓存了进行中的赛事数据
- 缓存键唯一性:一定要根据请求参数生成唯一的缓存键,避免不同赛事、不同请求条件的结果互相覆盖
内容的提问来源于stack exchange,提问作者taglius
相关产品推荐
相关产品推荐

