spring data rest 缓存/spring boot Jpa 二级缓存 ehcache 与 redis

2023-11-12

这两天都在为学校的项目做准备,期间也遇到了很多问题,比如自己写代码生成器,比如授权这些,发现自己还是有点太弱了。但是最为棘手的莫过于缓存的问题。主要原因还是自己太想用 spring data rest 了,这个在假期就没有解决缓存的问题,现在还是要来再次面对,不过相隔几个月,今非昔比。

问题分析

项目直接使用 spring data rest 进行资源暴露,repository 完全接手,所以我舍去了 service 层,controller 也基本没有方法,就算有也被抽象出来了。那么没有 service 如何做缓存呢?那就是用他 Jpa 底层实现的 hibernate 了,一级缓存我们是默认开启的,那么我们就要使用 二级缓存 来提高性能。

使用 ehcache

第一种方式就是使用非常快速的 ehcache 来提高性能,配合 hibernate-jcache 使用,就可以达到很好的效果,具体如下:

1、 引入依赖,没有加上版本号是因为 spring boot 的版本管理会自动下载合适的版本。

        <!--ehcache-->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-jcache</artifactId>
        </dependency>
        <dependency>
            <groupId>org.ehcache</groupId>
            <artifactId>ehcache</artifactId>
        </dependency>

2、 添加 ehcache.xml 配置文件

<?xml version="1.0" encoding="UTF-8"?>
<eh:config
        xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
        xmlns:eh='http://www.ehcache.org/v3'
        xsi:schemaLocation="http://www.ehcache.org/v3 http://www.ehcache.org/schema/ehcache-core-3.3.xsd">
    <eh:persistence directory="${java.io.tmpdir}/lesson-cloud-cache-data"/>

    <eh:cache-template name="default">
        <eh:expiry>
            <eh:ttl unit="seconds">600</eh:ttl>
        </eh:expiry>
        <eh:resources>
            <!--堆内内存可以放2000个条目,超出部分堆外100MB-->
            <eh:heap unit="entries">2000</eh:heap>
            <eh:offheap unit="MB">100</eh:offheap>
        </eh:resources>
    </eh:cache-template>
</eh:config>

3、 添加 hibernate.properties 配置文件

hibernate.format_sql=true
hibernate.cache.use_second_level_cache=true
hibernate.cache.use_query_cache=true
hibernate.cache.region_prefix=gzmu_lesson_cloud_
hibernate.cache.region.factory_class=org.hibernate.cache.jcache.JCacheRegionFactory
hibernate.cache.provider_configuration_file_resource_path=ehcache.xml
hibernate.cache.use_structured_entries=true
hibernate.generate_statistics=false
hibernate.javax.cache.missing_cache_strategy=create

如果你不喜欢使用 properties 文件,可以在 application.yml 里面配置

spring:
  jpa:
    show-sql: true
    properties:
      hibernate:
        generate_statistics: true
        javax:
          cache:
            missing_cache_strategy: create
        cache:
          format_sql: true
          use_second_level_cache: true
          use_query_cache: true
          region:
            factory_class: org.hibernate.cache.jcache.JCacheRegionFactory
          region_prefix: lesson_cloud_
          use_structured_entries: true
          provider_configuration_file_resource_path: ehcache.xml

4、 不需要在 service 层添加注解,而是在实体类添加注解,如下:

@Data
@Cacheable // 缓存
@Table(name = "sys_log")
@Entity(name = "sys_log")
@Where(clause = "is_enable = 1")
@EqualsAndHashCode(callSuper = true)
@Cache(region = "sys_log", usage = CacheConcurrencyStrategy.READ_WRITE ) // 缓存名字以及策略
public class SysLog extends BaseEntity {
	// ...
}

默认对查询的列表不缓存,一方面是因为命中率低,另一方面查询的列表会因为其中的一个改变就要销毁,操作频繁,没有缓存的必要。

使用 redis

这个是真的搞了好久,因为系统涉及到分布式,所以使用 ehcache 肯定是不太好的,所以要把它缓存 redis。一开始自己尝试了很多办法,自己尝试实现一个缓存机制(效率太低并且代码不忍直视)。所以就想到去找别人的,所以在 github 上一搜真的有,找到一个 hibernate-redis,但是一使用发现很多很多问题,然后自己一个一个的排除,最后遇到一个无法解决的问题

