Skip to content

Memcached

Memcached is a free, open-source, high-performance, distributed memory object caching system, generic in nature but intended for use in speeding up dynamic web applications by alleviating database load.

Installation

Linux/Ubuntu

# Package manager installation
sudo apt update
sudo apt install memcached

# Verify installation
memcached -h

# Check version
memcached -h | grep memcached

macOS

# Homebrew installation
brew install memcached

# Start service
brew services start memcached

# Verify
memcached -h

Docker

# Pull official image
docker pull memcached:latest

# Run memcached container
docker run -d \
  --name memcached \
  -p 11211:11211 \
  memcached:latest

# With memory limit (512MB)
docker run -d \
  --name memcached \
  -p 11211:11211 \
  memcached:latest -m 512

# Verify
docker exec memcached memcached-tool localhost:11211 stats

Build from Source

# Download and compile
wget http://www.memcached.org/files/memcached-1.6.18.tar.gz
tar xzf memcached-1.6.18.tar.gz
cd memcached-1.6.18

./configure && make && sudo make install

# Verify
memcached -h

Daemon Startup

Basic Startup

# Start with default settings (port 11211, 64MB memory)
memcached

# Start in background daemon mode
memcached -d

# Specify port
memcached -p 11211 -d

# Specify memory limit (in MB)
memcached -m 256 -d

# Specify listen address
memcached -l 127.0.0.1 -p 11211 -d

Advanced Startup Options

# Multiple parameters
memcached -l 0.0.0.0 -p 11211 -m 512 -d -u memcache

# Enable verbose logging
memcached -l 0.0.0.0 -p 11211 -m 512 -v -d

# Set max connections (default: 1024)
memcached -c 4096 -m 512 -d

# Run with specific user
memcached -u memcache -m 512 -d

# Enable TCP/UDP protocols
memcached -p 11211 -U 11211 -m 512 -d

# Disable UDP (use -U 0)
memcached -p 11211 -U 0 -m 512 -d

Systemd Service Setup

# Create systemd service file
sudo tee /etc/systemd/system/memcached.service > /dev/null <<EOF
[Unit]
Description=Memcached
After=network.target

[Service]
Type=simple
User=memcache
ExecStart=/usr/bin/memcached -l 127.0.0.1 -p 11211 -m 512
Restart=always

[Install]
WantedBy=multi-user.target
EOF

# Enable and start service
sudo systemctl enable memcached
sudo systemctl start memcached
sudo systemctl status memcached

Telnet Protocol Interface

Connect to Memcached

# Connect via telnet
telnet localhost 11211

# Connect to remote host
telnet 192.168.1.10 11211

Data Storage Commands

CommandSyntaxDescription
setset <key> <flags> <exptime> <bytes>\r\n<data block>\r\nStore data associated with a key
addadd <key> <flags> <exptime> <bytes>\r\n<data block>\r\nStore data only if key doesn’t exist
replacereplace <key> <flags> <exptime> <bytes>\r\n<data block>\r\nReplace data only if key exists
appendappend <key> <flags> <exptime> <bytes>\r\n<data block>\r\nAppend data to existing value
prependprepend <key> <flags> <exptime> <bytes>\r\n<data block>\r\nPrepend data to existing value

Telnet Examples

# Telnet session - Set key
telnet localhost 11211
set mykey 0 3600 5
hello
STORED

# Get key
get mykey
VALUE mykey 0 5
hello
END

# Add key (fails if exists)
add mykey 0 3600 3
bye
NOT_STORED

# Add new key
add newkey 0 3600 5
world
STORED

# Replace existing key
replace mykey 0 3600 6
goodbye
STORED

# Append to value
append mykey 0 3600 6
 there
STORED

# Prepend to value
prepend mykey 0 3600 5
hello
STORED

Data Retrieval Commands

CommandSyntaxDescription
getget <key> [<key> ...]Retrieve data for one or more keys
getsgets <key> [<key> ...]Retrieve data with CAS token
deletedelete <key>Delete a key
incrincr <key> <value>Increment numeric value
decrdecr <key> <value>Decrement numeric value

Telnet Retrieval Examples

# Get single key
get mykey
VALUE mykey 0 8
goodbye
END

# Get multiple keys
get key1 key2 key3
VALUE key1 0 5
value1
VALUE key2 0 5
value2
END

# Delete key
delete mykey
DELETED

# Delete non-existent key
delete nonexistent
NOT_FOUND

# Increment counter
set counter 0 3600 1
0
STORED

incr counter 1
1

incr counter 5
6

# Decrement counter
decr counter 2
4

Admin Commands

CommandSyntaxDescription
statsstatsDisplay server statistics
stats slabsstats slabsMemory slab statistics
stats itemsstats itemsItem statistics by slab
stats cachedumpstats cachedump <slab> <limit>Dump items in slab
flush_allflush_all [<delay>]Clear all data
quitquitClose connection

