Caching using Memcached

Tuesday, Aug 26, 2025| Tags: perl

DISCLAIMER: Image is generated using ChatGPT.


1. Introduction

2. Installation

3. Benchmark

4. Distributed Server


Introduction



Recently I shared my experience with Redis/Valkey. Continuing my exploration, today I’d like to talk about another very popular choice Memcached.

My first introduction to caching was actually through Memcached.

Memcached is a lightning-fast caching server that stores data in RAM for instant access.

At its core. it works like a simple key-value store.

Memcached is ideal for


- High-traffic websites (reduce DB load)
- Session storage (fast login checks)
- API response caching
- Computationally expensive operations

Key Advantages:


- Blazing Fast: Microsecond response times
- Distributed: Share cache across servers
- Simple: Just get()/set() operations

Installation



On my local setup, running Ubuntu 24.04.01 LTS, this is what I did.


$ sudo apt install memcached libmemcached-tools

Let’s enable and start the memcached service now.


$ sudo systemctl enable memcached
$ sudo systemctl start memcached

Now check the status.


$ systemctl status memcached
memcached.service - memcached daemon
     Loaded: loaded (/usr/lib/systemd/system/memcached.service; enabled; preset: enabled)
     Active: active (running) since Sun 2025-08-17 12:43:12 BST; 1 week 1 day ago
       Docs: man:memcached(1)
   Main PID: 221 (memcached)
      Tasks: 10 (limit: 18986)
     Memory: 2.7M (peak: 4.0M swap: 596.0K swap peak: 608.0K)
        CPU: 21.556s
     CGroup: /system.slice/memcached.service
             └─221 /usr/bin/memcached -m 64 -p 11211 -u memcache -l 127.0.0.1 -l ::1 -P /var/run/memcached/memcached.pid

How about checking the version of memcached running?


$ memcstat --servers=127.0.0.1:11211 | grep version
version: 1.6.24

Finally we need a Perl client to talk to the memcached server.

As always, MetaCPAN is the place for all solutions. I found Cache::Memcached::Fast, a Perl client for memcached, in C language.

Installing the module is as simple as below:


$ cpanm -vS Cache::Memcached::Fast

Let’s check the version installed.


$ perl -MCache::Memcached::Fast -e 'print "$Cache::Memcached::Fast::VERSION\n"'
0.28

Benchmark



Below is a very simple script that simulate the database.

File: memc.pl


#!/usr/bin/env perl

use v5.38;
use Cache::Memcached::Fast;
use Time::HiRes qw(gettimeofday tv_interval);

my $memd = Cache::Memcached::Fast->new({
    servers => ['127.0.0.1:11211']
});

# Simulate Database
my %fake_db = (
    1001 => { name => "Widget", price => 9.99 },
    1002 => { name => "Gadget", price => 8.88 }
);

say "First Fetch (uncached)";
my $start   = [gettimeofday];
my $product = get_product(1001);
say sprintf("Took %.3f seconds\n", tv_interval($start));

say "Second Fetch (cached)";
$start   = [gettimeofday];
$product = get_product(1001);
say sprintf("Took %.3f seconds\n", tv_interval($start));

#
#
# SUBROUTINES

sub get_product($id) {
    my $key = "product:$id";

    my $data;
    if ($data = $memd->get($key)) {
        say "Cache HIT for $id.";
    }
    else {
        say "Cache MISS for $id - querying database.";
        $data = expensive_db_query($id);
        # Cache for 10 secs
        $memd->set($key, $data, 10);
    }

    return $data;
}

sub expensive_db_query($id) {
    sleep 1; # Simulate slow query
    return $fake_db{$id} || undef;
}

Let’s test the setup now.


$ perl memc.pl
First Fetch (uncached)
Cache MISS for 1001 - querying database.
Took 1.003 seconds

Second Fetch (cached)
Cache HIT for 1001.
Took 0.001 seconds

Distributed Server



We can setup Memcached's distributed caching across multiple servers.

Let’s run two more services.


$ memcached -p 11212 -d
$ memcached -p 11213 -d

Let’s check the status of all memcached services.


$ ps aux | grep memcached
memcache     221  0.0  0.0 413152  4352 ?        Ssl  Aug24   0:21 /usr/bin/memcached -m 64 -p 11211 -u memcache -l 127.0.0.1 -l ::1 -P /var/run/memcached/memcached.pid
manwar    687242  0.0  0.0 412128  2480 ?        Ssl  11:27   0:00 memcached -p 11212 -d
manwar    687870  0.0  0.0 412128  2480 ?        Ssl  11:29   0:00 memcached -p 11213 -d

We will now create a very simple client to demonstrate the distributed caching.

File: memc-client.pl


#!/usr/bin/env perl

use v5.38;
use Data::Dumper;
use Digest::SHA qw(sha1);
use Cache::Memcached::Fast;

my @servers = (
    '127.0.0.1:11211',
    '127.0.0.1:11212',
    '127.0.0.1:11213',
);

my $memd = Cache::Memcached::Fast->new({
    servers   => \@servers,
    namespace => 'myapp:',
});

$memd->set('user:1001',  { name => 'Alice' }, 3600);
$memd->set('product:42', { name => 'Widget', price => 9.99 }, 3600);

for my $key ('user:1001', 'product:42') {
    my $value  = $memd->get($key);
    my $server = find_server_for_key('myapp:' . $key);

    say "Fetched key '$key' from server $server";
    say "Value: ", (defined $value ? Dumper($value) : 'undef');
}

#
#
# SUBROUTINES

sub find_server_for($key) {
    my $hash = unpack("N", substr(sha1($key), 0, 4));
    my $server_index = $hash % @servers;
    return $servers[$server_index];
}

Time for action.


$ perl memc-client.pl
Fetched key 'user:1001' from server 127.0.0.1:11213
Value: $VAR1 = {
          'name' => 'Alice'
        };

Fetched key 'product:42' from server 127.0.0.1:11212
Value: $VAR1 = {
          'name' => 'Widget',
          'price' => '9.99'
        };

Did you notice, the two servers in action helping with caching?

This should be a good foundation for anyone to take it further.



Happy Hacking !!!

SO WHAT DO YOU THINK ?

If you have any suggestions or ideas then please do share with us.

Contact with me