Skip to content

Memcached - 添加数据

add 命令用于存储键值对(key-value pair),但仅当键(key)在服务器上不存在时才成功。这使得它适用于只应成功一次的操作,例如设置初始值或获取锁(lock)。

add 命令的基本语法是:

add key flags exptime bytes [noreply]
value

参数定义如下:

  • key:数据的唯一标识符。用于存储和检索值。
  • flags:一个 32 位无符号整数(unsigned integer),服务器会与数据一起存储。客户端库可将其用于元数据(metadata)(例如,标记数据是否已序列化)。
  • exptime:过期时间(expiration time),单位为秒。值为 0 表示永不失效。对于大于 30 天(2592000 秒)的值,它将被视为 Unix 时间戳(Unix timestamp)。
  • bytes:value 的大小,单位为字节(bytes)。此值必须准确。
  • [noreply] (可选):指示服务器不发送回复。
  • value:要存储的数据。必须在新的一行发送。
  • STORED:表示数据已成功存储。
  • NOT_STORED:表示键已存在,因此数据未存储。

这里,我们首先添加一个新键 job:123,它会成功。然后,我们尝试再次添加相同的键,这将失败。

# Attempt to add a new key. This should succeed.
add job:123 0 300 7
PENDING
STORED
# Verify the key was stored
get job:123
VALUE job:123 0 7
PENDING
END
# Attempt to add the same key again. This should fail.
add job:123 0 300 7
RUNNING
NOT_STORED

使用 spymemcached 等 Java 客户端,您可以轻松执行 add 操作。使用 Maven 等工具管理项目依赖,并正确处理连接和响应至关重要。

确保您的 Maven pom.xml 中包含 spymemcached 依赖:

<dependency>
<groupId>net.spy</groupId>
<artifactId>spymemcached</artifactId>
<version>2.12.3</version>
</dependency>

此代码演示了 add 的核心行为:首次尝试成功,第二次尝试失败。

import net.spy.memcached.MemcachedClient;
import net.spy.memcached.AddrUtil;
import net.spy.memcached.internal.OperationFuture;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
public class MemcachedAddExample {
public static void main(String[] args) {
String serverAddress = "127.0.0.1:11211";
String key = "task_lock:import_users";
String value = "in_progress";
int expiration = 600; // 10 minutes
try (MemcachedClient client = new MemcachedClient(AddrUtil.getAddresses(serverAddress))) {
System.out.println("Connection to Memcached server successful.");
// 清理之前运行留下的键,以确保测试环境干净
client.delete(key).get();
// 1. 首次尝试添加键。这应该会成功。
System.out.println("\nAttempting to add key '" + key + "' for the first time...");
OperationFuture<Boolean> addFuture1 = client.add(key, expiration, value);
if (addFuture1.get()) {
System.out.println("SUCCESS: 'add' operation stored the value.");
} else {
System.out.println("FAILURE: 'add' operation did not store the value.");
}
// 验证值
System.out.println("Value for key '" + key + "' is: " + client.get(key));
// 2. 第二次尝试添加相同的键。这应该会失败。
System.out.println("\nAttempting to add key '" + key + "' again...");
OperationFuture<Boolean> addFuture2 = client.add(key, expiration, "running_again");
if (addFuture2.get()) {
System.out.println("SUCCESS: 'add' operation stored the value. (This should not happen)");
} else {
System.out.println("FAILURE: 'add' operation did not store the value, as expected because the key already exists.");
}
// 验证值未被覆盖
System.out.println("Value for key '" + key + "' is still: " + client.get(key));
} catch (IOException | InterruptedException | ExecutionException e) {
System.err.println("发生错误: " + e.getMessage());
Thread.currentThread().interrupt();
}
}
}

运行该程序后,预期输出为:

Connection to Memcached server successful.
Attempting to add key 'task_lock:import_users' for the first time...
SUCCESS: 'add' operation stored the value.
Value for key 'task_lock:import_users' is: in_progress
Attempting to add key 'task_lock:import_users' again...
FAILURE: 'add' operation did not store the value, as expected because the key already exists.
Value for key 'task_lock:import_users' is still: in_progress