Skip to content

Memcached - 前置数据

prepend 命令是一个原子操作,它将数据添加到给定 key 的现有值的开头。这对于添加元数据或更新列表等任务非常有用,而无需先读取整个值。

prepend 命令的基本语法如下:

prepend key flags exptime bytes [noreply]
<value>
  • key: 要修改项的键。
  • flags: 一个与项一起存储的 32 位整数,可在 get 调用时检索。
  • exptime: 项新的过期时间,以秒为单位。值为 0 表示永不Expire(过期)。
  • bytes: 您要预置的数据大小,以字节为单位。
  • [noreply](可选):指示服务器不发送响应,这可以在写入密集型场景中提高性能。
  • value: 要预置的数据。

让我们使用 telnet 来演示。首先,我们设置一个 key,然后向其预置数据。

# 连接到 Memcached
$ telnet localhost 11211
# 1. 设置一个初始的键值对
set site 0 900 11
example.com
STORED
# 2. 向现有值预置前缀
prepend site 0 900 8
https://
STORED
# 3. 检索最终值
get site
VALUE site 0 19
https://example.com
END

服务器在成功时响应 STORED。如果 key 不存在,它将响应 NOT_STORED。

现代开发:使用 Java 客户端预置数据

Section titled “现代开发:使用 Java 客户端预置数据”

在实际应用程序中,您将使用客户端库与 Memcached 交互。以下示例使用流行的 spymemcached Java 库。

将 spymemcached 依赖项添加到您项目的 pom.xml 中:

<dependency>
<groupId>net.spy</groupId>
<artifactId>spymemcached</artifactId>
<version>2.12.3</version> <!-- 使用最新的稳定版本 -->
</dependency>
import net.spy.memcached.MemcachedClient;
import net.spy.memcached.internal.OperationFuture;
import java.net.InetSocketAddress;
public class PrependExample {
public static void main(String[] args) {
// 使用 try-with-resources 进行自动连接管理和清理
try (MemcachedClient mcc = new MemcachedClient(new InetSocketAddress("127.0.0.1", 11211))) {
System.out.println("Connection to Memcached server successful.");
String key = "user:profile:activity";
String initialActivity = "viewed_homepage";
String newActivity = "clicked_login,";
// 1. 为键设置一个初始值(15 分钟过期)
OperationFuture<Boolean> setFuture = mcc.set(key, 900, initialActivity);
if (setFuture.get()) { // .get() 会阻塞,直到操作完成
System.out.println("Successfully set initial value for key '" + key + "'.");
}
// 2. 检索当前值以验证
System.out.println("Current value: " + mcc.get(key));
// 3. 将新的活动数据预置到现有字符串
OperationFuture<Boolean> prependFuture = mcc.prepend(key, newActivity);
if (prependFuture.get()) {
System.out.println("Successfully prepended '" + newActivity + "'.");
}
// 4. 检索更新后的值
System.out.println("Updated value: " + mcc.get(key));
} catch (Exception e) {
System.err.println("An error occurred: " + e.getMessage());
// 在生产应用程序中,使用适当的日志框架(例如 SLF4J)
e.printStackTrace();
}
}
}
Connection to Memcached server successful.
Successfully set initial value for key 'user:profile:activity'.
Current value: viewed_homepage
Successfully prepended 'clicked_login,'.
Updated value: clicked_login,viewed_homepage
  • 原子性: prepend 是一个原子操作。这使得它可以在并发环境中安全使用,无需在应用程序级别进行锁定即可完成简单的前缀添加任务。
  • 键必须存在: 如果 key 不存在于缓存中,该操作将失败(NOT_STORED)。您的应用程序逻辑必须处理这种情况,例如先设置一个初始值。
  • 项大小限制: 请注意 Memcached 的默认项大小限制(通常为 1MB)。重复地向一个 key 预置数据而不使其过期,可能导致项超出此限制,从而产生错误。
  • 使用场景: prepend 非常适合维护时间有序的列表(最新项优先)、添加版本号或元数据等前缀,或在缓存中构建日志字符串。