JPA,EclipseLink 缓存机制学习(一) 树节点搜索问题引发的思考

最近在项目在使用JPA+EclipseLink 的方式进行开发,其中EclipseLink使用版本为2.5.1。遇到一些缓存方面使用不当造成的问题,从本篇开始逐步学习EclipseLink的缓存机制。

一、树节点搜索问题出现

故事是这样的:项目中有一个对树节点搜索的需求,如下图中所示,按照前缀匹配查询节点名称中包含OK的节点,将返回下图中的数据结构。基本实现就是:1.先查找出OK节点,然后根据该节点的父节点id获得父节点,也就是PERSON2结点,同样按照PERSON2的父结点id找到节点ROOT。结点的类图大概是这样子的,每获得父节点后,会将本身节点加入到父结点children集合中去。

(图a)

一开始按照特定顺序在操作中出现奇怪的现象。

step 1.  检索包含OK的结点   显示正常,如图b所示。

step 2.  检索包含PERSON名称的节点,结果如图c所示。

step 3.  又一次检索OK的节点,结果奇怪的结果出现了,见图d。理想中的结果数据是不包含PERSON1的,这显然是一个缓存导致的问题。

(图b)(图c)(图d)

二、EclipseLink 缓存架构

其中几个基本概念:

1. Session Cache,即 Persistence Unit Cache,属于系统级的缓存,所有client共享数据。数据来源主要有两种:
a)通过EntityManager进行数据读入时,会将读入的数据拷贝一份放到Session Cache;
b) Unit of Work Cache 进行Commit操作成功后,将数据同步到Session Cache中;

2. Unit of Work Cache,即Persistence Context Cache,属于隔离型缓存,属于单个client。由EntityManager进行管理,Persistence Context中保存着读取过的Entity实例。当对Entity执行了Commit操作后会将更改后对数据同步到Session Cache。Flush,Clear操作不会触发同步Session Cache操作。

3. 数据查询过程。EntityManager根据实例唯一标识查看Persistence Context Cache中是否存在该实例,如果存在则返回该实例。如果不存在,则查询Persistence Unit Cache中是否存在该实例,如果存在则直接返回该实例,如果不存在则访问数据库进行查询,得到数据结果后将此数据保存到Persistence Unit Cache 和 Persistence Context Cache中。

三、Entity缓存隔离类型(决定是否将查询数据存入到共享缓存中)

1.SHARED
共享缓存,也是系统默认的配置。EnittyManger在进行查询操作的时后,返回的数据会在Session Cache/EntityManagerFactory中保存一部分。

2.PROTECTED
被保护的。EnittyManger在进行查询操作的时后,返回的数据并不会在Session Cache中保存完整的Entity实例,只会保存Entity状态信息。

3.ISOLATED
隔离的。EnittyManger在进行查询操作的时后,返回的数据不会在Session Cache/EntityManagerFactory中保存,只保存在Persistence Context Cache中。

、Entity缓存类型(决定缓存有效时间)

1.FULL
将缓存该Entity的所有查询到的实例,随时可以通过唯一标识通过缓存进行获取。由于该缓存数据不会被gc清除,所以要当心,对于数量庞大的Entity实例对象有可能导致Out Of Memory。

2.WEAK
将该缓存的所有Entity实例以Weak Reference的引用方式进行缓存。当gc执行的时候,缓存将被清除。

3.SOFT
将该缓存的所有Entity实例以Soft Reference的引用方式进行缓存。当JVM可用内存过低时将对这部分缓存进行释放。

4.SOFT_WEAK
此为系统默认配置。将该缓存的所有Entity实例以Soft Reference 与 Weak Reference 相结合的方式进行缓存。此缓存类型和WEAK类型的区别在于,存在一个基于Soft Reference的most-frequently-used的子缓存,读取最频繁的Entity实例将保存在这里,避免gc回收读取频繁的Entity实例。该子缓冲区大小可以通过设置@Cache中的size属性来调节。

5.HARD_WEAK
此缓存类型和SOFT_WEAK很相似,区别在于子缓存区用Hard Reference 进行存储,保证即使JVM内存过低,也不会清除这部分缓存数据。

6.CACHE
缓存唯一标识map维护一个指定大小的缓存,对象被移出缓存策略按照LRU ( Least Recently Used)。

7.NONE
对该Entity不进行任何缓存。

五、搜索问题出现的原因
使用了Spring-data-JPA,持久化层通过继承接口org.springframework.data.jpa.repository.JpaRepository实现。根据debug结果发现实现类为org.springframework.data.jpa.repository.support.SimpleJpaRepository。其中每个SimpleJpaRepository实例有一个EntityManager,且在该Repository实例化后服务期间EntityManager类型的成员变量没有变化(HashCode相同)。可以认为使用的是同一个Persistence Context Cache。根据前文对缓存的分析,Node类型缓存隔离类型为SHARED,缓存类型为SOFT_WEAK,每次根据id对Node的查询都要先从Persistence Context Cache中找,结果step 2中对ROOT节点设置完Children,step 3中直接又从Persistence Context Cache中得到了该ROOT对象,导致无效数据(step 3)的出现。

六、解决方案
    我第一想到的就是不要让Node类型被缓存起来,即在Entity类型中增加@Cache(type=CacheType.NONE)。问题虽然按照这种方式解决了,但是带来效率的下降。比如Node节点有获取整棵树数据的方法。具体优化方案将在后续JPA后续文章中给出。

七、参考

EclipseLink Cache
https://www.eclipse.org/eclipselink/documentation/2.5/concepts/cache001.htm

EclipseLink 源码地址:
https://www.eclipse.org/eclipselink/downloads/previous_releases.php

