Java 什么时候拥有Hibernate二级缓存的CPU优势会超过最初的影响

Java 什么时候拥有Hibernate二级缓存的CPU优势会超过最初的影响,java,hibernate,ehcache,Java,Hibernate,Ehcache,将对象添加到Hibernate二级对象缓存的CPU好处何时超过最初的影响 我目前正在使用没有二级缓存的Hibernate。这适用于处理音乐文件()的应用程序,它使用Hibernate,因此可以使用更多的数据进行扩展,也就是说,它可以处理100000首歌曲,而内存仅比1000首歌曲多一点。处理完歌曲后,这些歌曲就不感兴趣了(除非用户运行Undo) 据我所知,如果我启用二级缓存(对于我的歌曲类),那么歌曲到缓存的初始写入将使用更多的cpu,如果只是写入数据库,那么对歌曲对象的额外修改也将需要更多的c

将对象添加到Hibernate二级对象缓存的CPU好处何时超过最初的影响

我目前正在使用没有二级缓存的Hibernate。这适用于处理音乐文件()的应用程序,它使用Hibernate,因此可以使用更多的数据进行扩展,也就是说,它可以处理100000首歌曲,而内存仅比1000首歌曲多一点。处理完歌曲后,这些歌曲就不感兴趣了(除非用户运行Undo)

据我所知,如果我启用二级缓存(对于我的歌曲类),那么歌曲到缓存的初始写入将使用更多的cpu,如果只是写入数据库,那么对歌曲对象的额外修改也将需要更多的cpu资源。但随后从Ehcache检索歌曲所需的资源比从数据库检索歌曲所需的资源要少

我的歌曲会被一个文件夹一个文件夹地处理,并经过许多阶段(在不同的执行器上),当它们在下一个执行器上排队时,我们只需将歌曲ID作为参数传递,否则将使用大量堆内存存储歌曲对象本身。因此,当某个特定任务在执行器上实际运行时,它要做的第一件事就是检索这些ID的歌曲

因此,没有特定的歌曲ID会被检索1000次,但每首歌曲通常会被写入1到4次,并检索10次。因此,如果我们有一个相当小的缓存(因为我想保持堆内存处于紧密控制之下),我希望处理的前几个文件夹将其歌曲添加到缓存中,然后当它们完成歌曲时,新文件夹中的歌曲将在缓存中取代它们的位置

但我的问题是,这值得吗


根据经验,10次检索与1-4次写入相比,使用二级缓存是有意义的,或者只有在比率更接近100:1时才有用?

真正的答案是:只需对其进行基准测试。

写入堆缓存并没有那么昂贵。因此,是的,即使从缓存中检索一次,也会使它比返回数据库更快

然后,缓存在HashMap上主要做两件事。它驱逐并过期

逐出意味着您为缓存设置了一些最大大小。当达到该值时,缓存将逐出“最旧”条目以添加新条目。最早的有多个定义。Ehcache对一组条目进行采样,并剔除样本中最长时间未访问的条目

过期意味着给定的条目在某个时候将被视为过时。例如,您希望在使用数据库中最新的条目刷新条目前1小时保留条目。当您获得一个条目时,Ehcache首先查看该条目是否过期。如果是,它将返回null并从缓存中删除条目。这意味着过期条目将保留在缓存中,直到您尝试访问它

在您的情况下,您需要加载一次条目。然后把它放在缓存里。使用它并最终删除它以节省内存。如果你有一个最后的步骤,你知道你将不再需要该条目,只需将其删除

如果你不这样做,你将不得不依靠驱逐。因为逐出算法将首先删除过期条目(如果可以删除过期条目,为什么要删除完全有效的条目?)

您应该计算一个条目应该在缓存中停留多少时间才能通过所有执行器。这将是您的到期时间(TTL)。然后将缓存大小调整为
NB\u EXECUTORS*NB\u STEPS
。它将是当前使用的歌曲的大小。添加新歌时,缓存将需要逐出旧条目。在大多数情况下,此条目将过期,因此不会造成任何伤害

为了防止逐出(如果找不到过期的条目,这可能会很昂贵),您可以编写一个获取条目的后台例程。它将触发过期。但同样,在使用基准测试确定它实际上更快之前,不要这样做

最后,您可能希望直接缓存歌曲,而不是使用Hibernate level 2。因为它需要更少的操作来获得歌曲。此外,在写入二级缓存中的条目时,Hibernate往往会从缓存中退出。确保将其配置为而不是执行该操作

关于修改的注释。默认情况下,堆缓存上的Ehcache(并且仅在堆缓存上)是每个引用。因此,如果从缓存中检索歌曲对象,然后对其进行修改,缓存中的条目也会被修改,因为它实际上是唯一的实例

然而,Hibernate二级缓存不是这样工作的。它们将在缓存中保留某种数据库行。这将转换为歌曲并返回给您

当您将歌曲保存到数据库时,Hibernate将从缓存中将其逐出,正如我上面所说的(但您可能会在配置中要求缓存更新,我对此不确定)

这就是为什么我认为应该直接缓存,而不是使用二级缓存。但是,请注意,因为您将通过Hibernate加载对象。在将其放入缓存之前,需要将其与Hibernate分离。然后将其附加到新的执行器中。否则,例如,如果你有收藏,奇怪的事情就会发生

现在,假设您希望每次都更新缓存和数据库。你有两种方法

将缓存放在一边,您将更新数据库,然后更新缓存


通过Cache-through,您将更新缓存,该缓存将负责(自动)更新数据库。由于需要提供一个
CacheLoaderWriter
实现,所以Cache-through更为复杂。但它确保缓存和数据库始终同步。

我在内部争论,这是否适合SO.@Sir.Hedgehog为什么不合适?因为这是关于软件如何影响硬件的问题。在这种情况下,它可能属于超级用户,例如。这不是一个程序问题