后端开发缓存篇之缓存及缓存模式的介绍

一.什么是缓存:

缓存,简单说就是为了节约对原始资源重复获取的开销,而将结果数据副本存放起来以供获取的方式。

二.什么时候使用缓存

1.以 幂等和安全的方式对资源的获取操作

2.缓存数据必须是重复获取的:

     缓存能生效的本质是空间换时间

缓存的命中率: 把一批数据获取中,通过缓存获得数据的次数,除以总的次数,得到的结果,叫做缓存的命中率。

3. 缓存是为了解决“开销”的问题,开销包括:时间的开销、CPU、网络、I/O等资源的开销。

4. 缓存的存取其实不一定是“更快”的

5.缓存使用最常用的动机:(1) 一个是 latency,延迟(2) 另一个使用动机,是 throughput,吞吐量

三.缓存应用模式:

1. Cache-Aside(最常用的缓存模式)

  (1)获取数据: 

        应用先去查看缓存是否有所需数据;

        如果有,应用直接将缓存数据返回给请求方;

        如果没有,应用执行原始逻辑,例如查询数据库得到结果数据;

        应用将结果数据写入缓存。

  (2)更新数据:

        关键点一:必须先更新数据库-再令缓存失效:

(原因在于,如果先令缓存失效,那么在数据库更新成功前,如果有另外一个请求访问了缓存,发现缓存数据库已经失效,于是就会按照数据获取策略,从数据库中使用这个已经陈旧的数值去更新缓存中的数据,这就导致这个过期的数据会长期存在于缓存中,最终导致数据不一致的严重问题。)

        关键点二:数据库更新以后,需要令缓存失效,而不是更新缓存为数据库的最新值

(为什么呢?你想一下,如果两个几乎同时发出的请求分别要更新数据库中的值为 A 和 B,如果结果是 B 的更新晚于 A,那么数据库中的最终值是 B。但是,如果在数据库更新后去更新缓存,而不是令缓存失效,那么缓存中的数据就有可能是 A,而不是 B。因为数据库虽然是“更新为 A”在“更新为 B”之前发生,但如果不做特殊的跨存储系统的事务控制,缓存的更新顺序就未必会遵从“A 先于 B”这个规则,这就会导致这个缓存中的数据会是一个长期错误的值 A。)

  2. Read-Through

   (1)获取数据:

            应用向缓存要求数据;

            如果缓存中有数据,返回给应用,应用再将数据返回;

            如果没有,缓存查询数据库,并将结果写入自己;

            缓存将数据返回给应用。

这种情况下缓存系统彻底变成了它身后数据库的代理,二者成为了一个整体,应用的请求访问只能看到缓存的返回数据,而数据库系统对它是透明的。

虽然read-through和cache-aside非常相似,但至少有两个关键区别:

  1. 在cache-aside中,应用程序负责从数据库中获取数据并填充缓存。在read-through中,此逻辑通常由库或独立缓存提供程序支持。

  2. 与cache-aside不同,read-through cache中的数据模型不能与数据库中的数据模型不同

3. Write-Through

     主要用于处理数据更新的场景。

    (1)获取数据:

            应用要求缓存更新数据;

            如果缓存中有对应数据,先更新该数据;

            缓存再更新数据库中的数据;缓存告知应用更新完成。

    这里的一个关键点是,缓存系统需要自己内部保证并发场景下,缓存更新的顺序要和数据库更新的顺序一致。

  (数据更新的异常情形:如果缓存更新失败,直接返回失败,没有数据不一致的情况发生;如果缓存更新成功,数据库更新失败,这种情况下需要回滚缓存中的更新,或者干脆从缓存中删除该数据。)

    4. Write-Back

   数据写入缓存和数据库更新是异步完成的,即数据写入缓存后立即返回,数据库更新异步完成。

(这种方式带来的最大好处是拥有最大的请求吞吐量,并且操作非常迅速,数据库的更新甚至可以批量进行,因而拥有杰出的更新效率以及稳定的速率,这个缓存就像是一个写入的缓冲,可以平滑访问尖峰。另外,对于存在数据库短时间无法访问的问题,它也能够很好地处理。但是它的弊端也很明显,异步更新一定会存在着不可避免的一致性问题,并且也存在着数据丢失的风险(数据写入缓存但还未入库时,如果宕机了,那么这些数据就丢失了)

总结:缓存在实际项目中应用非常多,而最常用的缓存模式就是 Cache-Aside,所以深入理解 Cache-Aside是关键。

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(后端开发)