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
八、结语
欢迎大家吐槽、拍砖、指正 ^_^
JPA,EclipseLink 缓存机制学习(一) 树节点搜索问题引发的思考的更多相关文章
- JPA,EclipseLink 缓存机制学习——树节点搜索问题引发的思考
最近在项目在使用JPA+EclipseLink 的方式进行开发,其中EclipseLink使用版本为2.5.1.遇到一些缓存方面使用不当造成的问题,从本篇开始逐步学习EclipseLink的缓存机制. ...
- Linux 系统缓存机制学习
前言:本文为参考他人的文章,是一篇学习记录型博客.理解linux的系统缓存机制有助于理解elasticsearch实时更新的原理. 一.缓存机制 为了提高文件系统性能,内核利用一部分物理内存分配出缓冲 ...
- H5缓存机制学习记录
参考文章:http://mp.weixin.qq.com/s?__biz=MTEwNTM0ODI0MQ==&mid=404724239&idx=1&sn=e0a2887f9ff ...
- RecyclerView 缓存机制学习笔记2
RecyclerView 初始化所有的视图后,调用 去缓存(StaggeredGridLayoutManager), 而不是初始化一次缓存一次 存储后系统又会去调用tryGetViewHolderFo ...
- RecyclerView 缓存机制学习笔记1
盗用别人图片 获取VIew的方法的流程 最先调用 其次调用 这个方法调用会先去缓存 这个是是否有动画,有动画就去里面取. 如果取不到就接着调用 如果在没有继续调用 都取不到就去实例化 调用的次数取决于 ...
- MongoDB一次节点宕机引发的思考(源码剖析)
目录 简介 日志分析 副本集 如何实现 Failover 心跳的实现 electionTimeout 定时器 业务影响评估 参考链接 声明:本文同步发表于 MongoDB 中文社区,传送门: http ...
- MongoDB一次节点宕机引发的思考(源码剖析)【华为云分享】
目录 简介 日志分析 副本集 如何实现 Failover 心跳的实现 electionTimeout 定时器 业务影响评估 参考链接 声明:本文同步发表于 MongoDB 中文社区,传送门:http: ...
- CDN缓存机制
CDN也叫内容分发网络,是一个经策略性部署的整体系统,包括分布式储存.负载均衡.网络请求的重定向和内容管理4个要件.而其中内容管理和全局的网络流量管理是CDN的核心所在.通过用户就进行和服务器负载的判 ...
- C#无限极分类树-创建-排序-读取 用Asp.Net Core+EF实现之方法二:加入缓存机制
在上一篇文章中我用递归方法实现了管理菜单,在上一节我也提到要考虑用缓存,也算是学习一下.Net Core的缓存机制. 关于.Net Core的缓存,官方有三种实现: 1.In Memory Cachi ...
随机推荐
- android switch语句报错:case expressions must be constant expressions
今天无意中碰见了 case expressions must be constant expressions 的问题 写了一个 switch(item.getItemId()) { case R. ...
- css实现三角效果
demo <!DOCTYPE html> <html lang="zh"> <head> <meta charset=utf-8& ...
- 个人训练记录-赛码"bestcoder"杯中国大学生程序设计冠军赛
A.Movie 题意是给n个线段,要求求出是否存在三个不相交的线段,是的话输出yes,否则输出no.根据贪心的想法,可以先找出右端点r'最小的线段,他是三条线段中最左的那条,再找出左端点l'最大的线段 ...
- shell: bad interpreter: No such file or directory
执行shell脚本 错误提示如下: bash: ./back : bad interpreter:No such file or directory 因为操作系统是windows,在win ...
- CCNET+MSBuild+SVN实现每日构建
最近开始将源代码迁移到SVN,于是便考虑到如何从SVN定期获取源码,自动编译并部署以减轻工作量并提高工作效率.通过多方搜集资料并进行研究,基本实现了这个功能.对于每日构建的概念就不具体展开了,可以在各 ...
- Qt编译安装qwt错误moc/xxx Error:126
最近搞设计,需要在上位机上绘制曲线,在网上找了找,发现python的matplotlib和Qt的qwt都不错,本着难度最小原则,选择了Qt下面的qwt,安装过程中遇到了编译错误:moc/xxx Err ...
- Ansible 学习笔记
最近因为需要管理很多台机器,而这些机器又需要频繁重新安装,实在受不了Puppet需要在每个客户机上都安装一遍,于是转头开始学些Ansible.根据这段时间的使用,这个确实是神器,唯一的感觉就是相见恨晚 ...
- 响应式内容滑动插件jQuery.bxSlider
bxSlider特性 1.充分响应各种设备,适应各种屏幕: 2.支持多种滑动模式,水平.垂直以及淡入淡出效果: 3.支持图片.视频以及任意html内容: 4.支持触摸滑动: 5.支持Firefox,C ...
- 【数论】X problem
X problem X问题 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Othe ...
- listview和checkbox的冲突的用法
package com.exaple.music; import java.util.List; import java.util.Timer; import java.util.TimerTask; ...