Recently at work we needed a way to log successful and failed hits to automatically disable web services for a failover system. There are many ways to implement this but for our application's needs and available tools, only two ideas made sense.

  1. MySQL: store these values on a memory table with delayed insertions.
  2. Memcached: implement Zend_Cache_Backend_Memcached ::increment function

I have seen the mysql solution working great for a couple thousands hits every minute but with our application hitting sometimes 10.000 web service calls every minute we became skeptical really fast. The memcached solution has two major problems: first it's memcaheD you don't know if the value you put in cache will actually make it back and secondly the Zend Memcached adapter needs a patch to implement the increment and a custom method to retrieve the counters. The reason increment has never been officially implemented before in ZF1 is because Zend stores values to cache in a custom way alongside the cache date and lifetime.

$result = @$this->_memcache->set($id, array($data, time(), $lifetime), $flag, $lifetime);

Memcached::increment needs the values to be numerical. I can only speculate why ZF1 dev team decided to save all values as array but anyway. I added the following two methods in Zend\Cache\Backend\Memcached.php

 * Memcached::increment
 * @param string $id cache id
 * @param numerical $offset to increase counter
 * @param numerical $initial value to set counter
 * @param int $extraLifetime
 * @return numerical new items value on success or FALSE on failure.
public function increment($id, $offset = 1, $initial = 0, $specificLifetime = false)
	$result = $this->_memcache->increment($id, $offset);
	if (!$result) {
			$lifetime = $this->getLifetime($specificLifetime);
			$this->_memcache->add($id, $initial, false, $lifetime);
			$result = $this->_memcache->increment($id, $offset);
	return $result;

 * Custom get to retrieve incremental items
 * @param string $id cache id
 * @return numerical|false cached item
public function getCounterKey($id)
	$tmp = $this->_memcache->get($id);
	return is_numeric($tmp) ? $tmp : false;

The getCounterKey  is pretty straight forward, we wanted to bypass the default load method that tries to access the data from a custom array. The increment is a little more complex because we wanted a thread safe solution. The memcached::increment and memcached::add used like this, is thread safe.

Unfortunately you can't use these methods directly from the Zend_Cache_Core instance, you need a new patch for that to modify the Core class and all the adapters to add this new capability. It's doable but we were satisfied with just using the following snippet to access the Memcached adapter and the two new methods directly.

$cache = Zend_Registry::get('cache')->getBackend();
$cache->increment($key, 1, 0, 0);

The solution works like a charm when memcached is working properly but i would love someday to also test the MySQL idea. I would love to hear what solution other people used in similar problems.


  1. Chris #2   Chris | Feb 3, 2016 at 20:56

    Thank you for your comment, Freeman!

    This is a small tutorial on how to accomplice atomic counters in zf1, of course you shouldn't modify a dependency, I didn't want to get into how you can set up your own cache adapter and how you can register it as your default cache driver.

  2. Freeman #1   Freeman | May 26, 2015 at 12:43

    Why would you modify an application dependency?! Is your deployment plan to manually change this file every time Zend Framework upgrades? Why wouldn't you just create a wrapper class for Zend's memcached service, or create your own class implementing memcached? You could probably even fork the original source, then create a separate module based on the original source.

Leave a Comment
It will not be published.