杰瑞科技汇

Java memcached 过期时间如何设置?

核心要点

Memcached 的过期时间是一个非常重要的特性,它主要用于:

Java memcached 过期时间如何设置?-图1
(图片来源网络,侵删)
  1. 自动失效:当数据到达指定时间后,Memcached 会自动将其从内存中删除,无需客户端手动干预。
  2. 减少数据库压力:对于频繁访问但数据不常变更的信息(如配置、用户会话、热点数据),可以设置一个合理的过期时间,保证数据的“新鲜度”,同时避免频繁查询数据库。
  3. 内存管理:通过自动清理过期数据,Memcached 可以高效地利用有限的内存空间。

如何在 Java 客户端中设置过期时间

在 Java 中,我们通常使用一个客户端库来与 Memcached 交互,最流行的是 XmemcachedSpyMemcached,下面以 Xmemcached 为例进行说明,因为它性能更好,API也更现代化。

Xmemcached 设置过期时间

Xmemcached 的 setaddreplace 等方法都支持一个 expiry 参数来设置过期时间。

过期时间参数的单位是秒。

基本用法示例:

Java memcached 过期时间如何设置?-图2
(图片来源网络,侵删)
import net.rubyeye.xmemcached.MemcachedClient;
import net.rubyeye.xmemcached.XMemcachedClient;
import net.rubyeye.xmemcached.exception.MemcachedException;
import java.util.concurrent.TimeoutException;
public class MemcachedExpiryExample {
    public static void main(String[] args) {
        // 1. 创建 Memcached 客户端
        // 参数为 Memcached 服务器地址和端口
        try (MemcachedClient client = new XMemcachedClient("localhost", 11211)) {
            // --- 设置不同类型的过期时间 ---
            // a. 设置一个永不失效的项 (过期时间为 0)
            // 注意:永不失效并不意味着永远存在,它可能会因为内存不足而被 LRU 算法淘汰。
            // "never expire" 的特殊值是 0。
            client.set("user:session:123", 0, "some_session_data");
            System.out.println("设置了一个永不失效的键: user:session:123");
            // b. 设置一个 10 秒后过期的项
            client.set("config:app_settings", 10, "{\"theme\":\"dark\",\"lang\":\"zh-CN\"}");
            System.out.println("设置了一个10秒后过期的键: config:app_settings");
            // c. 设置一个 1 小时 (3600秒) 后过期的项
            client.set("cache:product_list", 3600, "product_data_string_or_object");
            System.out.println("设置了一个1小时后过期的键: cache:product_list");
            // --- 验证过期 ---
            System.out.println("\n立即获取 config:app_settings: " + client.get("config:app_settings"));
            // 等待11秒,让数据过期
            Thread.sleep(11000);
            System.out.println("11秒后再次获取 config:app_settings: " + client.get("config:app_settings"));
            // 输出应该是 null,因为数据已经过期并被删除
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

SpyMemcached 设置过期时间

SpyMemcached 的用法类似,也是在 set 方法中传入一个 int 类型的过期时间(单位秒)。

import net.spy.memcached.MemcachedClient;
import net.spy.memcached.internal.OperationFuture;
import java.net.InetSocketAddress;
import java.util.concurrent.TimeUnit;
public class SpyMemcachedExpiryExample {
    public static void main(String[] args) {
        try {
            MemcachedClient client = new MemcachedClient(
                    new InetSocketAddress("localhost", 11211));
            // 设置一个 30 秒后过期的项
            OperationFuture<Boolean> setFuture = client.set("key:with:expiry", 30, "Hello, Memcached!");
            System.out.println("Set operation status: " + setFuture.get());
            // 获取值
            System.out.println("Get key:with:expiry: " + client.get("key:with:expiry"));
            // 等待31秒
            TimeUnit.SECONDS.sleep(31);
            // 再次获取,应为 null
            System.out.println("Get key:with:expiry after 31s: " + client.get("key:with:expiry"));
            client.shutdown();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

过期时间的特殊值

Memcached 的过期时间参数支持一些特殊值,这在实际开发中非常有用。

值 (单位: 秒) 含义
0 永不失效,数据不会因为过期而被删除,但可能会因为内存不足而被 LRU(最近最少使用)算法淘汰。
*`< 60 60 24 30` (即小于30天)** 表示一个具体的秒数。3600 表示1小时后过期,这是最常用的方式。
*`>= 60 60 24 30` (即大于等于30天)** Memcached 会将其解释为一个 Unix 时间戳(UTC时间),而不是从现在开始的秒数。

使用 Unix 时间戳的示例:

如果你想设置一个在某个特定日期和时间过期的项,可以计算其 Unix 时间戳。

Java memcached 过期时间如何设置?-图3
(图片来源网络,侵删)
import java.time.Instant;
import java.time.temporal.ChronoUnit;
// 假设今天是 2025-10-27 10:00:00 UTC
// 我们想设置它在今天的 23:59:59 UTC 过期
Instant now = Instant.now();
Instant expiryTime = now.plus(13, ChronoUnit.HOURS).plus(59, ChronoUnit.MINUTES).plus(59, ChronoUnit.SECONDS);
// 获取 Unix 时间戳(秒)
long expiryTimestamp = expiryTime.getEpochSecond();
// 使用 Xmemcached 设置
client.set("daily_report_summary", (int) expiryTimestamp, "report data for 2025-10-27");

过期时间的底层机制

了解 Memcached 如何处理过期时间,有助于更好地使用它。

惰性删除

Memcached 主要采用 惰性删除 机制。

  • 工作原理:当客户端请求数据时,Memcached 在返回数据之前,会检查这个数据是否已经过期,如果已过期,它不会返回数据,而是直接将其从内存中删除,然后向客户端返回“未找到”(类似 null)。
  • 优点:对性能影响小,因为它只在数据被访问时才进行检查,不需要后台线程去扫描所有数据。
  • 缺点:已过期的数据会一直占用内存,直到有客户端再次访问它,如果某些数据过期后不再被访问,它们就会“赖”在内存里,造成浪费。

定期删除

为了弥补惰性删除的不足,Memcached 还有一个 定期删除 机制。

  • 工作原理:Memcached 内部有一个后台线程,它会每隔一段时间(通常是1秒)随机检查一部分(每个 slab 中随机检查一个 item)数据的过期时间。
  • 优点:可以更及时地清理掉大量过期但未被访问的数据,减轻惰性删除的压力,防止内存被长期无效数据占用。
  • 缺点:这个检查是随机的,所以不能保证所有过期数据都能被立即发现和删除。

Java 开发中的最佳实践

  1. 设置合理的过期时间

    • 不要过长:避免将热点数据设置成永不过期,这会导致数据“陈旧”,并可能占用过多内存。
    • 不要过短:过期时间太短会导致缓存频繁失效,穿透到后端数据库,增加数据库压力,反而失去了缓存的意义。
    • 根据业务场景定
      • 用户会话:30 分钟到几小时。
      • 热点商品信息:几分钟到几小时。
      • 系统配置:可以设置较长的时间(如几小时或1天),或者当配置变更时主动删除缓存。
      • 验证码:5 分钟。
  2. 主动更新 vs. 被动过期

    • 被动过期:依赖 set 时设置的 expiry 时间,这是最简单的方式。
    • 主动更新:当数据库中的数据被修改时,主动去删除或更新 Memcached 中的对应项,这可以保证缓存中的数据与数据库的强一致性,适用于对数据一致性要求高的场景。
  3. 处理缓存穿透

    • 缓存穿透是指查询一个根本不存在的数据,由于缓存中没有,请求会直接打到数据库上。
    • 解决方案:即使数据库中没有的数据,也将其在缓存中存一个“空值”或特殊标记,并设置一个较短的过期时间(如1分钟),这样下次请求就不会再打到数据库了。
  4. 使用连接池

    Xmemcached 和 SpyMemcached 都内置了高效的连接池,确保在

分享:
扫描分享到社交APP
上一篇
下一篇