一、概述
在应用对外提供服务的时候其稳定性,性能会受到诸多因素的影响。缓存的作用是将频繁访问的数据缓存起来,避免资源重复消耗,提升系统服务的吞吐量。
二、缓存的应用场景
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
redis_30">3.1 redis的工作原理
- Redis是一个基于RAM存储的。RAM读写速度比随机磁盘访问至少快1000倍。
- Redis利用IO多路复用技术和单线程执行循环来提高执行效率。
- Redis利用了高效的底层数据结构。
redis__35">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 策略避免了将不常用的数据写入缓存。但其首次读取数据都需要从数据库中加载,读取性能低,同时缓存命中率也低。
该策略适用于写操作频繁但读操作不频繁的场景。