`

缓存的使用

 
阅读更多

转自:https://www.cnblogs.com/songwenjie/p/9027012.html 

 

缓存能解决的问题

1.提升性能

绝大多数情况下,select 是出现性能问题最大的地方。一方面,select 会有很多像 join、group、order、like 等这样丰富的语义,而这些语义是非常耗性能的;另一方面,大多    数应用都是读多写少,所以加剧了慢查询的问题。

分布式系统中远程调用也会耗很多性能,因为有网络开销,会导致整体的响应时间下降。为了挽救这样的性能开销,在业务允许的情况(不需要太实时的数据)下,使用缓存是非常必要的事情。

2.缓解数据库压力

 

当用户请求增多时,数据库的压力将大大增加,通过缓存能够大大降低数据库的压力。

 

缓存的适用场景

对于数据实时性要求不高。对于一些经常访问但是很少改变的数据,读明显多于写,适用缓存就很有必要。比如一些网站配置项。

对于性能要求高。比如一些秒杀活动场景。

缓存三种模式

一般来说,缓存有以下三种模式:

  • Cache Aside 更新模式

  • Read/Write Through 更新模式

  • Write Behind Caching 更新模式

通俗一点来讲就是,同时更新缓存和数据库(Cache Aside 更新模式);先更新缓存,缓存负责同步更新数据库(Read/Write Through 更新模式);先更新缓存,缓存定时异步更新数据库(Write Behind Caching 更新模式)。这三种模式各有优劣,可以根据业务场景选择使用。

Cache Aside 更新模式

这是最常用的缓存模式了,具体的流程是:

  • 失效:应用程序先从 cache 取数据,没有得到,则从数据库中取数据,成功后,放到缓存中。
  • 命中:应用程序从 cache 中取数据,取到后返回。
  • 更新:先把数据存到数据库中,成功后,再让缓存失效。

 

 

注意我们上面所提到的,缓存更新时先更新数据库,然后在让缓存失效。那么为什么不是直接更新缓存呢?这里有一些缓存更新的坑,我们需要避免入坑。

避坑指南一

先更新数据库,再更新缓存。这种做法最大的问题就是两个并发的写操作导致脏数据。如下图(以Redis和Mysql为例),两个并发更新操作,数据库先更新的反而后更新缓存,数据库后更新的反而先更新缓存。这样就会造成数据库和缓存中的数据不一致,应用程序中读取的都是脏数据。



 

避坑指南二

先删除缓存,再更新数据库。这个逻辑是错误的,因为两个并发的读和写操作导致脏数据。如下图(以Redis和Mysql为例)。假设更新操作先删除了缓存,此时正好有一个并发的读操作,没有命中缓存后从数据库中取出老数据并且更新回缓存,这个时候更新操作也完成了数据库更新。此时,数据库和缓存中的数据不一致,应用程序中读取的都是原来的数据(脏数据)。



 

避坑指南三

先更新数据库,再删除缓存。这种做法其实不能算是坑,在实际的系统中也推荐使用这种方式。但是这种方式理论上还是可能存在问题。如下图(以Redis和Mysql为例),查询操作没有命中缓存,然后查询出数据库的老数据。此时有一个并发的更新操作,更新操作在读操作之后更新了数据库中的数据并且删除了缓存中的数据。然而读操作将从数据库中读取出的老数据更新回了缓存。这样就会造成数据库和缓存中的数据不一致,应用程序中读取的都是原来的数据(脏数据)。



 

但是,仔细想一想,这种并发的概率极低。因为这个条件需要发生在读缓存时缓存失效,而且有一个并发的写操作。实际上数据库的写操作会比读操作慢得多,而且还要加锁,而读操作必需在写操作前进入数据库操作,又要晚于写操作更新缓存,所有这些条件都具备的概率并不大。但是为了避免这种极端情况造成脏数据所产生的影响,我们还是要为缓存设置过期时间。

Read/Write Through 更新模式

在上面的 Cache Aside 更新模式中,应用代码需要维护两个数据存储,一个是缓存(Cache),一个是数据库(Repository)。而在Read/Write Through 更新模式中,应用程序只需要维护缓存,数据库的维护工作由缓存代理了。



 

Read Through

Read Through 模式就是在查询操作中更新缓存,也就是说,当缓存失效的时候,Cache Aside 模式是由调用方负责把数据加载入缓存,而 Read Through 则用缓存服务自己来加载。

Write Through

Write Through 模式和 Read Through 相仿,不过是在更新数据时发生。当有数据更新的时候,如果没有命中缓存,直接更新数据库,然后返回。如果命中了缓存,则更新缓存,然后由缓存自己更新数据库(这是一个同步操作)。

Write Behind Caching 更新模式

Write Behind Caching 更新模式就是在更新数据的时候,只更新缓存,不更新数据库,而我们的缓存会异步地批量更新数据库。这个设计的好处就是直接操作内存速度快。因为异步,Write Behind Caching 更新模式还可以合并对同一个数据的多次操作到数据库,所以性能的提高是相当可观的。

但其带来的问题是,数据不是强一致性的,而且可能会丢失。另外,Write Behind Caching 更新模式实现逻辑比较复杂,因为它需要确认有哪些数据是被更新了的,哪些数据需要刷到持久层上。只有在缓存需要失效的时候,才会把它真正持久起来。



 

总结

三种缓存模式的优缺点:

Cache Aside 更新模式实现起来比较简单,但是需要维护两个数据存储,一个是缓存(Cache),一个是数据库(Repository)。

Read/Write Through 更新模式只需要维护一个数据存储(缓存),但是实现起来要复杂一些。

Write Behind Caching 更新模式和Read/Write Through 更新模式类似,区别是Write Behind Caching 更新模式的数据持久化操作是异步的,但是Read/Write Through 更新模式的数据持久化操作是同步的。优点是直接操作内存速度快,多次操作可以合并持久化到数据库。缺点是数据可能会丢失,例如系统断电等。

缓存是通过牺牲强一致性来提高性能的。所以使用缓存提升性能,就是会有数据更新的延迟。这需要我们在设计时结合业务仔细思考是否适合用缓存。然后缓存一定要设置过期时间,这个时间太短太长都不好,太短的话请求可能会比较多的落到数据库上,这也意味着失去了缓存的优势。太长的话缓存中的脏数据会使系统长时间处于一个延迟的状态,而且系统中长时间没有人访问的数据一直存在内存中不过期,浪费内存。

  • 大小: 25.2 KB
  • 大小: 20.1 KB
  • 大小: 24.5 KB
  • 大小: 25.4 KB
  • 大小: 25.3 KB
  • 大小: 27.5 KB
分享到:
评论

相关推荐

    cache/ehcache缓存使用

    本文将详细讲解"cache/ehcache缓存使用"的相关知识点,包括缓存的基本概念、Ehcache的介绍、以及如何在Java应用中使用Ehcache进行缓存操作。 首先,我们要理解什么是缓存。缓存是一种存储技术,它临时存储常用或...

    ibatis-缓存使用示例

    在IT行业中,数据库操作是应用程序开发的核心部分,而iBATIS作为一个流行的持久层框架,它为Java开发者提供了...通过"ibatis-缓存使用示例"的学习,开发者能更好地掌握这一技巧,从而在实际项目中发挥出更大的价值。

    EHcache 缓存使用 手动存储 配置到SSH

    **正文** 在IT行业中,缓存技术是一种非常重要的性能...手动存储数据到缓存以及配置自动清空策略是优化缓存使用的关键。记住,缓存并非总是答案,合理的缓存策略应结合业务需求和系统负载进行设计,以达到最佳效果。

    Volley的三级缓存使用

    Volley的内存缓存使用了LRU(Least Recently Used)算法,优先淘汰最近最少使用的数据。 二级缓存是磁盘缓存,当内存缓存无法满足需求或者数据需要长期保存时,Volley会将数据写入到设备的文件系统中。磁盘缓存相比...

    缓存使用场景,介绍redis/内存等缓存的使用场景,更新策略等

    缓存使用场景 缓存是一种常用的优化技术,用于减少数据库查询的次数,以提高系统的性能和可扩展性。缓存的使用场景非常广泛,包括Web应用程序、移动应用程序、游戏等。 在缓存使用场景中,Redis和内存缓存是两种...

    Hibernate的缓存使用

    本文将深入探讨Hibernate的缓存使用,包括一级缓存和二级缓存的概念、工作原理以及如何在实际开发中有效利用它们。 ### 一级缓存 一级缓存是Hibernate默认提供的缓存,也称为Session缓存。每当我们在Session中进行...

    c#缓存使用工具,也已使用Redis和MemoryCache

    还在测试,这几天完善一下

    asp.net 2.0典型模块设计与实现源码 缓存使用

    在这个“asp.net 2.0典型模块设计与实现源码 缓存使用”的主题中,我们将深入探讨ASP.NET 2.0中的缓存机制,以及如何在实际项目中有效利用缓存来提高应用程序性能。 缓存是Web应用程序优化的关键策略之一,通过存储...

    Asp.Net从零开始25(缓存使用)

    ### ASP.NET从零开始25(缓存使用) #### 缓存的概念 缓存是一种用于存储数据的技术,目的是为了减少数据库或服务器的负担,并提高应用程序的响应速度。在Web开发中,缓存技术尤为重要,因为它可以帮助减少网络...

    memcached缓存使用演示

    系统会根据内存大小自动管理缓存对象,当内存满时,会使用LRU(Least Recently Used)最近最少使用算法来淘汰旧的、不常使用的数据。 ### 2. 安装与配置Memcached 在Linux环境下,可以通过包管理器(如apt-get或...

    swift内存缓存NSCache和沙盒磁盘缓存使用教程和demo下载

    本教程将深入探讨这两种缓存机制的使用,并提供一个包含实例代码的Demo下载。 ### 一、NSCache `NSCache`是苹果提供的轻量级内存缓存系统,用于临时存储不重要的数据。它与`NSMutableDictionary`类似,但有一些...

    hibernate二级缓存使用范例

    不过,需要注意的是,查询缓存依赖于二级缓存,因此必须先启用二级缓存才能使用查询缓存。 在配置二级缓存时,我们需要在Hibernate的配置文件中声明缓存提供者,并在实体类的映射文件中启用二级缓存。例如,对于...

    SSH使用缓存例子

    然而,缓存不是万能的,不恰当的缓存使用可能导致数据一致性问题,因此在使用缓存时应充分考虑数据的实时性和缓存更新策略。 总结来说,SSH框架结合Hibernate的二级缓存,通过在内存中存储常用数据,有效提升了Web...

    SpringBoot项目 MybatisPlus使用 Redis缓存.zip

    本项目中,我们看到“SpringBoot项目 MybatisPlus使用 Redis缓存.zip”主要涉及了SpringBoot、MybatisPlus和Redis三个核心组件,它们在实际开发中扮演着重要角色。 首先,SpringBoot是Spring框架的一种简化版,它...

    Spring.NET实用技巧1——基于Prevalence下的NHibernate二级缓存使用技巧

    Spring.NET实用技巧1——基于Prevalence下的NHibernate二级缓存使用技巧 文章出处 http://www.cnblogs.com/GoodHelper/archive/2010/05/19/SpringNet_NHbernate_Prevalence.html

    apc 缓存使用详解

    默认(无参数)时,只清除系统缓存,要清除用户缓存,需用?user‘参数。 apc_define_constants ( string key, array constants [, bool case_sensitive] ) 将数组constants以常量加入缓存。 apc_load_constants ...

    java map 实现缓存技术

    7. **缓存击穿与缓存雪崩**:处理大量并发请求同时导致缓存失效(击穿)或整个缓存服务崩溃(雪崩)的问题,可以通过加锁、使用分布式锁、预热缓存等方式解决。 8. **监控与统计**:为了优化缓存性能,需要收集和...

    Spring11Boot基于注解的Redis缓存使用.docx

    。。Spring11Boot基于注解的Redis缓存使用.docx

    Spring11Boot基于注解的Redis缓存使用.pdf

    。。Spring11Boot基于注解的Redis缓存使用.pdf

    C#缓存的使用

    本篇文章将深入探讨C#中的缓存使用,包括其原理、应用场景、实现方式以及一些实用的小程序示例。 一、缓存原理 缓存是一种数据存储机制,它存储最近经常访问的数据,以提高响应速度。在C#中,常见的缓存有内存缓存...

Global site tag (gtag.js) - Google Analytics