In-Memory Database

Memcached

Overview

Memcached is a high-performance distributed memory object caching system. Specialized for simple key-value operations, it is widely used to accelerate web applications. Through its lightweight, efficient design and multi-threaded architecture, Memcached provides sub-millisecond response times for cache data access, making it an ideal solution for reducing database load and improving application performance.

Details

Memcached was developed at LiveJournal in 2003 as an open-source cache system designed to reduce access to databases and file systems, thereby improving web application performance. It manages data in key-value pairs using an efficient data structure that combines hash tables with fixed-size buckets containing linked lists. While there is a 1MB size limit per value, this simple model enables high performance.

As of 2025, Memcached provides built-in proxy functionality and advanced routing capabilities, offering enterprise-grade features such as management of multiple backend servers and failover functionality. The multi-threaded architecture efficiently utilizes multiple CPU cores, significantly enhancing scalability by increasing the system's ability to process concurrent operations.

Pros and Cons

Pros

  • Ultra-High Speed Access: Sub-millisecond response times for data retrieval
  • Simple Design: Architecture specialized for key-value operations only
  • High Scalability: Multi-threaded design efficiently utilizes multiple CPU cores
  • Lightweight Design: Low memory usage and high efficiency
  • Broad Client Support: Support for multiple languages including PHP, Python, Java
  • Mature Ecosystem: Over 20 years of proven track record and stability
  • Flexible Deployment: Supports standalone, distributed, and cloud environments

Cons

  • No Persistence: Memory-only storage results in data loss on server restart
  • Simple Functionality: Only basic key-value operations, no complex data manipulation
  • Size Limitations: 1MB size limit per value
  • No Clustering: No native high availability features
  • Limited Security: No built-in authentication, encryption, or security features

Reference Pages

Code Examples

Server Startup and Basic Configuration

# Basic server startup
memcached -p 11211 -m 64 -d

# Multiple port instance startup
memcached -p 11212 -m 128 -d
memcached -p 11213 -m 128 -d

# Detailed configuration startup
memcached -l 127.0.0.1 -p 11211 -m 64 -c 1024 -t 4 -d

# Status check
echo "stats" | nc localhost 11211

PHP Client Usage

<?php
// Initialize Memcache client
$memcache = new Memcache();

// Add servers
$MEMCACHE_SERVERS = [
    "10.1.1.1", // web1
    "10.1.1.2", // web2
    "10.1.1.3", // web3
];

foreach($MEMCACHE_SERVERS as $server) {
    $memcache->addServer($server, 11211);
}

// Store and retrieve data
$key = "user:123:profile";
$data = [
    "name" => "John Doe",
    "email" => "[email protected]",
    "last_login" => time()
];

// Store in cache (TTL: 3600 seconds)
$memcache->set($key, $data, 0, 3600);

// Retrieve from cache
$cached_data = $memcache->get($key);
if ($cached_data !== false) {
    echo "Cache hit: " . print_r($cached_data, true);
} else {
    echo "Cache miss";
}

// Delete cache
$memcache->delete($key);
?>

Python Client Usage

import memcache
import json
from datetime import datetime, timedelta

# Initialize Memcached client
mc = memcache.Client([
    '127.0.0.1:11211',
    '127.0.0.1:11212',
    '127.0.0.1:11213'
], debug=0)

# Cache decorator
def cache_result(expiry_time=3600):
    def decorator(func):
        def wrapper(*args, **kwargs):
            # Generate key
            cache_key = f"{func.__name__}:{hash(str(args) + str(kwargs))}"
            
            # Try to get from cache
            result = mc.get(cache_key)
            if result is not None:
                return json.loads(result)
            
            # On cache miss, execute function
            result = func(*args, **kwargs)
            
            # Store result in cache
            mc.set(cache_key, json.dumps(result), time=expiry_time)
            return result
        return wrapper
    return decorator

# Usage example
@cache_result(expiry_time=1800)
def expensive_database_query(user_id):
    # Simulate heavy database query
    import time
    time.sleep(0.5)  # Database access simulation
    return {
        "user_id": user_id,
        "name": f"User {user_id}",
        "timestamp": datetime.now().isoformat()
    }

