杰瑞科技汇

Java memcached过期时间如何设置与优化?

Memcached 过期时间的核心概念

在深入 Java 客户端之前,必须先理解 Memcached 服务端是如何处理过期时间的。

Java memcached过期时间如何设置与优化?-图1
(图片来源网络,侵删)
  • 单位:过期时间的单位是
  • 设置方式:在 set, add, replaceSTORE 命令中,通过一个额外的参数来指定。
  • 过期时间范围
    • 大于 0 的整数:表示在多少秒后过期。3600 表示 1 小时后过期。
    • 0:表示 立即过期,这相当于删除该缓存项,这在某些场景下比 delete 命令更高效,因为它避免了网络往返(客户端发送删除命令,服务端确认)。
    • *小于 `60602430(即 30 天) 的 Unix 时间戳**:表示在指定的 UTC 时间点过期。1672531200` 代表 2025-01-01 00:00:00 UTC。
    • *大于等于 `60602430` 的整数Memcached 会将其解释为 Unix 时间戳** 而不是秒数,这是为了避免在设置远期过期时间(如 30 天后)时误用。
  • 惰性删除:Memcached 不会在后台主动扫描所有键来检查是否过期,它只在客户端请求某个键时,才会检查该键是否已过期,如果已过期,它不会返回数据,并在内存中将其释放。
  • LRU 策略:当 Memcached 内存不足时,它会使用 最近最少使用 策略来淘汰内存中的数据,即使一个数据还没到过期时间,也可能因为很久没有被访问而被 LRU 算法淘汰。

Java 客户端设置过期时间

在 Java 中,我们通常使用第三方客户端库来与 Memcached 交互,最流行和功能最强大的库是 XMemcached,我们以它为例来讲解。

1 Maven 依赖

在你的 pom.xml 文件中添加 XMemcached 的依赖:

<dependency>
    <groupId>com.googlecode.xmemcached</groupId>
    <artifactId>xmemcached</artifactId>
    <version>2.4.7</version> <!-- 建议使用较新版本 -->
</dependency>

2 核心方法:setadd

XMemcached 客户端提供了 setadd 方法来存储数据,它们都支持过期时间参数。

  • set(String key, int expiration, Object value)

    Java memcached过期时间如何设置与优化?-图2
    (图片来源网络,侵删)
    • 功能:将一个值与一个键关联,如果键已存在,则覆盖其旧值。
    • 参数
      • key: 缓存键。
      • expiration: 过期时间(秒),这是设置过期时间的关键参数。
      • value: 要缓存的对象。
  • add(String key, int expiration, Object value)

    • 功能:将一个值与一个键关联。仅当键不存在时才会设置成功,如果键已存在,操作会失败。
    • 参数:与 set 方法相同。

3 代码示例

下面是一个完整的示例,演示如何使用 XMemcached 设置不同类型的过期时间。

import net.rubyeye.xmemcached.MemcachedClient;
import net.rubyeye.xmemcached.XMemcachedClient;
import net.rubyeye.xmemcached.exception.MemcachedException;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class MemcachedExpirationExample {
    public static void main(String[] args) {
        // 1. 创建 Memcached 客户端
        // 参数是 Memcached 服务器地址和端口
        try (MemcachedClient memcachedClient = new XMemcachedClient("localhost", 11211)) {
            System.out.println("--- 设置 10 秒后过期的键 ---");
            // 设置一个键 "user:1001",10 秒后过期
            memcachedClient.set("user:1001", 10, "Alice");
            System.out.println("设置 'user:1001' 成功,值为 'Alice',10秒后过期。");
            // 立即获取,应该能拿到
            Object value = memcachedClient.get("user:1001");
            System.out.println("立即获取 'user:1001': " + value);
            // 等待 11 秒,让缓存过期
            Thread.sleep(11000);
            // 再次获取,应该为 null
            value = memcachedClient.get("user:1001");
            System.out.println("11秒后获取 'user:1001': " + value); // 预期输出: null
            System.out.println("\n--- 设置 0 秒后过期的键 (立即删除) ---");
            // 先设置一个值
            memcachedClient.set("temp_key", 3600, "This is a temporary value.");
            System.out.println("设置 'temp_key' 成功,值为 'This is a temporary value.'。");
            // 使用 0 作为过期时间,立即删除
            memcachedClient.set("temp_key", 0, null); // 值设为 null,过期时间设为 0
            // 或者更直接的方式是使用 delete 命令: memcachedClient.delete("temp_key");
            System.out.println("设置 'temp_key' 过期时间为 0,相当于删除。");
            // 获取,应该为 null
            value = memcachedClient.get("temp_key");
            System.out.println("获取 'temp_key': " + value); // 预期输出: null
            System.out.println("\n--- 使用 add 方法,键已存在则设置失败 ---");
            // 先设置一个键
            memcachedClient.set("another_key", 60, "First Value");
            System.out.println("首次设置 'another_key' 成功。");
            // 尝试用 add 方法再次设置同一个键,这会失败
            boolean result = memcachedClient.add("another_key", 120, "Second Value");
            System.out.println("尝试用 add 方法再次设置 'another_key': " + result); // 预期输出: false
            // 获取值,仍然是第一次设置的值
            value = memcachedClient.get("another_key");
            System.out.println("获取 'another_key' 的值: " + value); // 预期输出: First Value
        } catch (IOException | InterruptedException | TimeoutException | MemcachedException e) {
            e.printStackTrace();
        }
    }
}

其他相关操作

除了在存储时设置过期时间,还有一些其他相关操作。

1 replace 方法

replace 方法用于更新一个已存在的键的值,如果键不存在,操作会失败,它同样支持在更新时修改过期时间。

Java memcached过期时间如何设置与优化?-图3
(图片来源网络,侵删)
// 假设 "user:1001" 已存在且过期时间为 10 秒
// 将其值更新为 "Bob",并重置过期时间为 60 秒
boolean replaced = memcachedClient.replace("user:1001", 60, "Bob");
System.out.println("replace 操作是否成功: " + replaced); // 如果键存在,则为 true

2 touch 方法

这是一个非常有用的方法,它允许你在不改变键值的情况下,更新其过期时间

  • 用途:当你发现一个即将过期的键仍然被频繁访问时,可以使用 touch 来“延长”它的生命,而无需从数据库重新加载整个值。
  • 参数:键和新过期时间(秒)。
// 假设 "user:1001" 存在且即将过期
// 将其过期时间延长到 5 分钟 (300 秒) 后
boolean touched = memcachedClient.touch("user:1001", 300);
System.out.println("touch 操作是否成功: " + touched); // 预期输出: true

3 delete 方法

delete 方法用于立即从缓存中移除一个键,它没有过期时间参数,因为它的作用是立即删除。

// 立即删除 "user:1001"
memcachedClient.delete("user:1001");

最佳实践和注意事项

  1. 选择合适的过期时间
    • 对于热点数据(如首页信息、用户会话),可以设置较长的过期时间(如 30 分钟到几小时)。
    • 对于可能频繁变化的数据(如商品库存、用户状态),应设置较短的过期时间(如几秒或几分钟),或者采用缓存穿透/雪崩
分享:
扫描分享到社交APP
上一篇
下一篇