缓存架构

缓存架构

1.“缓存与数据库”的需求
2.“淘汰缓存”还是“更新缓存”
3.缓存与数据库的操作时序
4.缓存与数据库架构简析

“缓存与数据库”的需求

缓存是一种提高系统读性能的常见技术,对于读多写少的应用场景,经常使用缓存进行优化

读操作流程:
1.首先查询缓存
2.如果缓存命中,则返回
3.如果缓存没有命中,那查询数据库,之后插入缓存,再返回

缓存命中率=命中缓存请求个数/总缓存访问请求个数=hit/(hit+miss)

对于写操作流程存在3个问题:
1.是更新缓存中的数据,还是淘汰缓存中的数据?
2.是先操作数据库的数据再操作缓存的数据,还是先操作缓存的数据再操作数据库的数据?
3.缓存与数据库的操作,在架构上是否有优化的空间?

更新缓存与淘汰缓存

更新缓存:数据不但写入数据库,还会写入缓存
淘汰缓存:数据只会写入数据库,不会写入缓存,只会把数据淘汰掉

更新缓存的优点:缓存不会增加一次miss。命中率高
淘汰缓存的优点:简单

如何选择,取决“更新缓存的复杂度”
对于查询账户余额,只是简单的把余额money设置成一个值,那么:
淘汰缓存的操作为deleteCache
更新缓存的操作为setCache
更新缓存的代价很小,此时更倾向于更新缓存,以保证更高的缓存命中率

如果余额是通过负载的计算得出来的,例如业务上除了账户表account,还有商品表product,折扣表discount
account(uid,money)
product(pid,type,price,pinfo)
discount(type,zhekou)
业务场景用户买了一个商品product,这个商品的价格是price,这个商品从属type类商品,type类商品在做促销活动要打折扣zhekou,购买了商品过后,这个余额的计算就复杂了,需要:
1.先把商品的品类,价格取出来:SELECT type, price FROM product WHERE pid=XXX
2.再把这个品类的折扣取出来:SELECT zhekou FROM discount WHERE type=XXX
3.再把原有余额从缓存中查询出来money=getCache(uid)
4.再把新的余额写入到新缓存中去setCache(uid,money-price*zhekou)
更新缓存的代价很大,此时我们更倾向于淘汰缓存

先操作数据库与先操作缓存

假设淘汰缓存作为缓存通用的处理方式
由于写数据库与淘汰缓存不能保证原子性

假设先写数据库,在淘汰缓存:第一步操作数据库成功,第二步淘汰缓存失败,则会出现DB中是新数据,Cache中是旧数据,数据不一致

假设先淘汰缓存,再写数据库:第一步缓存淘汰成功,第二步写数据库失败,只会引发一次Cache miss

所以,数据库和缓存的操作时序是固定的:先淘汰缓存,再写数据库

遗留问题:
1.当淘汰缓存成功,还没来得及更新数据库,此时有其他读请求,那么此时这个读请求发现缓存miss,请求数据库,读到的是旧数据,更新到缓存。
2.如果数据库架构采用了一主多从,读写分离的架构,在特殊时序下,还很可能引发数据库与缓存的不一致,

缓存架构优化

加入一个服务层,向上游提供数据访问接口,向上游屏蔽底层数据存储的细节,这样业务线不需要关注数据是来自cache还是DB

后续补充

你可能感兴趣的:(架构师之路)