# Verify cache effectiveness
print(expensive_database_query(123))  # First call is slow
print(expensive_database_query(123))  # Second call is fast

Node.js Client Usage

const memcached = require('memcached');

// Initialize Memcached client
const mc = new memcached([
    '127.0.0.1:11211',
    '127.0.0.1:11212',
    '127.0.0.1:11213'
], {
    maxKeySize: 250,
    maxExpiration: 2592000,
    maxValue: 1048576,
    poolSize: 10,
    algorithm: 'md5',
    reconnect: 18000,
    timeout: 5000,
    retries: 5,
    failures: 5,
    retry: 30000,
    remove: true,
    failOverServers: ['127.0.0.1:11214']
});

// Promise wrapper functions
const memcachedGet = (key) => {
    return new Promise((resolve, reject) => {
        mc.get(key, (err, data) => {
            if (err) reject(err);
            else resolve(data);
        });
    });
};

const memcachedSet = (key, value, ttl) => {
    return new Promise((resolve, reject) => {
        mc.set(key, value, ttl, (err) => {
            if (err) reject(err);
            else resolve(true);
        });
    });
};

// Cache middleware function
async function cacheMiddleware(req, res, next) {
    const cacheKey = `api:${req.originalUrl || req.url}`;
    
    try {
        const cachedResponse = await memcachedGet(cacheKey);
        if (cachedResponse) {
            return res.json(JSON.parse(cachedResponse));
        }
        
        // Wrap original res.json to cache response
        const originalJson = res.json;
        res.json = function(data) {
            memcachedSet(cacheKey, JSON.stringify(data), 300); // 5-minute cache
            originalJson.call(this, data);
        };
        
        next();
    } catch (err) {
        console.error('Memcached error:', err);
        next();
    }
}

// Usage in Express app
app.get('/api/users/:id', cacheMiddleware, async (req, res) => {
    const user = await getUserFromDatabase(req.params.id);
    res.json(user);
});

Proxy Configuration (Lua Script)

-- memcached-proxy.lua
-- Proxy configuration file

-- Backend server pool definition
pools {
    main_pool = {
        backend_options = { connecttimeout = 5 },
        backends = {
            "192.168.1.10:11211",
            "192.168.1.11:11211",
            "192.168.1.12:11211"
        }
    },
    
    hot_keys_pool = {
        backends = {
            { host = "192.168.1.20", port = 11211, connecttimeout = 3 },
            { host = "192.168.1.21", port = 11211, connecttimeout = 3 },
            { host = "192.168.1.22", port = 11211, connecttimeout = 3 }
        }
    }
}

-- Routing configuration
routes {
    map = {
        -- Keys starting with "hot/" go to special pool
        hot = route_allfastest {
            children = "hot_keys_pool"
        }
    },
    
    -- Default routing
    default = route_direct {
        child = "main_pool"
    }
}

-- Global settings
settings {
    backend_connect_timeout = 3,
    active_req_limit = 5
}

Monitoring and Performance Tuning

# Get statistics
echo "stats" | nc localhost 11211
echo "stats slabs" | nc localhost 11211
echo "stats items" | nc localhost 11211

# Performance test script
#!/bin/bash
# Performance test using mc_conn_tester.pl
./mc_conn_tester.pl -s memcached-host -p 11211 -c 1000 --timeout 1

# Network tuning example
# /etc/sysctl.conf
net.ipv4.ip_local_port_range = 16384 65534
net.ipv4.tcp_max_tw_buckets = 262144
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_tw_reuse = 1

Command Line Tools

# Manual testing with telnet
telnet localhost 11211
# Enter the following:
set test_key 0 3600 5
hello
get test_key
delete test_key
quit

# Batch testing with script
echo -e "set test 0 300 5\r\nhello\r\nget test\r\nquit\r\n" | nc localhost 11211

# Memory usage monitoring
watch -n 1 'echo "stats" | nc localhost 11211 | grep bytes'