Caffeine Expiry 中如何设置多个过期标准?

2024-04-29

我正在使用 Caffeine v2.8.5,我想创建一个具有可变到期时间的缓存,基于:

  • 值的创建/更新以及
  • 该值的最后一次访问(读取)。

无论先发生什么都应该触发该条目的删除。


缓存将成为三层值解析的一部分:

  1. The key is present in the Caffeine cache
    • 使用这个值
    • 刷新访问/读取过期
  2. The key is present in the Redis database
    • 使用这个值
    • 将此值与剩余的值一起存储在咖啡因缓存中TTL(生存时间) https://redis.io/commands/ttlRedis 密钥的
  3. The key was neither present in the internal cache nor Redis
    • 从外部 REST API 请求值
    • 将此值存储在 Redis 数据库中,固定期限为 30 天
    • 将此值存储在 Caffeine 缓存中,固定期限为 30 天

Redis用作全局缓存,以便多个应用程序/实例可以共享缓存数据,但这种解析经常发生,以至于它不能用于每个请求,因此需要另一个缓存层。

根据请求时间,请求的数据具有不同的 TTL。因此,虽然当我们请求 REST API 时过期时间可能是固定的,并且过期时间是在 Redis 中设置的,但在 Caffeine 中该时间将是动态的,因为过期时间基于 Redis 密钥的剩余 TTL。

情况 (2) 和 (3) 已经在我的 Caffeine 缓存的 CacheLoader 中得到解决(我在通读模式下使用缓存)。为了控制我已经发现的过期时间,我必须利用高级过期 API https://github.com/ben-manes/caffeine/wiki/Eviction#time-based我也研究过类似的问题(指定条目的到期时间) https://stackoverflow.com/questions/51779879/caffeine-how-expires-cached-values-only-after-creation-time and (缓存值在创建时间后过期) https://stackoverflow.com/questions/51779879/caffeine-how-expires-cached-values-only-after-creation-time。所以我为我的键想出了一个包装对象,如下所示:

import lombok.Value;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.time.Instant;

@Value
public class ExpiringValue<ValueType> {

    @Nullable
    private final ValueType value;
    @NotNull
    private final Instant validUntil;
}

and an Expiry https://www.javadoc.io/doc/com.github.ben-manes.caffeine/caffeine/2.5.2/com/github/benmanes/caffeine/cache/Expiry.html像这样:

import com.github.benmanes.caffeine.cache.Expiry;
import org.jetbrains.annotations.NotNull;

import java.time.Duration;
import java.time.Instant;

public final class ValueBasedExpiry<KeyType, ValueType extends ExpiringValue<?>> implements Expiry<KeyType, ValueType> {

    @Override
    public long expireAfterCreate(
        @NotNull final KeyType key,
        @NotNull final ValueType value,
        final long currentTime
    ) {
        return Duration.between(Instant.now(), value.getValidUntil()).toNanos();
    }

    @Override
    public long expireAfterUpdate(
        @NotNull final KeyType key,
        @NotNull final ValueType value,
        final long currentTime,
        final long currentDuration
    ) {
        return currentDuration;
    }

    @Override
    public long expireAfterRead(
        @NotNull final KeyType key,
        @NotNull final ValueType value,
        final long currentTime,
        final long currentDuration
    ) {
        return currentDuration;
    }
}

我的用例的不同之处在于,我希望有一个基于该值的最后一次访问的第二个到期标准。因此,如果一个小时内没有提出请求,我想提前删除该条目。而如果频繁访问,最终会在 TTL 为零后被删除。

我将如何实施第二个标准?我不知道如何获取上次访问条目的时间。该接口似乎没有提供这样的值。我也调查过这个问题 https://stackoverflow.com/questions/62998616/caffeine-cache-delayed-entries-expiration-with-after-creation-policy。根据条目已排序到的调度程序存储桶,定期调用/重新评估这些方法是否正确?


我对如何做的一个很大的误解Expiries https://www.javadoc.io/doc/com.github.ben-manes.caffeine/caffeine/2.5.2/com/github/benmanes/caffeine/cache/Expiry.html工作,我认为,到期的方法将被定期触发和重新评估。我正在回答我自己的问题,以防有人从他们的研究中得到同样的印象。

