« Swifty 0.05 and the Thundering Herd | Main | Swifty 0.06 »

KeyedMutex - a mutex for web services

Yesterday, I wrote:

Normally, a cache entry has a single lifetime. The problem is that if a cache entry is read frequently and if it takes time to update the entry, a situation known as thundering herd would occur on expiration; i.e. many cache consumers will detect expiration and send same update requests to the backend, causing a performance decline. There are two solutions to the problem:
  • use a proxy that combines identical update requests as a single request
  • initiate an update request prior to expiration, when lifetime being left gets below a certain threshold

Kazuho at Work: Swifty 0.05 and the Thundering Herd

As a complement for the second appoarch I took in Swifty 0.05, I wrote a tiny server that enforces exclusive access to databases. Actually it is not a proxy but works much like a mutex object between processes, but has a slightly different interface to fit into the realities of web services. Here comes the sample code.

# start the server in shell
% keyedmutexd >/dev/null &
# perl source code
use KeyedMutex;

my $km = KeyedMutex->new;
...
until ($value = $cache->get($key)) {
    if ($km->lock($key)) {
        # locked, read from DB
        $value = get_from_db($key);
        $cache->set($key, $value);
        $km->release;
        last;
    }
}

As you can see, it is very simple to use KeyedMutex. When calling the lock function, it either returns immediately telling you that a lock for given key has been acquired, or returns false after some other client has stored the result to the cache.

This kind of approach is not always necessary, but is essential for services that need to issue heavy queries to the backend.

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)