缓存架构设计
需求分析
缓存是一种提高系统读性能的常见技术,对于读多写少的应用场景,我们经常使用缓存来进行优化。
例如对于用户的余额信息表account(uid, money),业务上的需求是:
- 查询用户的余额,SELECT money FROM account WHERE uid=XXX,占99%的请求
- 更改用户余额,UPDATE account SET money=XXX WHERE uid=XXX,占1%的请求
由于大部分的请求是查询,我们在缓存中建立uid到money的键值对,能够极大降低数据库的压力。
读操作流程
有了数据库和缓存两个地方存放数据之后(uid->money),每当需要读取相关数据时(money),操作流程一般是这样的:
- 读取缓存中是否有相关数据,uid->money
- 如果缓存中有相关数据money,则返回【这就是所谓的数据命中“hit”】
- 如果缓存中没有相关数据money,则从数据库读取相关数据money【这就是所谓的数据未命中“miss”】,放入缓存中uid->money,再返回
缓存的命中率 = 命中缓存请求个数/总缓存访问请求个数 = hit/(hit+miss)
上面举例的余额场景,99%的读,1%的写,这个缓存的命中率是非常高的,会在95%以上。
问题
当数据money发生变化的时候:
- 是更新缓存中的数据,还是淘汰缓存中的数据呢?
- 是先操纵数据库中的数据再操纵缓存中的数据,还是先操纵缓存中的数据再操纵数据库中的数据呢?
- 缓存与数据库的操作,在架构上是否有优化的空间呢?
更新缓存 VS 淘汰缓存
- 什么是更新缓存:数据不但写入数据库,还会写入缓存
- 什么是淘汰缓存:数据只会写入数据库,不会写入缓存,只会把数据淘汰掉
- 更新缓存的优点:缓存不会增加一次miss,命中率高
- 淘汰缓存的优点:简单
选择的关键:更新缓存的复杂度
情况一:只是简单的把余额money设置成一个值
- 淘汰缓存的操作为deleteCache(uid)
- 更新缓存的操作为setCache(uid, money)
更新缓存的代价很小,此时我们应该更倾向于更新缓存,以保证更高的缓存命中率。
情况二:如果余额是通过很复杂的数据计算得出来的,例如业务上除了账户表account,还有商品表
product,折扣表discount
account(uid, money)
product(pid, type, price, pinfo)
discount(type, zhekou)
业务场景是用户买了一个商品product,这个商品的价格是price,这个商品从属于type类商品,type类商品在做促销活动要打折扣zhekou,购买了商品过后,这个余额的计算就复杂了,需要:
- 先把商品的品类,价格取出来:SELECT type, price FROM product WHERE pid=XXX
- 再把这个品类的折扣取出来:SELECT zhekou FROM discount WHERE type=XXX
- 再把原有余额从缓存中查询出来money = getCache(uid)
- 再把新的余额写入到缓存中去setCache(uid, money-price*zhekou)
更新缓存的代价很大,此时我们应该更倾向于淘汰缓存。
建议
淘汰缓存操作简单,并且带来的副作用只是增加了一次cache miss,建议作为通用的处理方式。
先操作数据库 vs 先操作缓存
这个比较主要是针对写操作的,最根本性的问题就是保证数据的一致性,因为操作数据库和缓存不是原子性的,所以一旦中间出现什么错,有可能会导致数据不一致的情况,就要从下面情况来细说:
- add数据时,应该先写数据库,还是先写缓存?
- update数据时,如果选择淘汰cache,应该先更新数据库还是缓存?
- update数据时,如果选择更新cache,应该先更细数据库还是缓存?
add数据时,怎么选择?
很显然,这是啥先写数据库,然后再写缓存,即使后面写缓存失败,顶多出现一次cache miss,最起码数据库已经持久化了;如果反过来,一旦写数据失败,那么缓存将会是脏数据,除非自己加上写缓存失败时,delete掉数据库的数据,这样太麻烦了。
update数据时,选择淘汰cache,那应该先更新哪个?
记住这个准则,如果出现不一致,谁先做对业务的影响较小,就谁先执行。下面对两种情况进行业务上的比较:
假设先写数据库,再淘汰缓存:第一步写数据库操作成功,第二步淘汰缓存失败,则会出现DB中是新数据,Cache中是旧数据,数据不一致。
假设先淘汰缓存,再写数据库:第一步淘汰缓存成功,第二步写数据库失败,则只会引发一次Cache miss。
结论
先淘汰缓存,再写数据库。
update数据时,选择更新cache,那应该先更新哪个?
细想,无论是先更新数据库再更新缓存,还是先更新缓存再更新数据库,一旦后面的操作失败,都有可能出现数据不一致。所以,根据上面的解决方法,进行了改进:
情况一:更新或新增缓存代价比较大
- 先删除缓存
- 然后更新数据库
- 等下次查询时,首先cache miss,查询出数据后再增加缓存
情况二:更新或新增缓存代价小
- 先删除缓存
- 然后更新数据库
- 再将新数据新增到缓存
情况三:如果缓存服务器很稳定,基本上能够保证修改或查询不会出问题
- 更新数据库
- 然后更新缓存
缓存架构优化
前面提到的缓存架构有一个缺点:业务方需要同时关注缓存与DB,有没有进一步的优化空间呢?有两种常见的方案,一种主流方案,一种非主流方案。
主流优化方案
服务化:加入一个服务层,向上游提供帅气的数据访问接口,向上游屏蔽底层数据存储的细节,这样业务线不需要关注数据是来自于cache还是DB。
非主流方案
异步缓存更新:业务线所有的写操作都走数据库,所有的读操作都总缓存,由一个异步的工具来做数据库与缓存之间数据的同步,具体细节是:
- 要有一个init cache的过程,将需要缓存的数据全量写入cache
- 如果DB有写操作,异步更新程序读取binlog,更新cache
在(1)和(2)的合作下,cache中有全部的数据,这样:
- 业务线读cache,一定能够hit(很短的时间内,可能有脏数据),无需关注数据库
- 业务线写DB,cache中能得到异步更新,无需关注缓存
缺点
这样将大大简化业务线的调用逻辑,存在的缺点是,如果缓存的数据业务逻辑比较复杂,async-update异步更新的逻辑可能也会比较复杂。
相关推荐
### Rails缓存架构设计 #### 一、高性能Web应用与缓存架构的重要意义 在现代互联网环境下,构建高性能Web应用面临着前所未有的挑战。随着用户数量的激增和技术的发展,Web应用不仅需要处理大规模且高并发的访问...
### 缓存架构设计细节分析 #### 一、需求缘起及应用场景 缓存作为一种提升系统性能的关键技术,尤其适用于那些读操作远多于写操作的场景。在具体的应用场景中,比如用户的账户余额信息表(account(uid, money)),...
数据库多级缓存架构设计 数据库多级缓存架构设计是解决高并发低延迟要求复杂场景的解决方案。缓存设计的重要性在于解决 CPU 运算速度远大于内存读写速度的问题,缓存的出现主要是为了解决这个问题。传统的 CPU 通过...
本文档聚焦于亿级流量系统的多级缓存架构设计,其中涉及的关键知识点包括异常控制、错误编码、异步处理、CAP定理、分布式系统的一致性问题、以及高可用架构设计等。 首先,异常控制与错误编码是系统稳定运行的基石...
缓存架构设计时要考虑以下要点: 1. **缓存一致性**:更新策略如Write-Through、Write-Around、Write-Behind等,保证数据的一致性。 2. **缓存失效策略**:LRU(Least Recently Used)、LFU(Least Frequently Used...
【基于Redis的分布式缓存系统架构分析】 在现代高并发的互联网应用中,为了提高数据访问的速度和系统性能,往往采用缓存技术。基于Redis的分布式缓存系统因其高效、灵活的特点,被广泛应用于大型应用系统中。Redis...
#### 缓存架构设计目标概览 在大型促销活动中,比如每年的“双十一”,如何有效地处理零点时的访问峰值成为了众多电商平台面临的重大挑战之一。为了更好地应对这种瞬时高并发情况,本课程旨在帮助学员掌握缓存技术...
#### 三、缓存架构设计原则 在设计缓存架构时,需要遵循以下原则: - **一致性**:确保缓存中的数据与源数据保持一致,避免出现数据不一致的问题。 - **容错性**:缓存系统应该具备高可用性和容错能力,能够在部分...
2. **缓存一致性**:保持缓存数据与后端数据的一致性是缓存架构设计中的核心问题。微博采用的可能是失效策略(缓存失效后从后端重新加载)或者更新策略(对数据的任何更改都会实时更新到缓存中)。 3. **分布式缓存...
本文将对在线教育平台的架构设计进行详细的说明,涵盖产品架构、技术架构、架构设计关键点、数据库架构设计、消息队列架构设计、缓存架构设计、核心业务流程等方面。 第一部分:总体方案 在线教育平台架构主要包含...
本课程通过大白话解释和实际操作演示,旨在帮助开发者掌握高级缓存架构设计和高可用分布式系统架构的知识,解决复杂场景下的技术挑战。通过学习,你将能够设计和实现亿级流量电商网站的商品详情页系统,以及应对各种...
1. 文件有点大,[下载demo1](https://github.com/kepuna/cacheDemo1) 2. 关于详细的解释说明已经发布到[个人简书](http://www.jianshu.com/u/a641ef2b6bc1),欢迎交流
**实现多级缓存架构设计方案概述** TMC,即透明多级缓存,是由有赞PaaS团队开发的,旨在解决公司内部应用的缓存管理问题,特别是针对高并发下的热点访问。传统的分布式缓存解决方案,如CodisProxy + Redis或zanKV,...
【高性能网站架构设计之缓存篇】探讨了如何在网站架构中有效利用缓存提升性能。缓存是解决高并发、大数据量访问问题的关键技术,它通过存储热门数据,减少对数据库的直接访问,从而提高响应速度。在这个主题中,我们...
### 阿里双十一系统项目实战(缓存架构+高可用服务架构+微服务架构) #### 缓存架构 在大型互联网系统中,缓存架构是提高系统性能和响应速度的关键技术之一。尤其是在像“双十一”这样的大规模促销活动中,面对...
在选择和设计缓存架构时,需要考虑系统的特定需求,如并发量、数据规模、数据过期策略以及对高可用性和扩展性的要求。正确地使用缓存能够显著提升系统性能,但也会带来数据一致性、缓存穿透和雪崩等问题,因此在设计...
主要是基于简化以后的大型电商详情页系统的背景,来重点讲解了三块内容: Redis集群架构、大型 高并发缓存架构以及基于Hystrix的高可用服务架构。而本次的《亿级流量电商详情页系统实战(第二版):缓存架构+高可用...
这种架构设计旨在提高系统的响应速度,降低数据库压力,保证服务的稳定性。下面将详细探讨相关知识点。 一、缓存原理与类型 缓存是一种存储技术,用于临时存储频繁访问的数据,以减少对慢速存储(如硬盘)的依赖。...
Android之本地缓存——LruCache(内存缓存)与DiskLruCache(硬盘缓存)统一框架 [注:本内容来自网络,在此分享仅为帮助有需要的网友,如果侵犯了您的权利,麻烦联系我,我会第一时间删除,谢谢您。]