目录

1.缓存简介

2.应用场景

3.memcache

4.jetcache

4.1 jetcache简介

4.1.2 引入依赖

4.1.3 jetcacje配置

4.1.4 测试项目结构

4.1.5 启动类开启缓存

4.1.6 编写测试用例

4.1.7 缓存同步

5.mykit-cache


1.缓存简介

2.应用场景

3.memcached

3.1 简介

Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态、数据库驱动网站的速度。Memcached基于一个存储键/值对的hashmap。其守护进程(daemon )是用C写的,但是客户端可以用任何语言来编写,并通过memcached协议与守护进程通信。

3.2 特征

memcached作为高速运行的分布式缓存服务器,具有以下的特点。

1、协议简单
2、基于libevent的事件处理
3、内置内存存储方式
4、memcached不互相通信的分布式

3.3 docker安装

3.3.1 拉取镜像

docker pull memcached

拉取后查看docker镜像

后台运行容器

docker run -itd -p 9091:11211 --name memcache memcached

进入容器

[root@hw-cloud-02 memcached]# docker exec -it memcache bash
memcache@9490fbd7c0e1:/$
memcache@9490fbd7c0e1:/$
memcache@9490fbd7c0e1:/$ memcached -h  # 查看帮助信息

原文参考:memcached入门_怎么就重名了的博客-CSDN博客_memcached入门

3.4 linux安装

原文链接:https://blog.csdn.net/qq_43147136/article/details/85067986

memcached入门_怎么就重名了的博客-CSDN博客_memcached入门

4.jetcache

4.1 简介

JetCache是一个基于Java的缓存系统封装,提供统一的API和注解来简化缓存的使用。 JetCache提供了比SpringCache更加强大的注解,可以原生的支持TTL、两级缓存、分布式自动刷新,还提供了Cache接口用于手工缓存操作。 当前有四个实现,RedisCache、TairCache(此部分未在github开源)、CaffeineCache(in memory)和一个简易的LinkedHashMapCache(in memory),要添加新的实现也是非常简单的。

4.1.2 引入依赖


# spring-boot-starter-parent  2.6.4
# jetcache-starter-redis      2.6.2
<dependency><groupId>com.alicp.jetcache</groupId><artifactId>jetcache-starter-redis</artifactId>
</dependency>

4.1.3 jetcacje配置

jetcache:statIntervalMinutes: 15areaInCacheName: falsehidePackages: com.huachunlocal:default:type: caffeinelimit: 100keyConvertor: fastjsonexpireAfterWriteInMillis: 100000otherArea:type: linkedhashmaplimit: 100keyConvertor: noneexpireAfterWriteInMillis: 100000remote:default:type: rediskeyConvertor: fastjsonvalueEncoder: javavalueDecoder: javapoolConfig:minIdle: 5maxIdle: 20maxTotal: 50host: ${spring.redis.host}port: ${spring.redis.port}password: ${spring.redis.password}otherArea:type: rediskeyConvertor: fastjsonvalueEncoder: kryovalueDecoder: kryopoolConfig:minIdle: 5maxIdle: 20maxTotal: 50host: ${spring.redis.host}port: ${spring.redis.port}password: ${spring.redis.password}

配置参数说明:

