文档章节

Spring思维导图,让Spring不再难懂(cache篇)

java思维导图
 java思维导图
发布于 2017/08/28 09:02
字数 1373
阅读 7252
收藏 431

关于缓存

缓存是实际工作中非常常用的一种提高性能的方法。而在java中,所谓缓存,就是将程序或系统经常要调用的对象存在内存中,再次调用时可以快速从内存中获取对象,不必再去创建新的重复的实例。这样做可以减少系统开销,提高系统效率。

在增删改查中,数据库查询占据了数据库操作的80%以上,而非常频繁的磁盘I/O读取操作,会导致数据库性能极度低下。而数据库的重要性就不言而喻了:

  • 数据库通常是企业应用系统最核心的部分
  • 数据库保存的数据量通常非常庞大
  • 数据库查询操作通常很频繁,有时还很复杂

在系统架构的不同层级之间,为了加快访问速度,都可以存在缓存

缓存不同层级的作用.png

spring cache特性与缺憾

现在市场上主流的缓存框架有ehcache、redis、memcached。spring cache可以通过简单的配置就可以搭配使用起来。其中使用注解方式是最简单的。

特性与缺憾.png

Cache注解

缓存注解.png

从以上的注解中可以看出,虽然使用注解的确方便,但是缺少灵活的缓存策略,

缓存策略:

  • TTL(Time To Live ) 存活期,即从缓存中创建时间点开始直到它到期的一个时间段(不管在这个时间段内有没有访问都将过期)

  • TTI(Time To Idle) 空闲期,即一个数据多久没被访问将从缓存中移除的时间

项目中可能有很多缓存的TTL不相同,这时候就需要编码式使用编写缓存。

条件缓存