Admin Examples

# Get server stats
stats
STAT pid 1234
STAT uptime 3600
STAT time 1640000000
STAT version 1.6.18
STAT libevent 2.1.12-stable
STAT pointer_size 64
STAT rusage_user 0.050000
STAT rusage_system 0.025000
STAT curr_items 42
STAT total_items 150
STAT bytes 2048
STAT curr_connections 5
STAT total_connections 25
STAT connection_structures 8
STAT reserved_fds 20
STAT cmd_get 100
STAT cmd_set 50
STAT cmd_flush 1
STAT cmd_touch 0
STAT get_hits 80
STAT get_misses 20
STAT delete_misses 5
STAT delete_hits 10
STAT incr_misses 0
STAT incr_hits 5
STAT decr_misses 0
STAT decr_hits 3
STAT cas_misses 0
STAT cas_hits 0
STAT cas_badval 0
STAT touch_hits 0
STAT touch_misses 0
STAT auth_cmds 0
STAT auth_errors 0
STAT bytes_read 5120
STAT bytes_written 10240
STAT limit_maxbytes 67108864
STAT accepting_conns 1
STAT listen_disabled_num 0
STAT time_in_listen_disabled_us 0
STAT threads 4
STAT conn_yields 0
STAT hash_power_level 16
STAT hash_bytes 524288
STAT hash_is_expanding 0
STAT malloc_fails 0
STAT server_id 0
END

# Get slab statistics
stats slabs
STAT active_slabs 5
STAT total_malloced 1048576
STAT 1:chunk_size 96
STAT 1:chunks_per_page 10922
STAT 1:total_pages 1
STAT 1:total_chunks 10922
STAT 1:used_chunks 42
STAT 1:free_chunks 10880
...
END

# Dump items from slab 1
stats cachedump 1 100
ITEM key1 [5 b; 1640000000 s]
ITEM key2 [8 b; 1640000100 s]
END

# Flush all data immediately
flush_all
OK

# Flush all data after 10 seconds
flush_all 10
OK

Client Libraries

Python (pymemcache)

#!/usr/bin/env python3
from pymemcache.client.hash import HashClient

# Create client
client = HashClient([
    ('localhost', 11211),
    ('localhost', 11212),
])

# Set value
client.set(b'key1', b'value1', expire=3600)

# Get value
result = client.get(b'key1')
print(result)  # b'value1'

# Add (only if doesn't exist)
client.add(b'key2', b'value2', expire=3600)

# Replace (only if exists)
client.replace(b'key1', b'newvalue', expire=3600)

# Delete
client.delete(b'key1')

# Increment counter
client.incr(b'counter', 1)

# Decrement counter
client.decr(b'counter', 1)

# Get multiple keys
results = client.get_many([b'key1', b'key2', b'key3'])

# Append value
client.append(b'key1', b'_appended')

# Prepend value
client.prepend(b'key1', b'prepended_')

# Get stats
stats = client.stats()

# Flush all
client.flush_all()

# Close connection
client.close()

Java (Spymemcached)

import net.spy.memcached.MemcachedClient;
import java.net.InetSocketAddress;
import java.util.concurrent.Future;

public class MemcachedExample {
    public static void main(String[] args) throws Exception {
        // Create client
        MemcachedClient mcc = new MemcachedClient(
            new InetSocketAddress("localhost", 11211)
        );

        // Set value (expiry in seconds, 3600 = 1 hour)
        mcc.set("key1", 3600, "value1");

        // Get value
        Object obj = mcc.get("key1");
        System.out.println(obj);

        // Asynchronous get
        Future<Object> f = mcc.asyncGet("key1");
        Object o = f.get();
        System.out.println(o);

        // Add (only if doesn't exist)
        mcc.add("key2", 3600, "value2");

        // Replace (only if exists)
        mcc.replace("key1", 3600, "newvalue");

        // Delete
        mcc.delete("key1");

        // Increment counter
        mcc.incr("counter", 1);

        // Decrement counter
        mcc.decr("counter", 1);

        // Flush all
        mcc.flush();

        // Shutdown
        mcc.shutdown();
    }
}

Node.js (node-memcached)

const Memcached = require('memcached');

// Create client
const memcached = new Memcached(['localhost:11211']);

// Set value (expiry in seconds)
memcached.set('key1', 'value1', 3600, (err) => {
  if (err) console.error(err);
  else console.log('Set successful');
});

// Get value
memcached.get('key1', (err, data) => {
  if (err) console.error(err);
  else console.log(data); // 'value1'
});

// Get multiple keys
memcached.getMulti(['key1', 'key2'], (err, data) => {
  if (err) console.error(err);
  else console.log(data);
});

