Skip to content

Memcached - Add Data

The add command stores a key-value pair, but only if the key does not already exist on the server. This makes it useful for operations that should only succeed once, like setting an initial value or acquiring a lock.

The basic syntax for the add command is:

add key flags exptime bytes [noreply]
value

The parameters are defined as follows:

  • key: The unique identifier for the data. It’s used to store and retrieve the value.
  • flags: A 32-bit unsigned integer that the server stores with the data. Client libraries can use this for metadata (e.g., to mark data as serialized).
  • exptime: The expiration time in seconds. A value of 0 means the item never expires. For values greater than 30 days (2592000 seconds), it’s treated as a Unix timestamp.
  • bytes: The size of the value in bytes. This must be accurate.
  • [noreply] (optional): An instruction to the server not to send a reply.
  • value: The data to be stored. It must be sent on a new line.
  • STORED: Indicates the data was successfully stored.
  • NOT_STORED: Indicates the key already exists, and therefore the data was not stored.

Here, we first add a new key, job:123, which succeeds. Then, we attempt to add the same key again, which fails.

# 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

Using a Java client like spymemcached, you can perform the add operation easily. It’s crucial to manage project dependencies with a tool like Maven and handle connections and responses correctly.

Ensure the spymemcached dependency is in your Maven pom.xml:

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

This code demonstrates the core behavior of add: success on the first attempt and failure on the second.

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.");
// Clean up the key from previous runs to ensure a clean test
client.delete(key).get();
// 1. First attempt to add the key. This should succeed.
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.");
}
// Verify the value
System.out.println("Value for key '" + key + "' is: " + client.get(key));
// 2. Second attempt to add the same key. This should fail.
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.");
}
// Verify the value was not overwritten
System.out.println("Value for key '" + key + "' is still: " + client.get(key));
} catch (IOException | InterruptedException | ExecutionException e) {
System.err.println("An error occurred: " + e.getMessage());
Thread.currentThread().interrupt();
}
}
}

The expected output from running the program is:

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