架构设计系列(六):缓存

一、概述

在应用对外提供服务的时候其稳定性,性能会受到诸多因素的影响。缓存的作用是将频繁访问的数据缓存起来,避免资源重复消耗,提升系统服务的吞吐量。

二、缓存的应用场景

2.1 客户端

HTTP响应可以被浏览器缓存。我们第一次通过HTTP请求数据,它在HTTP报头中返回一个过期策略;我们再次请求数据,客户端应用程序首先尝试从浏览器缓存中检索数据。

2.2 CDN

CDN缓存静态web资源。客户端可以从附近的CDN节点检索数据。

2.3 负载均衡器

负载均衡器也可以缓存资源。

2.4 消息中间件

消息中间件用于削峰,在请求量大的场景下,引入消息中间件将请求消息缓存至中间件,待消费者消费处理。

2.5 应用服务本地缓存

这里是服务中的多层缓存。如果数据没有缓存在CPU缓存中,则服务将尝试从内存中检索数据。有时,该服务具有二级缓存,用于在磁盘上存储数据。

2.6 分布式缓存

像Redis这样的分布式缓存在内存中保存了多个服务的键值对。它提供了比数据库更好的读/写性能。

2.7 全文检索

我们有时需要使用全文搜索,如Elastic Search来进行文档搜索或日志搜索。数据的副本也会在搜索引擎中建立索引。

2.8 数据库

即使在数据库中,我们也有不同级别的缓存:

  • WAL(Write Ahead Log)预写日志:在构建B树索引之前,先进行WAL。
  • Bufferpool:分配给缓存查询结果的内存区域。
  • 物化视图(Materialized View):预先计算查询结果并将其存储在数据库表中,可以提升查询性能。
  • 事务日志(Transaction Log):记录所有事务和数据库更新
  • Replication Log:用于记录数据库集群的复制状态

三、Redis

3.1 redis的工作原理

  • Redis是一个基于RAM存储的。RAM读写速度比随机磁盘访问至少快1000倍。
  • Redis利用IO多路复用技术和单线程执行循环来提高执行效率。
  • Redis利用了高效的底层数据结构。

3.2 redis 的使用场景

以下列举的是常见的一些不单单作为缓存的应用场景:

  • Session:我们可以使用Redis在不同的服务之间共享用户会话数据。
  • Cache:我们可以使用Redis来缓存对象或页面,特别是对于热点数据。
  • 分布式锁:我们可以使用Redis字符串来获取分布式服务之间的锁。
  • 计数器:我们可以使用Redis记录文章的点赞数或阅读量。
  • 限流器:我们可以对某些用户ip应用速率限制。
  • 全局ID生成器:我们可以使用Redis 作为全局ID的生成。
  • 购物车:我们可以使用Redis Hash来表示实现购物车的功能。
  • 用户留存率:我们可以使用位图来表示用户每日登录并计算用户留存率。
  • 消息队列:使用Redis的List数据结构来实现简易化的消息队列。
  • 排名:我们可以使用ZSet对条目进行排序。

四、常用的缓存策略

设计大型系统通常需要仔细考虑缓存。下面是常用的五种缓存策略。

4.1 Cache-Aside 策略

流程

  • 当读取数据的时候,程序将会先去读取缓存,如果命中缓存则直接返回数据
  • 如果没有命中缓存则程序将去数据库查询数据,返回数据的同时也将缓存一份数据

总结

Cache-Aside 策略的优点是实现简单,只有被请求的数据才会被缓存起来,减少一些不必要数据的缓存。 但程序需要管理其时效性及一致性,增加了系统的复杂度。

该策略更多的使用在数据读取比较频繁,更新比较少的场景。

4.2 Read-Through 策略

流程

  • 程序只会读取缓存中的数据,如果命中缓存就直接返回数据。
  • 如果没有命中缓存缓存服务将会读取数据库数据加载进缓存并返回数据。

总结

Read-Through 策略 应用程序将不与数据库进行交互,简化了读取流程,由缓存系统自己管理缓存提高了数据的一致性。但缓存的写入需要单独处理,需要与其他写策略结合使用。

该策略适用于读写操作频繁的场景。

4.3 Write Through 策略

流程

  • 程序在接收到写入数据请求时,直接于缓存系统交互,写入缓存系统,然后缓存系统立即写入数据库。

总结

Read-Through 策略保证了数据的一致性,读取时总是能够在缓存中获取到最新的数据。但是每次写操作都需要更新两处数据储存,写入性能低。由于经常更新缓存对缓存的资源需求较高。

该策略适用于数据一致性要求比较高或者写操作比较低,读操作比较高的操作。

4.4 Write Back 策略

流程

  • 程序在接收到写入数据请求时,直接于缓存系统交互,写入缓存系统,但不会立即写入数据库,而是等待触发条件(如缓存满了,或者到达一定的时间间隔)之后才会批量一次性写入数据库。

总结

Write Back 策略 由于只更新缓存,所有对性能的提升显著,同时批量写入减少对数据的操作,减少资源的消耗。但存在数据不一致的风险,同时需要实现缓存的淘汰机制及批量会写数据的策略

该策略适用于写操作频繁并且对数据一致性要求不高的场景。

4.5 Write Around 策略

流程

  • 程序在接收到写入数据请求时,直接写入数据库
  • 在读取时程序先读取缓存,如缓存不命中,则程序从数据库读取,并更新缓存

总结

Write Around 策略避免了将不常用的数据写入缓存。但其首次读取数据都需要从数据库中加载,读取性能低,同时缓存命中率也低。

该策略适用于写操作频繁但读操作不频繁的场景。

相关推荐
李少兄19 分钟前
【java基础】Java 中的继承
java·开发语言
Ai 编码助手24 分钟前
idea里的插件spring boot helper 如何使用,有哪些强大的功能,该如何去习惯性的运用这些功能
java·spring boot·intellij-idea
web1376560764330 分钟前
快速上手 Spring Boot:基础使用详解
java·spring boot·后端
m0_7482365834 分钟前
Java高级开发进阶教程之系列
java·开发语言
猿小蔡-Cool36 分钟前
Java中将异步调用转为同步的五种方法
java·数据库·python
bing_1581 小时前
策略模式 (Strategy)详解
java
Utgnryk1 小时前
hot100-二叉树
java
hrrrrb1 小时前
【Java】I/O 流篇 —— 缓冲流
java·开发语言
IT闫1 小时前
【SpringBoot】——分组校验、自定义注解、登入验证(集成redis)、属性配置方式、多环境开发系统学习知识
java·spring boot·redis·后端
嘵奇1 小时前
Spring MVC框架二:创建第一个MVC程序
java·spring·mvc