属性 默认值 说明
jetcache.statIntervalMinutes 0 统计间隔,0表示不统计
jetcache.areaInCacheName true jetcache-anno把cacheName作为远程缓存key前缀,2.4.3以前的版本总是把areaName加在cacheName中,因此areaName也出现在key前缀中。2.4.4以后可以配置,为了保持远程key兼容默认值为true,但是新项目的话false更合理些。
jetcache.hiddenPackages @Cached和@CreateCache自动生成name的时候,为了不让name太长,hiddenPackages指定的包名前缀被截掉
jetcache.[local|remote].${area}.type 缓存类型。tair、redis为当前支持的远程缓存;linkedhashmap、caffeine为当前支持的本地缓存类型
jetcache.[local|remote].${area}.keyConvertor key转换器的全局配置,当前只有一个已经实现的keyConvertor:fastjson。仅当使用@CreateCache且缓存类型为LOCAL时可以指定为none,此时通过equals方法来识别key。方法缓存必须指定keyConvertor
jetcache.[local|remote].${area}.valueEncoder java 序列化器的全局配置。仅remote类型的缓存需要指定,可选java和kryo
jetcache.[local|remote].${area}.valueDecoder java 序列化器的全局配置。仅remote类型的缓存需要指定,可选java和kryo
jetcache.[local|remote].${area}.limit 100 每个缓存实例的最大元素的全局配置,仅local类型的缓存需要指定。注意是每个缓存实例的限制,而不是全部,比如这里指定100,然后用@CreateCache创建了两个缓存实例(并且注解上没有设置localLimit属性),那么每个缓存实例的限制都是100
jetcache.[local|remote].${area}.expireAfterWriteInMillis 无穷大 以毫秒为单位指定超时时间的全局配置(以前为defaultExpireInMillis)
jetcache.local.${area}.expireAfterAccessInMillis 0 需要jetcache2.2以上,以毫秒为单位,指定多长时间没有访问,就让缓存失效,当前只有本地缓存支持。0表示不使用这个功能

上表中${area}对应@Cached和@CreateCache的area属性。注意如果注解上没有指定area,默认值是"default"。

关于缓存的超时时间,有多个地方指定,澄清说明一下:

1.put等方法上指定了超时时间,则以此时间为准
2.put等方法上未指定超时时间,使用Cache实例的默认超时时间
3.Cache实例的默认超时时间,通过在@CreateCache和@Cached上的expire属性指定,如果没有指定,使用yml中定义的全局配置,例如@Cached(cacheType=local)使用jetcache.local.default.expireAfterWriteInMillis,如果仍未指定则是无穷大

4.1.4 测试项目结构

4.1.5 启动类开启缓存

package com.huachun;import com.alicp.jetcache.anno.config.EnableCreateCacheAnnotation;
import com.alicp.jetcache.anno.config.EnableMethodCache;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
@EnableMethodCache(basePackages = "com.huachun")
@EnableCreateCacheAnnotation
public class JetCacheApplication {public static void main(String[] args) {SpringApplication.run(JetCacheApplication.class, args);}}

说明:

启动类需要添加两个注解

@EnableMethodCache(basePackages = "com.huachun") 
用于激活@Cached注解的使用,basePackages指定包路径

@EnableCreateCacheAnnotation
用于激活@CreateCache注解的使用

4.1.6 编写测试用例

1.添加实体类

package com.huachun.model;import lombok.Data;import java.io.Serializable;/*** 测试表(HcTest)实体类** @author makejava* @since 2022-03-12 14:51:40*/
@Data
public class HcTest implements Serializable {private static final long serialVersionUID = -73106959549361546L;private String id;private String name;private String description;
}

2. 添加业务处理

package com.huachun.service.impl;import com.alicp.jetcache.Cache;
import com.alicp.jetcache.anno.CreateCache;
import com.huachun.dao.HcTestDao;
import com.huachun.model.HcTest;
import com.huachun.service.JetCacheService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class JetCacheServiceImpl implements JetCacheService {@Autowiredprivate HcTestDao hcTestDao;@CreateCache(expire = 300)private Cache<String, HcTest> cache;@Overridepublic HcTest getCache(String str) {HcTest hcTest = cache.get(str);if (null == hcTest) {hcTest = hcTestDao.queryById(str);cache.put(str, hcTest);}return hcTest;}
}

3. 编写控制器

package com.huachun.controller;import com.huachun.model.HcTest;
import com.huachun.service.JetCacheService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/jet")
public class JetCacheController {@Autowiredprivate JetCacheService jetCacheService;@GetMapping("/cache/{str}")public HcTest getCache(@PathVariable("str") String str) {return jetCacheService.getCache(str);}}

4. 启动服务测试

控制台打印信息

再次访问接口,控制台不再打印访问数据库信息,并且返回正常数据,此时说明缓存已生效

并且数据已经存入redis

此时重启服务,虽然内存中没有,但是会从redis中获取 ,仍然可以正常获取

问题:redis中存储的key名字不是我想要的,能否按照指定格式生成key?

