How to use multiple memcached servers with Zend Framework

11/14/2013

Memcached is a powerful tool for caching temporary data in memory for faster read/write. And it has been very popular with web application development for scaling purpose and performance tuning. Today, we would like to share our experience on how to use memcached for Zend Framework 1, especially on using multiple memcached servers.

 

Zend Framework comes nicely with its own module called Zend Cache, which allows you to cache a variety of temporary data for performance tuning, ranging from caching expensive database calls to cache page output for faster page rendering. You can configure Zend Cache to store cache data in a variety of storage medium such as local filesystem, APC (Alternative PHP Cache), sqlite, Xcache or memcached.

 

Before continue, let’s me introduce a little bit about the theory of Zend Cache and how it works. In a typical web application, you will have different points in your application that need caching for performance increase. For example, you may have to cache for auto suggest lookup or for expensive web service call to remote servers. So you will have two or more types of cache data to store and each type may have different requirements such as cache lifetime and medium for cache storage. Zend Cache was built with consideration for those scenarios. In Zend Cache, each type of cache data is represented as an instance or simply a PHP object. These cache objects are created by telling Zend Cache factory how to build with a set of information. And such information is divided into front end and backend. Frontend is basically for telling how long the cache should be alive, whether to automatically serialize the data or not and etc. Backend is about telling what storage medium will be used and other storage medium specific options. You can read more about it on Zend manual link provided at the end of this blog post.

 

So let’s get to the point and show you how to configure one or more memcached servers for your Zend application. Assume we are going to cache for two types of data 1) for auto-suggest cache 2) for expensive Web services call. Then, you will configure it in your application.ini file as follow:

 

With a single memcached server:

 

resources.cachemanager.auto_suggest.frontend.name = Core
resources.cachemanager.auto_suggest.frontend.customFrontendNaming = false
; every 24 hrs the cache will be refreshed
resources.cachemanager.auto_suggest.frontend.options.lifetime = 86400 resources.cachemanager.auto_suggest.frontend.options.automatic_serialization = true
resources.cachemanager.auto_suggest.backend.name = Memcached
resources.cachemanager.auto_suggest.backend.options.compression = true
resources.cachemanager.auto_suggest.frontendBackendAutoload = false

resources.cachemanager.auto_suggest.backend.name = Memcached
resources.cachemanager.web_service.backend.options.servers.host = 127.0.0.1
resources.cachemanager.auto_suggest.backend.options.compression = true
resources.cachemanager.auto_suggest.frontendBackendAutoload = false


resources.cachemanager.web_service.frontend.name = Core
resources.cachemanager.web_service.frontend.customFrontendNaming = false
; every 1 hr the cache will be refreshed
resources.cachemanager.web_service.frontend.options.lifetime = 3600
resources.cachemanager.web_service.frontend.options.automatic_serialization = true
resources.cachemanager.web_service.backend.name = Memcached
resources.cachemanager.web_service.backend.options.servers.host = 127.0.0.1
resources.cachemanager.web_service.backend.options.compression = true
resources.cachemanager.web_service.frontendBackendAutoload = false

resources.cachemanager.web_service.backend.name = Memcached
resources.cachemanager.web_service.backend.options.compression = true
resources.cachemanager.web_service.frontendBackendAutoload = false
  

 

How to use it in your code?

For example, in your controller you can use it as follow:

     $manager = $this->getFrontController()
                    ->getParam('bootstrap')
                    ->getPluginResource('cachemanager')
                    ->getCacheManager();
            //get the cache object for auto suggest data type
            $autosuggestCache = $manager->getCache('auto_suggest');
            //load from cache
            if(($data = $autosuggestCache->load('some key')) === false) {
                //cache miss
                //needs to load from actual data source
                $data = expensiveLookup('some key'); // just a dummy hypothetical function to get data from original source
                $autosuggestCache->save('some_key', $data);
            }
   

 

How to use multiple memcached servers?

Configuration for multiple memcached servers is also very similar to the previous configuration where you did it for a single memcached server. The only difference is in the backend option for “servers”. Following is an example of using three memcached servers for example above of auto suggest.

 
resources.cachemanager.auto_suggest.backend.options.servers.first.host = 127.0.0.1
resources.cachemanager.auto_suggest.backend.options.servers.second.host = 127.0.0.2
resources.cachemanager.auto_suggest.backend.options.servers.third.host = 127.0.0.3

 

one BIG caution

When you use multiple memcached servers, please do not think of this as redundancy storage for caching data. Often people think using multiple servers will allow them to store copies of cache data across multiple memcached servers. That is not the case. Instead, multiple memcached servers is for more of like load balancing strategy known as sharding i.e cache item A may be stored in first server and B will be in second and so on, depending on how you configure and how much memory space still available on each memcached server.

 

Reference:

Zend Manual on Caching -http://framework.zend.com/manual/1.12/en/zend.cache.introduction.html