【问题标题】:Objects from cache in PlayFramework seem to be the original objects?PlayFramework 中缓存的对象似乎是原始对象?
【发布时间】:2017-08-13 01:00:03
【问题描述】:

另一个关于缓存的 PlayFramework 2.x(具体来说是 2.5)相关问题。 Play 使用 EhCache,但我认为这是一个 Play 问题,而不是 EhCache 问题 - 但我可能错了。

所以我从缓存中获取对象。在此示例中,我从数据库中获取菜单项,然后突出显示当前菜单项。这是代码:

List<Menu> menuitems = cache.getOrElse("menu", () -> getMenuitemsFromDatabase(), DURATION_14_DAYS);
for (Menu menuitem : menuitems) {
    if (menuitem.getUrl().equals(request.uri())) {
        menuitem.setHighlighted(true);
        break;
    }
}

问题是,我总是从缓存中获取相同的对象。对于同一个对象,我实际上是指内存中的同一个对象。我猜它存储在内存中的某个哈希图中,我每次都获取相同的条目。

这意味着,当我浏览两个网站时,当前和上一个菜单项会突出显示。显然,如果我浏览更多网站,情况会变得更糟。

我期望(和需要)的是菜单项列表的副本。如果我用 Redis 替换 EhCache,我总是会得到副本(这是有道理的,因为 redis 服务器是另一台机器)。

那么,我如何告诉 Play 只获取缓存对象的副本。我真的不想手动复制所有这些对象。如果 Play 没有内置解决方案,那么通用方法是什么? 显然,缓存中的所有对象都是可序列化的,所以我想可以很容易地复制这些对象。

谢谢你, 舒贝

【问题讨论】:

    标签: java caching playframework-2.0 ehcache


    【解决方案1】:

    不确定这里使用的是哪个版本的 ehcache,因此如何解决此问题可能会有所不同……但如果不需要,Ehcache 确实不会复制对象。仅当还需要序列化时才需要它(例如您的 redis 用例)。但是只要条目保留在 JVM 的堆上,您确实会得到相同的对象。

    如何最好地解决这个问题?好吧,这取决于:您可以在 ehcache (2.x / 3.x) 的缓存级别强制“读/写复制”语义;但是如果我是您,我会考虑其他解决方案...因此,您正在为缓存访问引入不必要的延迟...但是我不确定在这个非常具体的用例中如何最好地解决

    无论如何,模仿 redis(在 VM 之外)读/写复制语义可能是最简单的,但性能也可能较低。

    【讨论】:

    • 感谢您的解释。通常,我不会更改缓存的对象,但在这种特殊情况下,我会突出显示菜单项,因此我会更改对象。我不知道,要么我复制菜单并突出显示副本中的当前项目,要么我循环遍历所有菜单项并将其他菜单项设置为menuitem.setHighlighted(false); 但我担心如果其他人访问该网站,那么我可能会参加比赛条件,因为两个用户都使用相同的对象并更改它...好吧,我将测试一些案例。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2017-10-30
    • 1970-01-01
    • 2021-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多