答案是当然可以的。

分析一下redis是由jetcache控制的,是否可以从配置文件或者注解入手?如果配置文件的话应该会有规则,而注解的方式明显会比较灵活

点进@CreateCache注解,发现有一个name属性

尝试设置@CreateCache注解name属性值

@CreateCache(expire = 10, name = "JetCacheService.getCache.")
private Cache<String, HcTest> cache;

再次重启后访问,搜索redis服务key果然有值,再次测试也是可用的

设置本地内存和远程都缓存数据

@CreateCache(expire = 20, name = "JetCacheService.getCache.",localExpire = 100,cacheType = CacheType.BOTH,localLimit = 100,serialPolicy = SerialPolicy.KRYO,keyConvertor = KeyConvertor.FASTJSON)
expire:远程缓存时间
name:缓存名称
localExpire:本地缓存时间
cacheType:缓存类型 REMOTE,LOCAL,BOTH;
localLimit:
serialPolicy:
keyConvertor:

L1:本地缓存->L2:远程缓存->L3:数据库

问题:jetcache是怎样保证缓存读写一致性?怎样保证本地和远程缓存服务数据一致性?

并发处理

package com.huachun.service.impl;import com.alicp.jetcache.Cache;
import com.alicp.jetcache.anno.CacheType;
import com.alicp.jetcache.anno.CreateCache;
import com.alicp.jetcache.anno.KeyConvertor;
import com.alicp.jetcache.anno.SerialPolicy;
import com.huachun.dao.HcTestDao;
import com.huachun.model.HcTest;
import com.huachun.service.JetCacheService;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;@Service
public class JetCacheServiceImpl implements JetCacheService {@Autowiredprivate HcTestDao hcTestDao;@CreateCache(expire = 100, name = "JetCacheService-", localExpire = 100, cacheType = CacheType.BOTH)private Cache<String, HcTest> cache;@Resource(description = "myRedisson")private RedissonClient redissonClient;@Overridepublic HcTest getCache(String str) {RLock rLock = redissonClient.getLock("jetcache-lock");HcTest hcTest = cache.get(str);try {if (rLock.tryLock(0, 10, TimeUnit.SECONDS) && null == hcTest) {hcTest = hcTestDao.queryById(str);if (null == hcTest) {hcTest = new HcTest();hcTest.setId(str);}cache.put(str, hcTest);} else {if (rLock.isLocked()) {if (rLock.isHeldByCurrentThread()) {rLock.unlock();}}}} catch (Exception exception) {System.out.println(exception);} finally {if (rLock.isLocked()) {if (rLock.isHeldByCurrentThread()) {rLock.unlock();}}}return hcTest;}
}

4.1.7 缓存同步

1 手动方式

