Here at CakeMail we use Memcached to cache numerous amounts of data required by our application. Often we need to flush data from Memcached before its expiration. This is quite easy when dealing with one key, but when you want to flush all keys starting with a given prefix it gets a bit trickier.

Since Memcached does not support wildcard deleting, we decided to implement namespacing in our caching object, which allows us to do just that. Although this is not a new idea, I still felt it was worth sharing with you guys.

Problem

Suppose your application is multilingual and strings are stored in a database. You might want to cache these strings as they do not change very often.

Strings could be stored in Memcached with the given key: string_<LOCALE>_<STRING_NAME> .

Updating a language means waiting for the keys to expire or deleting them. The latter is tricky since you would have to loop through each string and delete them one by one.

Solution

The idea behind namespacing is to have a single key that you can invalidate to cause all of its children to no longer be used.

For instance, here is how we are caching our localized strings:

ns_string_en_US => 1 string_en_US_1_welcome => Welcome string_en_US_1_logout => Logout

All strings are stored using the following format: string_<LOCALE>_<NS>_<STRING_NAME> .

Whenever we want to flush an entire language all we need to do is increment the ns_string_<LOCALE> key. Doing so causes the namespace to change to 2 , thus all strings are loaded from keys string_en_US_2_<STRING_NAME> .

Update: As flyingfirefox pointed out, the above problem can be solved without the use of namespacing, but I wanted to keep the examples simple.

To make this task easier, we built a simple Cache object that is initialized using dependency injection. At this time it only supports a single Memcached instance, but it would be quite trivial to have it support multiple.

Sample Usage

The Code

Cache.php

Cache_Service.php

Cache_Memcache.php

Downsides

Although this technique works for some situations, it may not work for all.

Flushing a namespace causes a waste of memory usage within Memcached until the old namespace expires, since you aren’t actually deleting the old keys. This isn’t a huge problem though since Memcached will remove the least recently used keys if it is ever full.

Getting a namespaced value requires that you first get the namespace value then the value of the key you want.

What are your thoughts on Memcached namespacing?

Psst.. We are hiring! 😉

By Christian Joudrey, CakeMail’s Lead Programmer. You can follow Christian on twitter @cjoudrey.