当前位置: 首页 > 科技观察

我用Ehcache提高了100倍的查询性能,真是太爽了!

时间:2023-03-18 13:57:13 科技观察

今天给大家分享一个知识点,就是如何使用Ehcache这个本地缓存框架,在我们开发系统的时候极大的提升和优化我们的查询性能,甚至可以提升很多查询操作的性能看了100多遍,下面聊聊这个话题。业务场景首先给大家介绍一个场景,就是假设我们写的一个Java系统,需要跑一个几百行的大SQL,去MySQL里面查询数据。这个查询会很慢吗?一定是,这种几百行的大SQL,往往是超复杂的查询,可能涉及到多张表的关联,还有一些是数据指标的查询。当然,这种数据指标的查询其实是比较常见的,是针对各种数据的。关联表来查询和统计一些指标。一般来说,遇到这种超大的SQL,往往会导致查询MySQL性能不佳。跑1s甚至几秒是很常见的。比如下图:所以很多时候对于这种场景,如果我们要优化这个查询的性能,一般都会用到缓存。也就是我这次用了几百行SQL查询结果,最后用了几秒钟,很慢,然后居然把结果缓存起来,下次有请求来的时候,直接用这个缓存中的数据取出来返回即可。从缓存中读取结果并返回最多需要1ms,根本不是几秒钟。如何通过缓存优化查询接口那么问题来了,缓存的结果应该存储在哪里呢?很多兄弟可能会说可以存储在Redis中!但是,是不是每次用缓存都得马上用Redis?毕竟Redis要部署额外的集群,一旦引入Redis就得考虑Redis会不会出现故障,一些访问问题,与Redis的网络通信毕竟比较费时间。所以,其实我们的优先级是先去本地缓存,也就是在运行业务系统的JVM的堆内存中,来缓存我们的查询结果。下次有请求过来,就从本地缓存中取出,直接返回即可。如下图所示:基于大数据离线平台的缓存预热那么下一个问题又来了。很多query他一天第一次查的时候可能不在localcache里,还得去mysql上花几秒查询,查完之后才能放到localcache里。不是说有些人每天第一次查询很慢吗?有没有更好的办法?当然是缓存预热。我们的业务系统可以记录每天的查询请求和参数。对于一些数据报表的复杂查询,每天的查询条件几乎都是一样的,只是当天的日期会发生变化。另外,一些数据报表的数据往往是通过大数据平台离线计算出来的。什么是离线计算?也就是说,可能有一个大数据系统,每天早上计算昨天的数据,把计算出来的数据结果写入MySQL,然后每天只更新一次数据,之后就没有更新过数据了。如下图:然后,用户每天都会向我们的系统发起很多复杂的报表查询语句,但是这个SQL多表关联的一些逻辑,以及一些附加的查询条件几乎是规律的,相似的,就是selecteveryday当天的日期不相同。那么这个时候我们就可以把这些查询条件记录下来,然后每天早上,趁着大家睡觉的时候,我们根据经常查询的条件和当天的日期,提前查询数据,将查询结果写入到提前本地缓存。这样用户在第一次访问的时候就可以直接从本地缓存中获取最新的数据,如下图所示:本地缓存框架:Ehcache下面给大家介绍一下我们常用的本地缓存框架Ehcache,这是一个著名的本地缓存框架,基本上Ehcache和Guava是使用最多的两个本地缓存框架。下面以Ehcache为例,说明本地缓存框架是如何使用的。首先要在我们的项目pom.xml中引入相应的依赖,如下:net.sf.ehcacheehcache2.10.2然后恶意引入一个类似ehcache.xml的配置文件来配置我们的缓存框架。如下图:下面给大家解释一下上面的参数对ehcache框架运行后的影响。首先,maxElementsInMemory是指它可以在内存中缓存多少条数据。eternal表示缓存是否永久有效,如果永久有效,那么timeToLiveSeconds就没用了。但如果不是永久的,你可以设置timeToLiveSeconds。比如你可以设置缓存数据存活24小时,然后自动过期。然后你必须强制从数据库查询。overflowToDisk表示如果缓存的数据超过maxElementsInMemory,是否将超出的数据刷入磁盘。diskPersistent是指JVM重启时,是否将缓存在内存中的数据flush到磁盘中,等JVM重启后再将磁盘中的数据恢复到内存中。这两个参数,如果缓存的数据特别多的话,其实是可以打开的。一方面,如果内存缓存不够用,可以刷新到磁盘。另一方面,内存中的数据在重启时会被持久化,然后重新加载到内存中。还有memoryStoreEvictionPolixy,是一种缓存回收策略,因为如果缓存的数据量太大,内存和磁盘就存不下了。这时候就必须回收一部分数据。一般都是用LRU,最近用的最少。回收策略。下面是在代码中使用Ehcache的例子:希望今天分享给大家的本地缓存知识,可以帮助大家在以后遇到类似复杂报表数据查询场景时,利用这个知识点来优化自己的系统性能!