java.lang.IncompatibleClassChangeError: Expected static method org.hibernate.cache.internal.DefaultCacheKeysFactory.createEntityKey(Ljava/lang/Object;Lorg/hibernate/persister/entity/EntityPersister;Lorg/hibernate/engine/spi/SessionFactoryI

然后发现这个问题是个 bug,已经在未来的版本解决,见 issue, 由于没有上传到 maven 仓库,需要自己切换到 2.4 版本的分支自己构建自己打包,并且还要用本地 jar 导入的方式导入,实在太过麻烦,暂时放弃。

然后找资料,网上乱七八糟的一大堆,没一个有用的,重复的还非常多。最后又回到 hibernate-redis,然后查看的时候发现了他引用了 redisson 的依赖,就很好奇这个是什么,然后去 官网 看了下,发现他是一个 java 的 redis client,可以通过它来操作 redis,并且观望上给出的标语

Redis based cache implementations for Java like JCache API, Hibernate 2nd Level Cache, Spring Cache and application level caching.

他也可以作为 JCache API, Hibernate, Spring Cache 的二级缓存,那么是不是意味着我可以用它呢?于是去他的 github wiki 看了下,果然有!而且还有 spring cache 的!不过我们不用,因为我们不用那几个注解来进行缓存控制,而是通过 hibernate,所以我尝试一下,完美整合!

1、 导入依赖,不同的是,我们导入的不是 redisson 的依赖,而是 redisson-hibernate ,这里算是坑到我了,导入 redisson 没用,然后去 maven 中央仓库逛了一波才发现 redisson-hibernate,然后尝试了一波才发现居然可以。

<!-- 注意先导入你的 hibernate-core -->
<dependency>
    <groupId>org.redisson</groupId>
    <!-- 对于 Hibernate v4.x -->
    <artifactId>redisson-hibernate-4</artifactId>
    <!-- 对于 Hibernate v5.0.x - v5.1.x -->
    <artifactId>redisson-hibernate-5</artifactId>
    <!-- 对于 Hibernate v5.2.x -->
    <artifactId>redisson-hibernate-52</artifactId>
    <!-- 对于 Hibernate v5.3.x - v5.4.x -->
    <artifactId>redisson-hibernate-53</artifactId>
    <version>3.10.6</version>
</dependency>

2、 添加 hibernate.properties 如下

hibernate.format_sql=true
hibernate.cache.use_second_level_cache=true
hibernate.cache.use_query_cache=true
hibernate.cache.region_prefix=gzmu_lesson_cloud_
hibernate.cache.region.factory_class=org.redisson.hibernate.RedissonRegionFactory
hibernate.cache.redisson.config=redisson.yaml
hibernate.cache.use_structured_entries=true
hibernate.generate_statistics=false
hibernate.javax.cache.missing_cache_strategy=create

3、 添加 redisson.yaml 如下

# 配置参见 https://github.com/redisson/redisson/wiki/2.-%E9%85%8D%E7%BD%AE%E6%96%B9%E6%B3%95

# 单节点设置,其余模式待测试
singleServerConfig:
  idleConnectionTimeout: 10000
  pingTimeout: 1000
  connectTimeout: 1000
  timeout: 1000
  retryAttempts: 1
  retryInterval: 1000
  reconnectionTimeout: 3000
  failedAttempts: 5
  password: null
  subscriptionsPerConnection: 5
  clientName: null
  address: "redis://127.0.0.1:6379"
  subscriptionConnectionMinimumIdleSize: 1
  subscriptionConnectionPoolSize: 25
  connectionMinimumIdleSize: 5
  connectionPoolSize: 100
  database: 0
threads: 0
# Codec
codec: !<org.redisson.codec.SnappyCodec> {}
eventLoopGroup: null

4、 同样,实体类添加注解

@Data
@Cacheable // 缓存
@Table(name = "sys_log")
@Entity(name = "sys_log")
@Where(clause = "is_enable = 1")
@EqualsAndHashCode(callSuper = true)
@Cache(region = "sys_log", usage = CacheConcurrencyStrategy.READ_WRITE ) // 缓存名字以及策略
public class SysLog extends BaseEntity {
	// ...
}

5、 测试即可

不过在使用的时候发现 redisson-hibernate-53 比 redisson-hibernate-52 少了一些包,其查看 jar 结构的时候会很奇怪

redisson-hibernate-52

redisson-hibernate-53

使用的时候优势会出问题有时候不会,一开始提示找不到类,试了很多次,后来莫名其妙又可以了。。。。

更细致化配置

使用 yaml 进行配置

spring:
  jpa:
    show-sql: true
    properties:
      hibernate:
        cache:
          redisson:
            config: redisson.yaml
          region:
            factory_class: org.redisson.hibernate.RedissonRegionFactory
          region_prefix: gzmu_lesson_cloud_
          use_query_cache: true
          use_second_level_cache: true
          use_structured_entries: true
          provider_configuration_file_resource_path: classpath:conf/hibernate-redis.properties
        format_sql: true
        generate_statistics: false
        javax:
          cache:
            missing_cache_strategy: create

添加 hibernate-redis.properties

##########################################################2
#
# properities for hibernate-redis 可以在这里进行更加细致化的 redis 配置
#
##########################################################

# Redisson configuration file
redisson-config=classpath:conf/redisson.yaml

# Cache Expiry settings
# 'hibernate' is second cache prefix
# 'common', 'account' is actual region name
redis.expiryInSeconds.default=120
redis.expiryInSeconds.hibernate.common=0
redis.expiryInSeconds.hibernate.account=1200

redisson 配置同上

值得注意的是,redis 同样不会缓存查询的列表,理由同上。

总结

搞这个搞了一天多才成功,集群还没尝试,不过应该不难了,还是需要多多熟悉才行啊。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

spring data rest 缓存/spring boot Jpa 二级缓存 ehcache 与 redis 的相关文章

随机推荐

  • 实验七 ICMP 协议分析实验

    实验七 ICMP 协议分析实验 1 ICMP 协议介绍 ICMP Internet Control Message Protocol 是因特网控制报文协议 RFC792 的缩写 是因特网的标准协议 ICMP允许路由器或主机报告差错情况和提供
  • 99元起定制专属RPA机器人丨UB Store年中钜惠

    炎炎夏日 不管是 前浪 还是 后浪 都抵挡不住酷暑热浪 不少办公族的 夏日综合症 又犯了 精神疲惫 心理烦躁 容易疲劳 什么都没干就累了 上班没精神 办公没效率怎么办 别担心 工作上的事儿 可以交给RPA机器人 没有什么办公操作是RPA机器
  • Django城市信息查询功能

    基于 Pythgo的 Django 框架 编程实现一个 WEB 程序 为用户提供 城市信息查询功能 用户可输入一个城市名 输出其所在省份名称和邮编 等信息 例如 输入 桂林市 输出 广西壮族自治区 和 541000 等 城市相关信息 数据准
  • 深入理解Hibernate表与表之间的关联,搞懂cascade、inverse、lazy等属性,和注解版Hibernate实例

    1 搞定Hibernate表与表之间的关联 搞懂cascade inverse lazy等属性 2个类 书 Book 类别 BookType public class Book private Long id private BookTyp
  • Matlab中的snr

    一 matlab中产生高斯白噪声 可以直接应用两个函数 一个是WGN 另一个是AWGN WGN用于产生高斯白噪声 AWGN则用于在某一信号中加入高斯白噪声 1 WGN 产生高斯白噪声 y wgn m n p 产生一个m行n列的高斯白噪声的矩
  • python 单下划线及双下划线使用方法

    Python下划线命名模式 小结 以下是一个简短的小结 即 速查表 罗列了我在本文中谈到的五种Python下划线模式的含义 Python 用下划线作为变量前缀和后缀指定特殊变量 方法 主要存在四种情形 object public objec
  • MySQL查看所有连接的客户端ip

    有时候我们需要查看当前的mysql数据库中 有哪些客户端保持了连接 每个客户端分别保持了多少连接 下面的语句能够直观的反馈结果 SELECT substring index host 1 AS host name state count F
  • 测试自动化的 10 个最佳实践方法

    虽然大家都知道坚果是非常健康和有营养的 但是 当你尝试吃它的时候 我猜测过程都不会很顺利 现实就是那么相似 我们都知道测试自动化对软件开发有好处 就像坚果对我们的身体一样 很遗憾很多公司在不考虑细微差别的情况下就赶着上线测试自动化 如果您不
  • Python 3中同时使用MatplotLib和OpenCV显示图像,发生异常

    文章目录 问题 原因分析 解决方法 问题 运行如下代码 不能正常执行 并报以下异常 代码 from matplotlib import pyplot as plt BLUE 255 0 0 img1 cv imread img file c
  • 记一次swoole连接数太多导致的错误

    原先就有点担心这个项目正式上线会出现各种问题 所以刚上线就赶紧查看日志 果然 频繁出现错误 WARNING Server accept connection accept failed Error Too many open files 2
  • 使用python将excel表格中的A+,A等分数自动转换成百分制分数,并自动保存于excel中

    使用该简短程序 将excel表格中的A A A B 等转换成对应的百分制分数 再加和平均 并自动保存于excel表格中 本文较为适合学生数次作业分数的最终统计 本例是将学生的八次作业转换成百分制并综合平均得到最终分数 并自动将每位学生的分数
  • Java内存分配策略

    1 内存分配有哪些策略 我们从编译原理讲起 不同的开发环境 开发语言都会有不同的策略 一般来说 程序运行时有三种内存分配策略 静态的 栈式的 堆式的 静态存储 是指在编译时就能够确定每个数据目标在运行时的存储空间需求 因而在编译时就可以给它
  • 数组常用的方法

    穷举法是什么 穷举法 顾名思义 是指根据题目的条件确定答案的大致范围 并在此范围内对所有可能的情况逐一验证 直到全部情况验证完毕 若某个情况符合题目的条件 则为本问题的一个解 若全部情况验证后都不符合题目的条件 则本题无解 什么是数组 数组
  • 类模板案例_数组类封装

    案例描述 实现一个通用的数组类 要求如下 可以对内置数据类型以及自定义数据类型的数据进行存储 将数据中的数据存储到堆区 new 构造函数中可以传入数组的容量 提供对应的拷贝构造函数以及opertor 防止浅拷贝问题 提供尾插法和尾删法对数组
  • websocket 基本使用

    websocket 第一次创建连接的时候也是建立了一个http连接 之后才能传递消息 websocket特点 HTTP响应头 和 websocket响应头 的区别 websocket 响应头 前端代码 div div
  • Vue Hooks 让Vue开发更简单与高效

    Vue Hooks 让Vue开发更简单与高效 介绍 Vue Hooks 是一个基于 Vue js 的插件 它提供了一种新的方式来编写 Vue 组件 使得开发更加简单和高效 它借鉴了 React Hooks 的概念 通过使用 Hooks 我们
  • 杂项 Windows安装WSL

    WechatIMG188 jpeg 安装WSL 检查 gt wsl 适用于 Linux 的 Windows 子系统没有已安装的分发版 可以通过访问 Microsoft Store 来安装分发版 https aka ms wslstore c
  • 1.结合宏定义三目运算符实现两个数求最大值

    一 题目 结合宏定义三目运算符实现两个数求最大值 二 知识点 1 三目运算符 三目运算符又称条件运算符 格式 表达式1 表达式2 表达式3 运算规则 先执行表达式1 然后判断表达式1是否成立 如果成立就执行表达式2 否则就执行表达式3 2
  • 华为机试C语言-书籍叠放问题2

    题目描述 https www cnblogs com zucc 31701019 p 14967899 html https zhuanlan zhihu com p 526649048 这题贪心就可以了 强行动态规划有点勉强 但是也刚好练
  • spring data rest 缓存/spring boot Jpa 二级缓存 ehcache 与 redis

    这两天都在为学校的项目做准备 期间也遇到了很多问题 比如自己写代码生成器 比如授权这些 发现自己还是有点太弱了 但是最为棘手的莫过于缓存的问题 主要原因还是自己太想用 spring data rest 了 这个在假期就没有解决缓存的问题 现