内的方法Expiry https://www.javadoc.io/doc/com.github.ben-manes.caffeine/caffeine/2.5.2/com/github/benmanes/caffeine/cache/Expiry.html仅在执行相应方法名称的操作后才调用(因此仅更新值)。例如expireAfterRead(K, V, long, long)仅当每次在缓存中读取此键值映射时才会调用。

因此,如果映射在创建后永远不会有任何操作(不读取或更新),则只有expireAfterCreate(K, V, long)方法将被调用一次。这就是为什么所有方法都应始终返回其余的持续时间,但不必考虑上次读取条目的时间,因为该时刻就是现在(如Instant.now()), the expireAfterRead(K, V, long, long)叫做。

正如 @BenManes 在评论中指出的那样,我最初问题的正确解决方案正在返回

Math.min(TimeUnit.HOURS.toNanos(1), Duration.between(Instant.now(), value.getValidUntil()).toNanos())

在 Expiry 的所有三种方法中。


并回答我在帖子中的另外两个问题:

我如何获得最后一次访问条目的时间?打电话(例如)Instant.now() in the expireAfterRead(K, V, long, long)方法。如果您还想在外部或在其他过期方法中拥有该值,则始终可以选择使用易失性字段将此值存储在 ExpiringValue 中。

根据条目已排序到的调度程序存储桶,定期调用/重新评估这些方法是否正确?不会。如上所述,只有执行相应操作后,Expiry 中的方法才会被调用。这些方法不会定期触发或重新评估。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Caffeine Expiry 中如何设置多个过期标准? 的相关文章

  • Kafka - 如何同时使用过滤器和过滤器?

    我有一个 Kafka 流 它从一个主题获取数据 并且需要将该信息过滤到两个不同的主题 KStream
  • 如何以编程方式使用包含多列的 where-in 子句执行 PostgreSQL 查询?

    我的查询是这样的 select from plat customs complex where code t code s in 01013090 10 01029010 90 它在 psql 控制台中运行良好 我的问题是如何在客户端代码中
  • 为什么在 10 个 Java 线程中递增一个数字不会得到 10 的值?

    我不明白 a 的值为0 为什么 a 不是10 那段代码的运行过程是怎样的 是否需要从Java内存模型来分析 这是我的测试代码 package com study concurrent demo import lombok extern sl
  • 什么是内部类的合成反向引用

    我正在寻找应用程序中的内存泄漏 我正在使用的探查器告诉我寻找这些类型的引用 但我不知道我在寻找什么 有人可以解释一下吗 Thanks Elliott 您可以对 OUTER 类进行合成反向引用 但不能对内部类实例进行合成 e g class
  • 我对线程失去了理智

    我想要这个类的对象 public class Chromosome implements Runnable Comparable
  • 自定义列表字段点击事件

    我正在编写一个应用程序 其中我创建了用于显示列表视图的自定义列表字段 我的 CustomListField 包含连续的一个图像和文本 我正在通过单击列表字段行获取字段更改侦听器 但我也想将字段更改侦听器放在图像上 谁能告诉我我该怎么做 这是
  • Java中Gson、JsonElement、String比较

    好吧 我想知道这可能非常简单和愚蠢 但在与这种情况作斗争一段时间后 我不知道发生了什么 我正在使用 Gson 来处理一些 JSON 元素 在我的代码中的某个位置 我将 JsonObject 的 JsonElements 之一作为字符串获取
  • 使用 OkHttp 下载损坏的文件

    我编写的下载文件的方法总是会产生损坏的文件 public static String okDownloadToFileSync final String link final String fileName final boolean te
  • 如何使用 Java 引用释放 Java Unsafe 内存?

    Java Unsafe 类允许您按如下方式为对象分配内存 但是使用此方法在完成后如何释放分配的内存 因为它不提供内存地址 Field f Unsafe class getDeclaredField theUnsafe Internal re
  • 为什么 jar 执行的通配符在 docker CMD 中不起作用?

    我有一个Dockerfile与以下CMD启动我的 Spring Boot 应用程序 FROM java 8 jre CMD java jar app file jar 当我尝试从创建的图像启动容器时 我得到 Error Unable to
  • 2^31 次方的 Java 指数错误 [重复]

    这个问题在这里已经有答案了 我正在编写一个java程序来输出2的指数幂 顺便说一句 我不能使用Math pow 但是在 2 31 和 2 32 处我得到了其他东西 另外 我不打算接受负整数 My code class PrintPowers
  • 数据库中的持久日期不等于检索日期

    我有一个具有 Date 属性的简单实体类 此属性对应于 MySQL 日期时间列 Entity public class Entity Column name start date Temporal TemporalType TIMESTAM
  • Android - 存储对ApplicationContext的引用

    我有一个静态 Preferences 类 其中包含一些应用程序首选项和类似的内容 可以在那里存储对 ApplicationContext 的引用吗 我需要该引用 以便我可以在不继承 Activity 的类中获取缓存文件夹和类似内容 你使用的
  • Spring Data Rest 多对多 POST

    首先 让我解释一下我的用例 这非常简单 有一个用户实体和一个服务实体 我使用 UserService 作为连接实体 连接表 在用户和服务之间建立多对多关联最初 会有一些用户集和一些服务集 用户可以在任何时间点订阅任何服务 在这种情况下 将向
  • 在 Java 中通过 D-Bus MPRIS 访问 Clementine 实例

    我使用 Clementine 作为音乐播放器 它可以通过 D Bus 命令进行控制 在命令行上 使用 qdbus 我可以 Start Stop 暂停播放器 强制它跳过播放列表中的歌曲 检查播放列表的长度 检查播放列表中当前播放的曲目及其元数
  • 带 getClassLoader 和不带 getClassLoader 的 getResourceAsStream 有什么区别?

    我想知道以下两者之间的区别 MyClass class getClassLoader getResourceAsStream path to my properties and MyClass class getResourceAsStre
  • 如何让 Firebase 与 Java 后端配合使用

    首先 如果这个问题过于抽象或不适合本网站 我想表示歉意 我真的不知道还能去哪里问 目前我已经在 iOS 和 Android 上开发了应用程序 他们将所有状态保存在 Firebase 中 因此所有内容都会立即保存到 Firebase 实时数据
  • 使用 DBCP 配置 Tomcat

    在闲置一段时间 几个小时 后 我们收到了 CommunicationsException 来自 DBCP 错误消息 在异常中 位于这个问题的末尾 但我没有看到任何配置文件中定义的 wait timeout 我们应该看哪里 在 tomcat
  • 在会话即将到期之前调用方法

    我的网络应用程序有登录的用户 有一个超时 在会话过期之前 我想执行一个方法来清理一些锁 我已经实现了sessionListener但一旦我到达public void sessionDestroyed HttpSessionEvent eve
  • 设置 TreeSet 的大小

    有没有办法像数组一样对 Java 集合中的 TreeSet 进行大小限制 例如我们在数组中 anArray new int 10 数组具有固定长度 在创建数组时必须指定该长度 A TreeSet当您向其中添加元素时会自动增长 您无法设置其大

