缓存使用设计思考

419 阅读2分钟

我正在参与掘金创作者训练营第5期,点击了解活动详情

背景&目标

确保服务高可用的前提下,

  • 降低后端服务的负载能力,对一些频繁读取的功能和复杂计算的的功能增加缓存,降低后端的负载
  • 加快请求的响应时间,利用缓存优化数据读取,直接从缓存中读取比从 DB 中读取更快,从而优化用户的体验

现状分析

  • 避免缓存滥用,统一封装提供缓存层 controller--sevice--cache--dao

  • 部分业务功能因需强依赖缓存,需有容错机制或者可恢复机制

  • 缓存更新策略

    • 对于一致性要求比较高,在更新时数据时久更新缓存
    • 若允许数据不一致,可通过设置过期时间。到期后就可以重新获取再放置在缓存中再设置缓存过期时间
    • 缓存使用量超过预计最大值时可对现有数据进行删除,通过LRU/LFO/ FIFO算法进行删除

详细设计

规范缓存处理

制定缓存处理规范,避免所有的功能增加缓存时参差不齐,所以应该在一个项目里统一标准规范。要基于自己的项目情况考虑

  • 统一缓存层处理缓存
  • 确定场景是缓存还是存储,尽量避免强以来缓存
  • 坚持原则:无它也可,有它更强
  • set/hash/zset/list/tairhash/bloom/gis等大key(内部叫做godkey)不要超过3000,会记录sillylog
  • 避免使用keys,hgetall,lrange0-1等大range(使用scan替代)
  • 避免使用大value(10k以上就算大value,50k会记录)

详细的 redis 缓存规范可参考:阿里云登录 - 欢迎登录阿里云,安全稳定的云计算服务平台

基于抽象工厂模式设计

  • 定义 ICache 接口,其中定义了操作 Redis 的相关抽象方法

  • 定义 2 个具体的缓存类,实现了 ICache 接口,并实现所有的接口方法

  • 定义 1 个对外的 Cache 类,它也是实现了 ICache 接口。其中包含一个获取缓存 Client 的方法 driver 。实现了接口就要实现接口中所有的方法。每个方法都是完成具体的缓存 Client 的对应的方法

    func get(key string) interface{} {  
       return this.driver().get(key);  
    }
    

参考资料