// Add (only if doesn't exist)
memcached.add('key2', 'value2', 3600, (err) => {
  if (err) console.error(err);
});

// Replace (only if exists)
memcached.replace('key1', 'newvalue', 3600, (err) => {
  if (err) console.error(err);
});

// Delete
memcached.del('key1', (err) => {
  if (err) console.error(err);
});

// Increment
memcached.incr('counter', 1, (err, value) => {
  if (err) console.error(err);
  else console.log(value);
});

// Decrement
memcached.decr('counter', 1, (err, value) => {
  if (err) console.error(err);
  else console.log(value);
});

// Flush all
memcached.flush((err) => {
  if (err) console.error(err);
});

// Get stats
memcached.stats((err, stats) => {
  if (err) console.error(err);
  else console.log(stats);
});

// Close connection
memcached.end();

PHP (Memcached)

<?php
// Create client
$memcached = new Memcached();
$memcached->addServer('localhost', 11211);

// Set value (expiry in seconds)
$memcached->set('key1', 'value1', 3600);

// Get value
$value = $memcached->get('key1');
echo $value; // 'value1'

// Add (only if doesn't exist)
$memcached->add('key2', 'value2', 3600);

// Replace (only if exists)
$memcached->replace('key1', 'newvalue', 3600);

// Delete
$memcached->delete('key1');

// Get multiple keys
$values = $memcached->getMulti(['key1', 'key2', 'key3']);

// Increment
$memcached->increment('counter', 1);

// Decrement
$memcached->decrement('counter', 1);

// Flush all
$memcached->flush();

// Get stats
$stats = $memcached->getStats();
print_r($stats);

// Get server list
$servers = $memcached->getServerList();
print_r($servers);

// Get version
$version = $memcached->getVersion();
print_r($version);
?>

Command-Line Tools

memcached-tool Script

# Get server stats
memcached-tool localhost:11211 stats

# Get slab information
memcached-tool localhost:11211 stats slabs

# Get items per slab
memcached-tool localhost:11211 stats items

# Dump keys from slab
memcached-tool localhost:11211 dump 1 1000

# Full inspection
memcached-tool localhost:11211 inspect

nc (netcat) Commands

# Connect and send command
echo "stats" | nc localhost 11211

# Get stats
echo "stats" | nc localhost 11211 | head -20

# Flush all
echo "flush_all" | nc localhost 11211

# Set and get
echo -e "set mykey 0 3600 5\nhello" | nc localhost 11211
echo "get mykey" | nc localhost 11211

Performance Tuning

Startup Parameters

# Optimize for read-heavy workload
memcached -c 4096 -m 2048 -t 8 -d

# Optimize for write-heavy workload
memcached -c 8192 -m 4096 -t 16 -d -o hashpower=16

# Optimize for high concurrency
memcached -c 16384 -m 8192 -t 32 -d

# Parameters explained:
# -c: max concurrent connections (default: 1024)
# -m: maximum memory in MB (default: 64)
# -t: number of worker threads (default: 4)
# -o: misc options (hashpower, etc.)

Memory Management

# Monitor memory usage
echo "stats" | nc localhost 11211 | grep bytes

# Check memory fragmentation
echo "stats slabs" | nc localhost 11211 | grep waste

# Eviction policy details
echo "stats" | nc localhost 11211 | grep eviction

Monitoring

Basic Monitoring

# Real-time monitoring with watch
watch -n 1 'echo "stats" | nc localhost 11211'

# Monitor hit/miss ratio
watch -n 5 'echo "stats" | nc localhost 11211 | grep -E "get_hits|get_misses"'

# Monitor connections
watch -n 2 'echo "stats" | nc localhost 11211 | grep -E "curr_connections|total_connections"'

# Monitor memory
watch -n 2 'echo "stats" | nc localhost 11211 | grep -E "bytes|limit_maxbytes"'

Calculating Statistics

#!/bin/bash
# Calculate hit ratio
STATS=$(echo "stats" | nc localhost 11211)
HITS=$(echo "$STATS" | grep "get_hits" | awk '{print $3}')
MISSES=$(echo "$STATS" | grep "get_misses" | awk '{print $3}')
TOTAL=$((HITS + MISSES))
RATIO=$(echo "scale=2; $HITS * 100 / $TOTAL" | bc)
echo "Hit Ratio: $RATIO%"

Best Practices

  • Set appropriate expiration times for cache items
  • Use consistent key naming conventions
  • Monitor hit/miss ratios to optimize cache effectiveness
  • Configure adequate memory allocation based on expected data size
  • Use connection pooling in client applications
  • Implement proper error handling for cache misses
  • Consider using consistent hashing for distributed caching
  • Regularly monitor server statistics and performance metrics
  • Use dedicated servers for memcached in production
  • Implement redundancy for critical cache data
  • Test cache behavior under load
  • Document cache key schemas and TTL policies