前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Hibernate二级缓存

Hibernate二级缓存

作者头像
全栈程序员站长
发布2022-08-31 21:40:29
4610
发布2022-08-31 21:40:29
举报

大家好,又见面了,我是你们的朋友全栈君。

因为项目中经常出现,由于使用了hibernate生成的方法,会从二级缓存中拿取数据,导致数据不一致的问题,甚至导致出现脏数据的问题,所以总结以下hibernate的缓存机制。

什么是二级缓存

我们知道一级缓存,并且一级缓存的作用范围就在session中,每个session都有一个自己的一级缓存,而二级缓存也就是比一级缓存的作用范围更广,存储的内容更多,我们知道session是由sesssionFactory创建出来的,一个sessionFactory能够创建很多个session,每个session有自己的缓存,称为一级缓存,而sessionFactory也有自己的缓存,存放的内容供所有session共享,也就是二级缓存。

Hibernate二级缓存
Hibernate二级缓存

 一级缓存:保存session中,事务范围的缓存(通俗点讲,就是session关闭后,该缓存就没了,其缓存只能在session的事务开启和结束之间使用)

 二级缓存:保存在SessionFactory,进程范围内的缓存(进程包括了多个线程,也就是我们上面说的意思,A线程可能拿到一个session进行操作,B线程也可能拿到一个session进行操作,但是A和B读能访问到SessionFactory中的缓存,也就是二级缓存,这里只是拿A,B说事,可能有一个线程刚创建出来session,也能拿到二级缓存中的数据)

hql做的查询能够存入一级缓存和二级缓存,但是不能够从二级缓存中拿数据

get\load能够将其查询数据插入一级缓存和二级缓存,也能够从一级二级缓存中拿数据。

例如:

我们有一个Order对象,是一个实体对象,对应数据库中order表中的一条记录,经过查询已有n个Order对象被放入二级缓存中。现在我们要修改order表中任意任x条记录,执行以下HQL:

template.bulkUpdate(“update Order set owner = ? where id in (?,?,?)”);

这时Hibernate会直接将二级缓存中的n个Order对象清除掉。 天啊,居然不是你想像的修改谁就同步更新二级缓存中的谁,而是清除了二级缓存中全部的Order类型的对象。为什么?这一切是为了保证“数据一致性”。你执行了HQL修改了order表中的x条记录,这x条是哪几条?如果sql是子查询:update Order set owner =? where id in(select id from *** ),谁知道你修改了order表中的哪几条记录,你自己都不知道,Hibernate更不知道了。所以为了保证二级缓存中的数据与order表中的数据一致,只能清除了二级缓存中全部的Order类型的对象。二级缓存频繁的载入与清除,这样缓存命中率就会下降。

二级缓存的更新机制

 存放了对于查询结果相关的表进行插入,更新,删除操作的时间戳,Hibernate通过时间戳缓存区域来判断被缓存的查询结果是否过期,如果过期了则从数据库中拿数据,没过期则直接从缓存中拿数据。通俗点讲,就三步

1、查询结果放到二级缓存中,此时记录一个时间为T1

2、当有操作直接更改了数据库的数据时,比如使用hql语句,就会直接对数据库进行修改,而不会改变缓存中的数据。此时记录时间为T2

3、当下次在查询记录时,会先将T1和T2进行比较,如果T2>T1,则说明缓存中的数据不是最新的,那么就从数据库中拿出正确的数据,如果T2<T1,就说明没有对数据库进行过什么修改操作,那么就可以直接从缓存中获取数据。

解惑:如果没有T1和T2的比较,那么会出现我们查询到的数据不是准确的,因为就像上面第二步所说的,数据库的数据会和缓存中的数据不一样,什么都不做就从缓存中拿数据,就会出现错误。

这里需要注意:如果你用了update语句,那么二级缓存无法更新。因为系统无法判断二级缓存的对象哪些失效了。如果你是update(对象)的方式更新,则系统可以通过ID确认哪个二级缓存对象需要更新,系统能够维护二级缓存。

项目中出现的缓存问题分析

由于项目的beta和prod环境是有多台server集群的,所以如果在某些对数据一致性要求较高的地方使用了二级缓存(也就是从缓存中取数据,不是直接从db中查取数据),就会出现数据一致性问题。

原因:由于server的elb机制是粘性session,那么就可能出现用户A和admin连上了两台不同的server,并且所有的db操作都是在不同的server上进行的,这时候如果admin更新的用户A的状态信息,只会刷新admin所连接server的二级缓存,并不会刷新其他server的缓存,而用户A并不能及时获取到db的更新,如果所有的地方都是从二级缓存中取数据就还好,只会出现延时的问题,这种可能性比较小。但如果不是全部都从二级缓存中取数据,那用户A就会出现数据不一致问题,甚至导致页面挂掉。

上面这种情况当清楚的db的catch之后就可以恢复正常,但还有一种更严重的情况,如果用户A从缓存中获取的和db不一致的数据,并做的相应的更新操作,那么就会直接导致数据库出现脏数据,直接导致这个用户出现问题。

所以hibernate需要慎用,在更新较为频繁或者对数据一致性较高的地方不要使用二级缓存,否则会得不偿失。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/142112.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022年5月2,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是二级缓存
  • 例如:
  • 二级缓存的更新机制
  • 项目中出现的缓存问题分析
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档