缓存架构设计

原创
2016/03/29 18:57
阅读数 251
  1. 缓存使用场景
      缓存是提高应用程序性能的最常见的一种技术,常适用于读多写少的场景。按照架构层次可以分为:客户端缓存、页面缓存、应用缓存、持久层缓存。
      其中应用缓存设计最为复杂,本文主要讨论应用缓存的设计。
  2. 更新or淘汰
      缓存的存储一般为键值对的方式,存储的值可能为对象或集合或单值,比如用户信息、购物车列表、阅读计数等。而缓存发生变化时的更新则存在两种策略:更新or淘汰。一般来说淘汰最为简单。
      淘汰数据可以简单的将缓存删除,更新数据则需要将新的值放入缓存中;淘汰数据会导致查找缓存时的一次miss,而更新缓存则不存在此问题,特别时某些复杂场景下淘汰缓存可能会导致缓存穿透。
      如果更新缓存不需要增加额外的复杂计算或者分支流程推荐使用更新缓存的策略。另外如果对主线流程的响应速度要求比较高可以采用异步方式更新缓存。
  3. 缓存对象or单值数据
      一般倾向于缓存单值数据而非对象,当然不包含其它业务对象的数据可视为单值数据(可以存储为string)。例如redis,支持List、Hash、Set(ZSet)和String,对于其中的集合对象可以根据不同的业务场景选用。
      存储一个复杂对象需要将对象的属性拆分成不同的key-value来存储,比如:
    Book{
    string id;
    int buyCount;
    string name;
    }。
    可以拆分成:
    Book.ID.buyCount = buyCount、Book.ID.name = name。
    这样的存储会加大缓存对象的读写开销。如果buyCount不需要单独读写则可视为单值数据,可以以json的方式存取。具体如何选择需要视不同场景而定。
  4. 缓存穿透与失效
      缓存设计不得不考虑的另一个问题是缓存穿透与失效时的雪崩效应。缓存穿透是指查询一个一定不存在的数据,由于缓存miss时会从持久存储(DB)中查询数据,并且出于容错考虑查不到数据的时候不会写入缓存,这将导致每次查询这个数据时都要到存储层去查询,而失去了缓存的意义。
      缓存穿透:有很多种方法可以有效地解决缓存穿透问题,最常见的则是采用布隆过滤器,将所有可能存在的数据hash到一个足够大的bitmap中,一个一定不存在的数据会被 这个bitmap拦截掉,从而避免了对持久存储(DB)的查询压力,这种方法的缺陷是hash及查询bitmap的性能开销以及bitmap的存储开销,在极端情况下会导致得不偿失。另外一种方法是将n巨ull最为这个数据的值放入缓存并设定缓存的失效时间,这种方法的缺陷是低频的缓存穿透以及失效时间可能带来的性能开销(特别是在分布式的缓存系统中)。
      缓存失效:这个问题目前并没有很完美的解决方案。大多数系统设计者考虑用加锁或者队列的方式保证缓存的单线 程(进程)写,从而避免失效时大量的并发请求落到持久存储层(DB)上。当然并发量不是特别大的系统不需要处理。
  5. 触发时机
      程序中我们可以在数据持久之间更新缓存或者在数据持久之后更新缓存。
      在数据持久之前更新缓存会存在这样的问题:缓存更新成功,数据持久失败。这种情况下需要额外的回馈机制处理缓存的回滚,复杂且不够高效。
      而在数据持久之后更新缓存则可能会存在数据持久成功,缓存更新失败的情况,这种情况下需要再次更新缓存或者直接失效缓存,同样需要额外的回馈机制处理缓存更新失败的情况。
      如何选择需要考虑的是对主线业务的影响大小以及缓存脏数据对系统的影响大小,一般来说缓存脏数据并不会造成系统性的影响。
  6. 分布式缓存
    缓存系统需要考虑几个问题:

    • 缓存本身的水平线性扩展问题
    • 缓存大并发下的本身的性能问题
    • 缓存的单点故障问题(多副本和副本一致性)

    而由此催发出来的分布式缓存系统则需要额外考虑这几个问题

    • 系统本身的管理问题,包括了存储空间的分配、扩展、回收机制
    • 分布式节点管理和路由算法
    • 缓存键值的管理

    成熟的分布式缓存系统有Redis、Memcached、Ehcache、阿里云的OSC等等,各个系统的使用场景和实现方式各不相同这里不再深究。

  7. 缓存+数据库
      通常我们使用缓存是配合数据库特别是关系型数据库,而数据库则存在主从、读写分离等提高性能和可用性的方案。在这样的情况下,设计缓存系统需要特别注意数据的分发传递速度以及数据库单点故障可能导致的缓存更新失败。没有特殊处理的话可能会引发数据库数据与缓存数据的不一致。
  8. 服务化
      缓存系统需要对外提供统一透明的服务API,你懂的,不解释!
展开阅读全文
打赏
1
5 收藏
分享
加载中
更多评论
打赏
0 评论
5 收藏
1
分享
返回顶部
顶部