数据随处缓存
该图说明了我们在典型架构中缓存数据的位置。
沿着流程有多个层次。
- 客户端应用程序:HTTP 响应可以由浏览器缓存。我们第一次通过 HTTP 请求数据,返回时在 HTTP 标头中包含过期策略;我们再次请求数据,客户端应用程序首先尝试从浏览器缓存中检索数据。
- CDN:CDN缓存静态网页资源。客户端可以从附近的CDN节点检索数据。
- 负载均衡器:负载均衡器也可以缓存资源。
- 消息传递基础设施:消息代理首先将消息存储在磁盘上,然后消费者按照自己的节奏检索消息。根据保留策略,数据会在Kafka集群中缓存一段时间。
- 服务:服务中有多层缓存。如果数据没有缓存在CPU缓存中,服务将尝试从内存中检索数据。有时服务有二级缓存来将数据存储在磁盘上。
- 分布式缓存:像Redis这样的分布式缓存在内存中保存多个服务的键值对。它提供比数据库更好的读/写性能。
- 全文搜索:我们有时需要使用全文搜索,例如Elastic Search来进行文档搜索或日志搜索。数据副本也会在搜索引擎中建立索引。
- 数据库:即使在数据库中,我们也有不同级别的缓存:
- WAL(Write-ahead Log):在构建B树索引之前,先将数据写入WAL
- Bufferpool:分配用于缓存查询结果的内存区域
- 物化视图:预先计算查询结果并将其存储在数据库表中以获得更好的查询性能
- 事务日志:记录所有事务和数据库更新
- 复制日志:用于记录数据库集群中的复制状态
为什么Redis这么快?
主要原因有3个,如下图所示。
- Redis 是一个基于 RAM 的数据存储。RAM 访问至少比随机磁盘访问快 1000 倍。
- Redis 利用 IO 多路复用和单线程执行循环来提高执行效率。
- Redis 利用多种高效的低级数据结构。
如何使用Redis?
Redis 不仅仅是缓存。
Redis 可用于多种场景,如图所示。
我们可以使用Redis在不同服务之间共享用户会话数据。
我们可以使用Redis来缓存对象或页面,尤其是热点数据。
我们可以使用Redis字符串来获取分布式服务之间的锁。
我们可以统计文章的点赞数或阅读量。
我们可以对某些用户 IP 应用速率限制器。
我们可以使用 Redis Int 作为全局 ID。
我们可以使用 Redis Hash 来表示购物车中的键值对。
我们可以使用Bitmap来表示每天的用户登录情况并计算用户留存情况。
我们可以使用 List 作为消息队列。
我们可以使用ZSet对文章进行排序。
顶级缓存策略
设计大型系统通常需要仔细考虑缓存。以下是五种常用的缓存策略。