What is Memcached?

David Morales
The Startup
Published in
4 min readJan 28, 2021

Memcached is a free and open-source high-performance memory caching system. It’s typically used to cache database data, API calls or page rendering chunks in RAM to increase the application performance.

It can store data as little as a number, or as big as a finished HTML page.

The system is designed to be accessed through TCP so it can work in a separate server, and can also be distributed among several servers, summing up a big hash table to store data.

When running out of space, the older data is overwritten. So it must be treated as a transitory (not-persisted) cache, meaning that your data may not still be there.

Installation

If you’re using macOS, it’s very easy to install Memcached using Homebrew:

$ brew install memcached

Then you can start it using this command:

$ /usr/local/opt/memcached/bin/memcached

If you are using Linux, you can use your distribution’s package manager to install it easily.

Connecting

The default port is 11211. Let’s try to connect using Telnet:

$ telnet localhost 11211
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.

Great! The server is up. Now quit Telnet (using the quit command) and let’s install a Ruby gem to interact with the server more comfortably:

gem install dalli

Run a Ruby console (irb) and connect to the server using the default port:

require 'dalli'
cache = Dalli::Client.new('localhost')
=> #<Dalli::Client:0x007f999d867e80 @servers=["localhost"], @options={}, @ring=nil>

Basic storage

Let’s start playing with Memcached storing a string and then getting it:

cache.set 'greet', 'hello'
cache.get 'greet'
=> "hello"

As you see, set is used to set a value to a key, which will be overwritten if it already exists. get is used to get the key value.

Data can also be limited by some time in seconds:

cache.set 'greet', 'hello', 5
cache.get 'greet'
=> "hello"
sleep 5
cache.get 'greet'
=> nil

Multiple values can be get in a unique query using get_multi, resulting in a hash:

cache.set 'greet1', 'hello'
cache.set 'greet2', 'good morning'
cache.get_multi 'greet1', 'greet2'
=> {"greet1"=>"hello", "greet2"=>"good morning"}

Let’s free some memory by deleting those greetings:

cache.delete 'greet1'
cache.delete 'greet2'
cache.get_multi 'greet1', 'greet2'
=> {}

If you want to delete all keys, the flush operation is what you need:

cache.flush
=> [true]

Adding data

The set command overwrites the value if the key already exists:

cache.set 'greet', 'hello'
cache.get 'greet'
=> "hello"
cache.set 'greet', 'good morning'
cache.get 'greet'
=> "good morning"

To avoid this, the add command can be used instead, which will create the value if the key doesn’t exist:

# It doesn't overwrite an existing key (defined in the previous code block)
cache.add 'greet', 'good evening'
cache.get 'greet'
=> "good morning"
# It creates the value for new keys
cache.add 'greet2', 'good evening'
=> "good evening"

Replacing data

replace is used to replace data for an existing key:

cache.replace 'greet', 'hi there!'
cache.get 'greet'
=> "hi there!"

But it will do nothing if the key doesn’t exist:

cache.replace 'non existing greet', 'hi there!'
=> nil

Appending and prepending data

In order to append or prepend data, Dalli requires it to be previously set as raw:

cache.set 'greet', 'hello', 0, raw: true

Now we can append:

cache.append 'greet', '!'
cache.get 'greet'
=> "hello!"

And prepend:

cache.prepend 'greet', 'hey! '
cache.get 'greet'
=> "hey! hello!"

Increment and decrement data

Another useful case is to have a counter, so it can be incremented or decremented.

cache.set 'counter', 1, 0, raw: true
cache.incr 'counter'
=> 2
cache.incr 'counter', 2
=> 4
cache.decr 'counter'
=> 3
cache.decr 'counter', 3
=> 0

Check and set

Imagine having a value that can be updated by any concurrent client (trying to update it at the same time). Wouldn’t that be a problem? That’s a race condition that can be controlled using the cas operation, that checks if the value has been changed by other client before updating it.

It works like a set operation, but it requires a block:

cache.set 'config', 'foo'
cache.cas('config') { 'bar' }
cache.get 'config'
=> "bar"

Therefore, this is an atomic operation.

Conclusion

We have seen what’s Memcached and how it can be used directly using the Dalli gem. It may seem simple, but it can help a big web application to work faster like many important companies are doing, such as YouTube, Reddit, Facebook, Twitter, and Wikipedia.

Sometimes it’s essential to work with Memcached directly, for instance when developing a service with special needs. There are other times where the framework (Ruby on Rails for example) can store its cache out of the box in Memcached using a gem like Dalli.

--

--

David Morales
The Startup

Exploring the intersections of productivity, economy, business, marketing, and software engineering for growth and success. 💻💼📈🚀