Angular 6集成Spring Boot 2,Spring Security,JWT和CORS系列:八、Spring Boot实现两级cache

本文介绍了如何在Angular 6应用中集成Spring Boot 2,利用Spring Security和JWT实现身份验证,并通过CORS处理跨域问题。重点探讨了Spring Boot实现的两级缓存机制,包括Caffeine作为一级缓存,Redis作为二级缓存,以及如何利用Redis的消息发布订阅功能进行缓存同步。文章详细阐述了缓存的读取、更新和删除流程,并展示了具体的代码实现。
摘要由CSDN通过智能技术生成

Springboot实现缓存很简单,最多两处配置(Maven工程的pom.xml引入依赖包和系统配置文件application.yml定义参数)即可引入缓存,然后再使用注解,就可以很方便是开始使用缓存了。

这样是比较简单,书写代码也很高效。可是执行的代码高效吗,当然的不高效:

1、单机的redis,并发访问量有限吧?

2、集群redis,并发访问量还是有限吧?

3、redis的命中率、网络传输,都需要一定的损耗时间吧?

站在前人的肩膀上,才能更接近成功。参考了一些前人的资料,我目前整理出下面的两级缓存机制。

一、两级缓存数据流原理

1、Cacheable(读取数据流程)

读取数据,先从一级缓存中读取,一级缓存中有值则直接读取,没有则再读取二级缓存;二级缓存中有值则更新一级缓存返回值,没有则从数据库中获取数据,依次更新一二级缓存。

2、CachePut(数据变更流程)

3、CacheEvict(缓存删除流程)

4、利用redis的消息发布订阅模式,实现其它站点缓存同步

二、一级缓存引入

Spring Boot的本地缓存有好几种,我采用Caffeine。

Caffeine是一个基于Google开源的Guava设计理念的一个高性能内存缓存,使用java8开发,spring boot引入Caffeine后已经逐步废弃Guava的整合了。Caffeine源码及介绍地址:caffeine

caffeine提供了多种缓存填充策略、值回收策略,同时也包含了缓存命中次数等统计数据,对缓存的优化能够提供很大帮助

caffeine的介绍可以参考://www.jb51.net/article/134242.htm

这里简单说下caffeine基于时间的回收策略有以下几种:

  1. expireAfterAccess:访问后到期,从上次读或写发生后的过期时间
  2. expireAfterWrite:写入后到期,从上次写入发生之后的过期时间
  3. 自定义策略:到期时间由实现Expiry接口后单独计算

在工程的pom.xml中增加一下依赖

<dependency>
	<groupId>com.github.ben-manes.caffeine</groupId>
	<artifactId>caffeine</artifactId>
</dependency>

三、代码

1、增加属性文件CacheRedisCaffeineProperties.java

package com.demo.example.security.core.cache;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.springframework.boot.context.properties.ConfigurationProperties;


@ConfigurationProperties(prefix = "spring.cache.multi")
public class CacheRedisCaffeineProperties {
	
	/**
	 * 本机的ip地址
	 */
	private String localIp="127.0.0.1";
	
	private Set<String> cacheNames = new HashSet<>();
	/** 是否存储空值,默认true,防止缓存穿透 */
	private boolean cacheNullValues = true;
	/** 是否动态根据cacheName创建Cache的实现,默认true */
	private boolean dynamic = true;

	/** 缓存key的前缀 */
	private String cachePrefix;
	private Redis redis = new Redis();
	private Caffeine caffeine = new Caffeine();

	public class Redis {
		
		/** 全局过期时间,单位毫秒,默认不过期 */
		private long defaultExpiration = 0;

		/** 每个cacheName的过期时间,单位毫秒,优先级比defaultExpiration高 */
		private Map<String, Long> expires = new HashMap<>();

		/** 缓存更新时通知其他节点的topic名称 */
		private String topic = "cache:redis:caffeine:topic";

		public long getDefaultExpiration() {
			return defaultExpiration;
		}

		public void setDefaultExpiration(long defaultExpiration) {
			this.defaultExpiration = defaultExpiration;
		}

		public Map<String, Long> getExpires() {
			return expires;
		}

		public void setExpires(Map<String, Long> expires) {
			this.expires = expires;
		}

		public String getTopic() {
			return topic;
		}

		public void setTopic(String topic) {
			this.topic = topic;
		}

	}

	public class Caffeine {
		/** 访问后过期时间,单位毫秒 */
		private long expireAfterAccess;

		/** 写入后过期时间,单位毫秒 */
		private long expireAfterWrite;

		/** 写入后刷新时间,单位毫秒 */
		private long refreshAfterWrite;

		/** 初始化大小 */
		private int initialCapacity;

		/** 最大缓存对象个数,超过此数量时之前放入的缓存将失效 */
		private long maximumSize;

		/** 由于权重需要缓存对象来提供,对于使用spring cache这种场景不是很适合,所以暂不支持配置 */
		// private long maximumWeight;

		public long getExpireAfterAccess() {
			return expireAfterAccess;
		}

		public void setExpireAfterAccess(long expireAfterAccess) {
			this.expireAfterAccess = expireAfterAccess;
		}

		public long getExpireAfterWrite() {
			return expireAfterWrite;
		}

		public void setExpireAfterWrite(long expireAfterWrite) {
			this.expireAfterWrite = expireAfterWrite;
		}

		public long getRefreshAfterWrite() {
			return refreshAfterWrite;
		}

		public void setRefreshAfterWrite(long refreshAfterWrite) {
			this.refreshAfterWrite = refreshAfterWrite;
		}

		public int getInitialCapacity() {
			return initialCapacity;
		}

		public void setInitialCapacity(int initialCapacity) {
			this.initialCapacity = initialCapacity;
		}

		public long getMaximumSize() {
			return maximumSi
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值