package com.huachun.service.impl;import com.alicp.jetcache.Cache;
import com.alicp.jetcache.anno.*;
import com.huachun.dao.HcTestDao;
import com.huachun.model.HcTest;
import com.huachun.service.JetCacheService;
import com.huachun.utils.RlockUtils;
import com.huachun.utils.SnowFlakeGenerateIdWorker;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;@Service
@Slf4j
public class JetCacheServiceImpl implements JetCacheService {/*** 预计插入的数据*/private static Integer expectedInsertions = 10000;/*** 误判率*/private static Double fpp = 0.01;@Autowiredprivate HcTestDao hcTestDao;@Autowiredprivate RlockUtils rlockUtils;@CreateCache(expire = 100, name = "JetCacheService-", localExpire = 100, cacheType = CacheType.BOTH)private Cache<String, HcTest> cache;@Resource(description = "myRedisson")private RedissonClient redissonClient;@Overridepublic HcTest getData(String str) {String logBy = this.getClass().getName() + ".getCache:{}";RBloomFilter<Object> bloomFilter = redissonClient.getBloomFilter("JetCacheService");if (!bloomFilter.contains(str)) {return null;}RLock rLock = redissonClient.getLock("jetcache-lock");HcTest hcTest = cache.get(str);rLock.lock(10, TimeUnit.SECONDS);try {if (rLock.tryLock(0, 10, TimeUnit.SECONDS) && null == hcTest) {hcTest = hcTestDao.queryById(str);if (null == hcTest) {hcTest = new HcTest();hcTest.setId(str);cache.put(str, hcTest);}}} catch (Exception exception) {log.error(logBy, exception);} finally {rlockUtils.unLock(rLock);}return hcTest;}@Overridepublic void addData(HcTest hcTest) {String logBy = this.getClass().getName() + ".addData:{}";try {RBloomFilter<Object> bloomFilter = redissonClient.getBloomFilter("JetCacheService");bloomFilter.tryInit(expectedInsertions, fpp);SnowFlakeGenerateIdWorker snowFlakeGenerateIdWorker = new SnowFlakeGenerateIdWorker(1, 3);String id = snowFlakeGenerateIdWorker.generateNextId();bloomFilter.add(id);hcTest.setId(id);hcTestDao.insert(hcTest);} catch (Exception exception) {log.error(logBy, exception);}}@Overridepublic void updateData(HcTest hcTest) {cache.put(hcTest.getId(), hcTest);hcTestDao.update(hcTest);}@Overridepublic void removeData(String str) {cache.remove(str);hcTestDao.deleteById(str);}}
// 创建缓存
@CreateCache(expire = 100, name = "JetCacheService-", localExpire = 100, cacheType = CacheType.BOTH)private Cache<String, HcTest> cache;// 添加缓存
cache.put(str, hcTest);
// 缓存更新
cache.put(hcTest.getId(), hcTest);
// 缓存删除
cache.remove(str);
同步测试正常

2 注解方式

    @Autowiredprivate HcTestDao hcTestDao;@Cached(name = "JetCacheServiceAnno.", key = "#str")@Overridepublic HcTest getData(String str) {return hcTestDao.queryById(str);}@Overridepublic void addData(HcTest hcTest) {hcTestDao.insert(hcTest);}@CacheUpdate(name = "JetCacheServiceAnno.", value = "#hcTest", key = "#hcTest.id")@Overridepublic void updateData(HcTest hcTest) {hcTestDao.update(hcTest);}@CacheInvalidate(name = "JetCacheServiceAnno.", key = "#str")@Overridepublic void removeData(String str) {hcTestDao.deleteById(str);}

参考原文:阿里开源的缓存框架JetCache,实现spring二级缓存_Young丶的博客-CSDN博客_spring二级缓存

5.mykit-cache

常见问题

1.整合jetcache循环依赖问题

问题详细:

The dependencies of some of the beans in the application context form a cycle:

┌─────┐
|  redisAutoInit (field protected com.alicp.jetcache.anno.support.ConfigProvider com.alicp.jetcache.autoconfigure.AbstractCacheAutoInit.configProvider)
↑     ↓
|  springConfigProvider
└─────┘

Action:

Relying upon circular references is discouraged and they are prohibited by default. Update your application to remove the dependency cycle between beans. As a last resort, it may be possible to break the cycle automatically by setting spring.main.allow-circular-references to true.

解决方法:application.yml文件中添加 allow-circular-references: true

spring:main:allow-circular-references: true

