缓存设计

互联网服务中,缓存是提高系统性能的重要手段。缓存的设计需要考虑的因素很多,包括缓存的类型、缓存的位置、缓存的更新策略、缓存的一致性等等。本文将从这些方面来介绍缓存的设计。

缓存

缓存,是一种存储数据的组件,它的作用是让对数据的请求更快地返回。实际上,凡是位于速度相差较大的两种硬件之间,用于协调两者数据传输速度差异的结构,均可称之为缓存。

技术为业务服务,缓存也不例外;在业务系统中,主要会用到以下几种缓存:

  • 本地缓存 (aka 进程内缓存)
  • 分布式缓存
  • 类似于 CDN 的静态数据缓存

进程内缓存

一般也叫 Local Cache, 是指缓存在应用进程内部的缓存,比如 Java 中的 HashMapConcurrentHashMap 等。这种缓存的特点是速度快,但是缓存的数据量有限,一般只能缓存一些热点数据;此外,这类缓存会引入多实例下数据短暂不一致的问题,所以在使用的时候要格外小心。

经常使用的 Local cache 有:Google Guava CacheCaffeineConcurrentHashMapEhcache 等。目前 Caffeine 是性能最好的 Local Cache。此外,leveldb 也是一种本地缓存的实现,但是它是基于磁盘的,所以性能不如上面几种。

什么时候需要用本地缓存?什么场景不适合用?

举几个场景

  • 黑名单用户 ID / 白名单用户 ID;这种数据量不大,但是访问频率很高,所以可以用本地缓存,在启动时加载,运行过程中随着 Admin 的添加或者删除而更新
  • 用户 ID 和 用户名、头像、昵称等的对应关系,由于某些原因我们一般指存储用户的 ID,当需要用户的其他信息时就需要从数据库中查询这些数据回来,如果每次都从 DB 中获取,显然对 DB 的压力很大,并且每次访问 DB 不是很有必要
  • 分布式配置中心,为了降低业务服务对配置中心的压力,一般都是将数据缓存在本地,当有新的配置发布后,会通知业务服务中配置中心的 client,然后拉取新的配置,或者推送新的配置

总结一下

  1. 数据读多写少且对一致性要求不高的场景;如果一致性要求非常高,需要考虑使用分布式缓存,并且还要考虑数据库与分布式缓存的一致性问题
  2. 对性能要求极其严苛的场景,比如秒杀、抢购等
  3. 只读数据的场景
  4. 分布式缓存的普适性更强一些,很多场景都可以用分布式缓存来解决,如非必要,不建议使用本地缓存 (也就是说用了也要慎重)

优势是什么?劣势是什么?

Local Cache 和应用服务处于同一个进程内,且存储在内存中,一个字:快;无论对于 RT、QPS 还是吞吐量,都有极大增益。此外,也节省了内网带宽。

依据服务无状态设计的原则:尽量把数据的状态和存储放在专门的数据存储服务中,实例节点本身只做计算,不把数据状态和某个实例做耦合,这样在水平扩展时才能收放自如。本地缓存其实在一定程度上引入了状态,所以一个最需要关心的问题就是数据一致性,这一点有别于分布式缓存。

  • 本地缓存:每个实例都有一份缓存,需要协调数据一致性问题
  • 分布式缓存:缓存数据集中存放在独立的缓存服务中,每个实例是不存在缓存数据的,但是需要考虑缓存和 SOR (Source of Record) 的一致性问题

目前有哪些本地缓存的实现方案,各自的优缺点?

  • 编程语言的内置数据结构,比如 Java 中的 HashMapConcurrentHashMap
  • Google guava
  • Caffeine
  • Encache
  • Leveldb / Rocksdb

本地缓存关注的技术点是什么?

  • 缓存命中率
  • 缓存容量
  • 缓存淘汰策略
  • 缓存一致性

分布式缓存

TODO

缓存规范

  • JSR107
  • Spring Cache

缓存实践

缓存可以应对高并发大流量的场景。

在做缓存设计时,有一些误区要避开:

  1. 把缓存作为服务间传递数据的通道,这个要避免
  2. 使用缓存没有考虑雪崩的情况,这个要考虑
  3. 多服务共享一个缓存实例,这个最好要避免,多个服务之间缓存做垂直拆分

找几个例子分析一下


References

Frameworks

https://bbs.huaweicloud.com/blogs/365239 https://mp.weixin.qq.com/s/36kVm4pfiy2vQEMToZ9--g https://cloud.tencent.com/developer/article/1546995 https://juejin.cn/post/6844903961078530062 https://mp.weixin.qq.com/s/YBpOz1dQ0sG15vGL7N0PeQ https://shniu.gitbook.io/cs/middleware/redis https://shniu.gitbook.io/cs/system-design/backend-store/cache-design https://tech.meituan.com/2017/03/17/cache-about.html http://highscalability.com/blog/2016/1/25/design-of-a-modern-cache.html https://juejin.cn/post/7151937376578142216 https://juejin.cn/column/7140852038258147358