随机推荐

  • ASP.net kerberos 偶尔下降到 NTLM

    背景 仅相关部分 我们有一个大型 Intranet asp net 2 0 3 5 应用程序 Web服务器是AD域上的Windows Server 2003 客户端使用 Windows IE 6 8 Windows 身份验证 具有从 Win
  • PHP内部hashCode函数

    我正在寻找与 JAVA 等效的 PHP SomeString hashCode 功能 我正在寻找的 hashCode 应该与 PHP 中用于索引 Hashmap 的 hashCode 相同 我希望你可以帮助我 EDIT 好的 找到了我正在搜
  • WPF 重复按钮 MouseUp

    有没有办法让重复按钮上的 MouseUpevent 在不再按下按钮时触发 我试图使用 MouseMove 事件来跟踪按下按钮时鼠标的位置 但 MouseDown 和 MouseUp 都不会触发鼠标左键的事件 关于可以做什么的任何想法或建议
  • 如何将图像(位图)调整为给定尺寸? [复制]

    这个问题在这里已经有答案了 如何以编程方式将图像 位图 大小调整为例如 800 480 我在我的应用程序中检索了一张约 1MB 的图片 我需要将其缩小到 800 480 我已经加载了该图片并对其进行了压缩 但是如何使其变小 ByteArra
  • 选择组合框文本

    我有一个组合框声明如下
  • 将Pycharm项目移动到另一个目录

    我的主目录空间不足 我想将 PyCharm 项目移动到另一个目录 我最终复制了它 因为重构不起作用 我删除了 pycache 和 zip 异常 出现的异常消失了 现在一切都按预期工作 不过 从 settings python interpr
  • 如何使用 GitHub README 中的 Markdown 渲染多列?

    为了呈现三列中的项目 我尝试将以下 CSS3 指令添加到我的项目中README md文件 但样式被删除 div div style display inline block div div div div
  • 从我的应用程序创建日历事件,无需默认提醒

    我正在开发一个应用程序 可以创建 更新和删除原生 Google 日历中的事件 我正在通过以下代码创建一个事件 ContentValues cvEvent new ContentValues cvEvent put Events DTSTAR
  • `geom_line()` 连接映射到不同组的点

    我想group我的数据基于两个变量的相互作用 但仅将美学映射到其中一个变量 另一个变量代表重复 理论上 它们应该彼此相等 我可以找到不优雅的方法来做到这一点 但似乎应该有更优雅的方法来做到这一点 例如 Data frame with two
  • 如何使用 url_for() 将路径和查询数据传递到使用 FastAPI 和 Jinja2 的路由?

    我想从 Jinja2 模板中调用 FastAPI 路由 并传递两者path and query该路由的数据 参数 我在 Jinja2 模板中尝试过如下所示 url for function1 uustr data uustr interva
  • 从 R 中的 Sys.Date() 获取当前时间(包括秒)

    我确信这是非常基本的 但我无法从系统日期中提取各种时间 简而言之 我不确定为什么我无法使用 M 或 S 准确提取当前的分钟和秒数 有什么想法吗 我的机器上当前时间为中午 12 38 gt format Sys Date c 1 12 16
  • “冲突可序列化”和“冲突等效”有什么区别?

    在数据库理论中 冲突可序列化 和 冲突等效 有什么区别 我的教科书有一个关于可序列化冲突的部分 但掩盖了冲突等价性 这些可能都是我熟悉的概念 但我不熟悉术语 所以我正在寻找解释 DBMS 中的冲突可以定义为两个或多个不同的事务访问同一变量
  • 将带有变量的循环转换为 BigQuery SQL

    我有数千个脚本 其中包括循环数据集并使用变量进行累积 例如 assuming that ids is populated from some BQ table ids 1 2 3 4 5 var1 v1 initialize variabl
  • 如何使用 RealmSwift 存储字典?

    考虑以下模型 class Person Object dynamic var name let hobbies Dictionary
  • 清漆配置文件在哪里?

    我刚刚安装了清漆并准备好提供网页服务 问题是我们达到了打开文件限制 我们已经设定了ulimit给清漆用户 我们想要找到一个可以写入此配置的文件 Maximum number of open files NFILES 131072 Locke
  • ios7 UITableViewCell SelectionStyle 不会变回蓝色

    Xcode 5 0 iOS 7 并更新现有应用程序 UITableView所选行现在是灰色的 而不是蓝色的 据我所知 他们更改了默认值selectionStyle至灰色 但 蓝色 仍然是 IB 的一个选项UITableViewCellSel
  • 在内核模块中执行shell命令

    是否可以在内核模块中执行shell命令 我知道我们可以在用户空间 C 代码中使用system子程序 我正在调试一个存在内存泄漏问题的内核模块 在无限循环中执行 insmod 和 rmmod module ko 后 8G RAM 的系统在几分
  • boost Deadline_timer 最小示例:我应该替换“睡眠”吗?

    我有一个线程 我需要每 10 毫秒执行一些操作 所以我有非常简单的代码 如下所示 while work do something Sleep 10000 boost sleep can be also used 我听说Sleep一般不推荐
  • 避免在react + typescript中使用通用函数类型

    我正在寻找一条规则来阻止使用 函数 作为类型 myMethod Function 我没有找到任何东西 所以我愿意接受建议 您可以使用 typescript eslint ban types rule 规则链接 https github co
  • Caffeine Expiry 中如何设置多个过期标准?

    我正在使用 Caffeine v2 8 5 我想创建一个具有可变到期时间的缓存 基于 值的创建 更新以及 该值的最后一次访问 读取 无论先发生什么都应该触发该条目的删除 缓存将成为三层值解析的一部分 The key is present i