Memcached thread safe lock

It is a quite common problem when cache is expired and multiple PHP processes are trying to update it. There is even a special term for this - "cache slam".
The "cache slam" problem is described very good on php.net

"If a highly shared cache entry stored, for example, in Memcache expires, many clients gets a cache miss. Many client requests can no longer be served from the cache but try to run the underlying query on the database server. Until the cache entry is refreshed, more and more clients contact the database server. In the worst case, a total lost of service is the result."

You can't do $memcached->set('lock_xyz') and then in some other place if ($memcached->get('lock_xyz')) like described in a lot of suggestions all over the internet. Imaging that 10 processes in parallel are trying to check whether lock exists and if not - set it. All of them will end up with setting the lock and do the cache refresh process. In other words this operations are not atomic and thus are not thread safe.
One of the solutions is to update cache from special process, may be cronjob process. But what if you have multiple servers that query to the memcached replica set? What if cache depends on request data?
Despite of the fact that Memcached is an old technology many systems are still using it. Mainly because it is a widespread, fast and simple technology. So when you have no alternative and you need a solution please read further.
Memcached functionality i quite limited and it offers no lock solutions to solve cache slam problem. But there is an alternative approach.
There is a Memcached::add function. It returns TRUE only once, when key was not exist on insertion. Using this behavior it possible to synchronize multiple processes.
Here is an example how to implement this https://github.com/cmyker/MemcachedLock
The idea is that the cache exists always and you just update it after several interval.

Comments

Popular posts from this blog

Memory efficient array permutation in PHP 5.5 using generators

How to dump http request headers with PHP under CGI/FastCGI SAPI

Zend Framework 2 AJAX: return JSON response from controller action. The proper way.