八、结语
欢迎大家吐槽、拍砖、指正 ^_^

时间: 2024-11-08 09:58:51

JPA,EclipseLink 缓存机制学习(一) 树节点搜索问题引发的思考的相关文章

H5缓存机制学习记录

参考文章:http://mp.weixin.qq.com/s?__biz=MTEwNTM0ODI0MQ==&mid=404724239&idx=1&sn=e0a2887f9ff6293f0f550fa4e44057a0&scene=1&srcid=0331jLkF55dKeJO00POMiXLZ 1.浏览器缓存机制 2.Dom Storage(local storage 和 session storage) 3.Web SQL Database,不推荐使用. 根据官

浏览器缓存机制学习总结

在前端开发中,性能一直都是被大家所重视的一点,然而判断一个网站的性能最直观的就是看网页打开的速度.其中提高网页反应速度的一个方式就是使用缓存.一个优秀的缓存策略可以缩短网页请求资源的距离,减少延迟,并且由于缓存文件可以重复利用,还可以减少带宽,降低网络负荷. 一.web缓存简介: web缓存是指一个web资源(如html页面,图片,js,数据等)存在于web服务器和客户端(浏览器)之间的副本. 缓存会根据进来的请求保存输出内容的副本:当下一个请求来到的时候,如果是相同的URL,缓存会根据缓存机制

Ext 4.2树节点搜索功能

注,如果拿到的节点Type是treeNode这样的类型,你的Ext版本和笔者的Ext版本并不相同,据网上说treeNode是比较老的Ext版本.笔者使用的类型是Ext.data.NodeInterface. 来看正文,因为工作需要,公司使用的是Ext这个比较完善的前端Js框架,最近写到树的节点查询时,发现网上的资料全部都是手动迭代,更有甚者搬出了Jquery,这让我很纳闷,前面说了Ext这么完善的框架会蠢到连个树的搜索功能都没有?翻阅API后,不断尝试,给出以下一行代码即可做到Ext树查找节点功

MongoDB一次节点宕机引发的思考(源码剖析)

目录 简介 日志分析 副本集 如何实现 Failover 心跳的实现 electionTimeout 定时器 业务影响评估 参考链接 声明:本文同步发表于 MongoDB 中文社区,传送门: http://www.mongoing.com/archives/26759 简介 最近一个 MongoDB 集群环境中的某节点异常下电了,导致业务出现了中断,随即又恢复了正常. 通过ELK 告警也监测到了业务报错日志. 运维部对于节点下电的原因进行了排查,发现仅仅是资源分配上的一个失误导致. 在解决了问题

C#无限极分类树-创建-排序-读取 用Asp.Net Core+EF实现之方法二:加入缓存机制

在上一篇文章中我用递归方法实现了管理菜单,在上一节我也提到要考虑用缓存,也算是学习一下.Net Core的缓存机制. 关于.Net Core的缓存,官方有三种实现: 1.In Memory Caching 我理解是在内容中实现,这种方法适用于单服务器的生产环境. 2.a Distributed Cache 分部式缓存实现. 3.Response Cache 这种方式我理解为客户端缓存. 今天我只用了第一种实现方法,内存中缓存,之所以用这种方法我是觉得我这里用缓存的初衷是为了减少访问数据库的次数,

MyBatis学习手记(二)MyBatis缓存机制

MyBatis学习手记二 前:MyBatis官方学习(中文)文档 http://mybatis.github.io/mybatis-3/zh/index.html 一,首先,要使用MyBatis必须使用官方提供的MyBatis的JAR包              链接:https://github.com/mybatis/mybatis-3/releases 这里使用的数据库是MySQL,所以还需要Mysql的驱动包. 二,看MyBatis官方介绍,说MyBatis支持一级缓存,二级缓存.这里才

学习ASP.NET缓存机制

缓存是大型BS架构网站的性能优化通用手段,之前知道有这个概念,并且也知道很重要,但是一直没静下心来了解.这次借着学习PetShop源码的机会熟悉一下ASP.NET基本的缓存机制(生产环境中的真实缓存有多种实现方式,曾经了解过有MemCache等,这些都不在本篇讨论范围内),主要是3种缓存:1.页面缓存:2.缓存依赖:3.SQL缓存依赖. 先说页面缓存,最简单的使用方式就是在aspx页面顶部(比如在<%@ Page... %>后面)添加<%@ OutputCache Duration=&q

Java缓存学习之三:CDN缓存机制

CDN是什么? 关于CDN是什么,此前网友详细介绍过. CDN是Content Delivery Network的简称,即"内容分发网络"的意思.一般我们所说的CDN加速,一般是指网站加速或者用户下载资源加速. 举个通俗的例子: 谈到CDN的作用,可以用8年买火车票的经历来形象比喻:8年前,还没有火车票代售点一说,12306.cn更是无从说起.那时候火车票还只能在火车站的售票大厅购买,而我所住的小县城并不通火车,火车票都要去市里的火车站购买,而从县城到市里,来回就是4个小时车程,简直就

hbase 学习(十五)缓存机制以及可以利用SSD作为存储的BucketCache

下面介绍Hbase的缓存机制: a.HBase在读取时,会以Block为单位进行cache,用来提升读的性能 b.Block可以分类为DataBlock(默认大小64K,存储KV).BloomBlock(默认大小128K,存储BloomFilter数据).IndexBlock(默认大小128K,索引数据,用来加快Rowkey所在DataBlock的定位) c.对于一次随机读,Block的访问顺序为BloomBlock.IndexBlock.DataBlock,如果Region下面的StoreFi