根据运行流程,如下@Cacheable将在执行方法之前( #result还拿不到返回值)判断condition,如果返回true,则查缓存; 

@Cacheable(value = "user", key = "#id", condition = "#id lt 10")  
public User conditionFindById(final Long id)  

如下@CachePut将在执行完方法后(#result就能拿到返回值了)判断condition,如果返回true,则放入缓存

@CachePut(value = "user", key = "#id", condition = "#result.username ne 'zhang'")  
public User conditionSave(final User user)   

  如下@CachePut将在执行完方法后(#result就能拿到返回值了)判断unless,如果返回false,则放入缓存;(即跟condition相反)

@CachePut(value = "user", key = "#user.id", unless = "#result.username eq 'zhang'")  
public User conditionSave2(final User user)   

  如下@CacheEvict, beforeInvocation=false表示在方法执行之后调用(#result能拿到返回值了);且判断condition,如果返回true,则移除缓存;

@CacheEvict(value = "user", key = "#user.id", beforeInvocation = false, condition = "#result.username ne 'zhang'") 
public User conditionDelete(final User user)   
  • 小试牛刀,综合运用:
    @CachePut(value = "user", key = "#user.id")
    public User save(User user) {
        users.add(user);
        return user;
    }

    @CachePut(value = "user", key = "#user.id")
    public User update(User user) {
        users.remove(user);
        users.add(user);
        return user;
    }

    @CacheEvict(value = "user", key = "#user.id")
    public User delete(User user) {
        users.remove(user);
        return user;
    }

    @CacheEvict(value = "user", allEntries = true)
    public void deleteAll() {
        users.clear();
    }

    @Cacheable(value = "user", key = "#id")
    public User findById(final Long id) {
        System.out.println("cache miss, invoke find by id, id:" + id);
        for (User user : users) {
            if (user.getId().equals(id)) {
                return user;
            }
        }
        return null;
    }

配置ehcache与redis

  • spring cache集成ehcache,spring-ehcache.xml主要内容:
<dependency>
	<groupId>net.sf.ehcache</groupId>
	<artifactId>ehcache-core</artifactId>
	<version>${ehcache.version}</version>
</dependency>
<!-- Spring提供的基于的Ehcache实现的缓存管理器 -->
    
<!-- 如果有多个ehcacheManager要在bean加上p:shared="true" -->
<bean id="ehcacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
     <property name="configLocation" value="classpath:xml/ehcache.xml"/>
</bean>
    
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
     <property name="cacheManager" ref="ehcacheManager"/>
     <property name="transactionAware" value="true"/>
</bean>
    
<!-- cache注解,和spring-redis.xml中的只能使用一个 -->
<cache:annotation-driven cache-manager="cacheManager" proxy-target-class="true"/>
  • spring cache集成redis,spring-redis.xml主要内容:
<dependency>
	<groupId>org.springframework.data</groupId>
	<artifactId>spring-data-redis</artifactId>
	<version>1.8.1.RELEASE</version>
</dependency>
<dependency>
	<groupId>org.apache.commons</groupId>
	<artifactId>commons-pool2</artifactId>
	<version>2.4.2</version>
</dependency>
<dependency>
	<groupId>redis.clients</groupId>
	<artifactId>jedis</artifactId>
	<version>2.9.0</version>
</dependency>
<!-- 注意需要添加Spring Data Redis等jar包 -->
<description>redis配置</description>

<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
	<property name="maxIdle" value="${redis.pool.maxIdle}"/>
	<property name="maxTotal" value="${redis.pool.maxActive}"/>
	<property name="maxWaitMillis" value="${redis.pool.maxWait}"/>
	<property name="testOnBorrow" value="${redis.pool.testOnBorrow}"/>
	<property name="testOnReturn" value="${redis.pool.testOnReturn}"/>
</bean>

<!-- JedisConnectionFactory -->
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
	<property name="hostName" value="${redis.master.ip}"/>
	<property name="port" value="${redis.master.port}"/>
	<property name="poolConfig" ref="jedisPoolConfig"/>
</bean>

<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"
	  p:connectionFactory-ref="jedisConnectionFactory">
	<property name="keySerializer">
		<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"></bean>
	</property>
	<property name="valueSerializer">
		<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
	</property>
	<property name="hashKeySerializer">
		<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
	</property>
	<property name="hashValueSerializer">
		<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
	</property>
</bean>

<!--spring cache-->
<bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager"
	  c:redisOperations-ref="redisTemplate">
	<!-- 默认缓存10分钟 -->
	<property name="defaultExpiration" value="600"/>
	<property name="usePrefix" value="true"/>
	<!-- cacheName 缓存超时配置,半小时,一小时,一天 -->
	<property name="expires">
		<map key-type="java.lang.String" value-type="java.lang.Long">
			<entry key="halfHour" value="1800"/>
			<entry key="hour" value="3600"/>
			<entry key="oneDay" value="86400"/>
			<!-- shiro cache keys -->
			<entry key="authorizationCache" value="1800"/>
			<entry key="authenticationCache" value="1800"/>
			<entry key="activeSessionCache" value="1800"/>
		</map>
	</property>
</bean>
<!-- cache注解,和spring-ehcache.xml中的只能使用一个 -->
<cache:annotation-driven cache-manager="cacheManager" proxy-target-class="true"/>

项目中注解缓存只能配置一个,所以可以通过以下引入哪个配置文件来决定使用哪个缓存。

<import resource="classpath:spring/spring-ehcache.xml"/>
<!-- <import resource="classpath:spring/spring-redis.xml"/>-->

当然,可以通过其他配置搭配使用两个缓存机制。比如ecache做一级缓存,redis做二级缓存。

缓存对比.png

更加详细的使用与配置,可以参考项目中spring-shiro-training中有关spring cache的配置。

写在最后

欢迎关注我的微信公众号java思维导图,下载导图源文件,以及更多java思维导图与项目资料供你学习,带你走进记忆脑图的世界。

关注公众号并回复“思维导图”即刻下载源xmind导图。

上篇文章阅读

扫一扫关注java-mindmap公众号.jpg

© 著作权归作者所有

共有 人打赏支持
java思维导图

java思维导图

粉丝 1716
博文 29
码字总数 28964
作品 0
广州
程序员
加载中

评论(10)

java思维导图
java思维导图

引用来自“xzg”的评论

想问,这个是用哪款脑图软件画的呢?感谢

xmind
OSC_DwqZQI
OSC_DwqZQI
����
xzg
xzg
想问,这个是用哪款脑图软件画的呢?感谢
周sir
周sir
不错
不错
hantsy
hantsy
N 年前写了各种Spring 4 官方支持 Cache的例子, https://github.com/hantsy/spring4-sandbox, 文档看 Wiki
kppom
kppom

引用来自“yak”的评论

写代码越来越象写配置文件了
没错啊,最开始的程序形式就是图灵机的状态转移表,不能理解为一台机器的“配置文件”吗?
配置一下就能拿来计算了诶。
爱漫爱
爱漫爱
用框架就像是基于XML的编程或者基于注解的编程:joy:
struct
struct

引用来自“yak”的评论

写代码越来越象写配置文件了
代码就是编译器的配置文件。
程序就是 CPU 的配置文件。
yak
yak
写代码越来越象写配置文件了
Only5loveyou
Only5loveyou
学习了
提高效率,eclipse上你可能不知道的技巧

一张思维导图 公众号回复“eclipse技巧”可下载源导图 1、控制台(console )日志输出另保存 经常会遇到这种情况,习惯性的清掉控制台上的输出日志,再然后发现刚才的日志居然还有用,不得不又...

java思维导图
2017/10/20
0
0
轩少/spring-shiro-training

Spring Shiro学习系统 简介 基于springmvc、spring、mybatis-plus、shiro、easyui、Log4j2简单实用的权限系统。 界面基于EasyUI,图标采用较为开放的(MIT协议)。 :http://git.oschina.net/...

轩少
2015/12/07
0
0
Spring读取xml配置文件的原理与实现

Spring读取xml配置文件的原理与实现 本篇博文的目录: 一:前言 二:spring的配置文件 三:依赖的第三方库、使用技术、代码布局 四:Document实现 五:获取Element的实现 六:解析Element元素...

DemonsI
09/12
0
0
Spring AOP就是这么简单啦

前言 只有光头才能变强 上一篇已经讲解了Spring IOC知识点一网打尽!,这篇主要是讲解Spring的AOP模块~ 之前我已经写过一篇关于AOP的文章了,那篇把比较重要的知识点都讲解过了一篇啦:Sprin...

Java3y
05/24
0
0
Spring IOC知识点一网打尽!

前言 只有光头才能变强 回顾前面: 给女朋友讲解什么是代理模式 包装模式就是这么简单啦 单例模式你会几种写法? 工厂模式理解了没有? 在刷Spring书籍的时候花了点时间去学习了单例模式和工...

Java3y
05/22
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Kali Linux Docker 練習

docker pull kalilinux/kali-linux-docker docker run -t -i kalilinux/kali-linux-docker /bin/bash apt-get update apt-get install htop apt-get install nmap apt-get install wpscan ap......

BaiyuanLab
今天
1
0
通俗大白话来理解TCP协议的三次握手和四次分手

最近在恶补计算机网络方面的知识,之前对于TCP的三次握手和四次分手也是模模糊糊,对于其中的细节更是浑然不知,最近看了很多这方面的知识,也在系统的学习计算机网络,加深自己的CS功底,就...

onedotdot
今天
2
0
TiDB 在爱奇艺的应用及实践

爱奇艺,中国高品质视频娱乐服务提供者,2010 年 4 月 22 日正式上线,推崇品质、青春、时尚的品牌内涵如今已深入人心,网罗了全球广大的年轻用户群体,积极推动产品、技术、内容、营销等全方...

TiDB
今天
1
0
Web系统大规模并发:电商秒杀与抢购

一、大规模并发带来的挑战 在过去的工作中,我曾经面对过5w每秒的高并发秒杀功能,在这个过程中,整个Web系统遇到了很多的问题和挑战。如果Web系统不做针对性的优化,会轻而易举地陷入到异常...

xtof
今天
3
0
代码质量管理平台-sonarqube

在工作中,往往开发的时候会不怎么注重代码质量的人很多,存在着很多的漏洞和隐患等问题,sonarqube可以进行代码质量的审核,而且十分的残酷。。。。。接下来我们说下怎么安装 进入官网下载:...

落叶清风
今天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部