SpringBoot整合缓存框架(jetcache、memcached、mykit-cache)相关推荐

  1. 【SpringBoot整合缓存】-----Redis缓存篇

    本专栏将从基础开始,循序渐进,以实战为线索,逐步深入SpringBoot相关知识相关知识,打造完整的SpringBoot学习步骤,提升工程化编码能力和思维能力,写出高质量代码.希望大家都能够从中有所收 ...

  2. 【SpringBoot整合缓存】-----spring-boot-starter-cache篇

    本专栏将从基础开始,循序渐进,以实战为线索,逐步深入SpringBoot相关知识相关知识,打造完整的SpringBoot学习步骤,提升工程化编码能力和思维能力,写出高质量代码.希望大家都能够从中有所收 ...

  3. SpringBoot整合CXF框架开发

    在开发过程中遇到了一些使用webservice开发的需求,后查阅资料学习,可上手开发.在学习过程中实现了个小demo,为了养成良好的总结习惯(我还没这"坏习惯"),特意写了个小呆萌 ...

  4. SpringBoot整合Web框架

    SpringBoot整合Web框架 Spring Boot可以轻松创建独立的.基于Spring的生产级应用程序 它可以让你"运行即可". 大多数Spring Boot应用程序只需要 ...

  5. 详解SpringBoot整合Mybatis框架

    文章目录 前言 一.创建SpringBoot项目 二.配置Mybatis 1. 在pom.xml文件中添加jar包依赖 2. SpringBoot整合Mybatis配置文件 三.创建Mapper接口 ...

  6. 2023新版图文详解SpringBoot整合SSM框架(附源码)

    版权声明 本文原创作者:谷哥的小弟 作者博客地址:http://blog.csdn.net/lfdfhl 教程概述 本教程以图文形式详细讲解SpringBoot整合SSM框架的流程以及具体步骤及其注意 ...

  7. idea中springboot整合Axis2框架一

    idea中springboot整合Axis2框架一 1.Axis2框架所需要的maven坐标: 2.编写webservice服务类 3.在WEB-INF/services/webService/MET ...

  8. 阿里开源的缓存框架JetCache,实现spring二级缓存

    之前一直在用Spring Cache进行接口数据的缓存,主要是Spring Cache在对具体key缓存失效时间的设置不是很方法,还要自己去扩展,无意中发现了阿里的JetCache.大部分的需求都能满 ...

  9. iBase4J是Java的分布式系统架构 使用Springboot整合开源框架

    iBase4J项目简介 iBase4J是Java语言的分布式系统架构. 使用Spring整合开源框架. 使用Maven对项目进行模块化管理,提高项目的易开发性.扩展性. 系统包括4个子系统:系统管理S ...

最新文章

  1. 导师:CNN 开山之作 AlexNet 都复现不了,延毕吧!
  2. oracle11gr2 active data guard,Oracle11gR2 Aactive DataGuard(手动)装配部署及维护文档(三)之升级及rman...
  3. Flutter 填坑之 表单数据哪里去了?
  4. 在线建立或重做mysql主从复制架构方法(传统模式和GTID模式)【转】
  5. java 捆绑_java – 如何在jar文件中捆绑图像
  6. 生成同时兼容iOS真机和模拟器的.a包
  7. 迭代获取ViewState
  8. HDU3685 几何+重心+凸包+判定锐角三角形
  9. 「管理数学基础」2.4 泛函分析:有界线性算子与泛函、例题
  10. 开课吧:深入了解C++语言应用方向有哪些?
  11. MySQL优化(二)
  12. 登录,注册,个人信息,退出的隐藏和出现
  13. BST、AVL、BTree、B+Tree、B*Tree、23Tree、234Tree、TTree、RBTree、LLRBTree、AATree、SplayTree、Treap、无旋Treap、scap
  14. Matlab应变片仿真,一种基于Matlab/Adams联合仿真的真实路谱再现系统和方法与流程...
  15. 计算机毕业设计Java校园闲置物品交易平台(系统+源码+mysql数据库+lw文档)
  16. Unity 2D精灵分割图片注意事项
  17. 最新版 FatFS f_mkfs 详解
  18. oracle Blob保存方式,oracle 存储过程操作blob
  19. qc35 说明书_Bose QC35耳机怎么使用,Bose QC35耳机使用教程
  20. 计算机与代数---如何计算ln---方法和实现

热门文章

  1. 小程序之 实现转发/分享功能
  2. 机械臂的牛顿-欧拉动力学方程
  3. php httphost和servername,PHP中的HTTP_HOST和SERVER_NAME有什么区别?
  4. ERROR 1130 (HY000): Host '113.57.150.82' is not allowed to connect to this MySQL server
  5. 如何设置计算机网络端口
  6. 单纯形法解下列线性规划问题_用单纯形法求解下列线性规划问题 线性规划单纯形法教学策略探求...
  7. 喜马拉雅FM--iOS架构师招聘中
  8. 看完这篇 教你玩转渗透测试靶机vulnhub——FunBox4(CTF)
  9. heracles压测平台介绍
  10. flume简单使用案例