Snippets

Create an account or login to be able to add, comment and rate snippets.

Navigation

sfMemcached with multiple servers/buckets

This is a version of sfMemcached modified to allow multiple servers to be used. Servers are grouped in buckets for organization.

A bucket must be initialized before it is used.

Example:

sfAdvMemcachedCache::createInstance('function', array (
  'lifetime' => 60
  'servers' => 
  array (
    array (
      'host' => '72.29.86.195',
      'port' => 11211,
      'persistent' => true,
      'weight' => 2,
      'timeout' => 1,
      'retry_interval' => 1,
      'status' => 1,
    )
  )
));

Then the bucket can be used through a call to getInstnace(bucketName)

Ex:

sfAdvMemcacheCache::getInstance('function')->set('helloKey', 'world_data');

For ease of use, multiple buckets and servers can be defined and auto-intialized through a YAML file called memcached.yml that will sit in the /config folder of your application.

Example configuration:

default:
  servers:
    default:
      host: localhost
      port: 11211
      timeout: 1
      weight: 1
      retry_interval: 1
      status: 1 
    host1:
      host: 72.29.86.195
      port: 11211
      weight: 2
    host2:
      host: 66.7.208.83
      port: 11211
      weight: 2
    host3:
      host: 66.7.208.87
      port: 11211
  buckets:
    default:
      lifetime: 60
      servers: host1
    session:
      servers: [host1, host2]
    object:
      servers: [host1]
    function:
      servers: host2
    view:

In order to use YAML configuration a file named "myMemcacheConfigHandler.class.php" must be created in the /lib folder of your application.

<?php
 class myMemcacheConfigHandler extends sfYamlConfigHandler
{
  /**
   * Executes this configuration handler.
   *
   * @param array An array of absolute filesystem path to a configuration file
   *
   * @return string Data to be written to a cache file
   *
   * @throws <b>sfParseException</b> If a requested configuration file is improperly formatted
   */
  public function execute($configFiles)
  {
    // parse the yaml
    $myConfig = $this->parseYamls($configFiles);
 
    $myConfig = sfToolkit::arrayDeepMerge(
      isset($myConfig['default']) && is_array($myConfig['default']) ? $myConfig['default'] : array(),
      isset($myConfig['all']) && is_array($myConfig['all']) ? $myConfig['all'] : array(),
      isset($myConfig[sfConfig::get('sf_environment')]) && is_array($myConfig[sfConfig::get('sf_environment')]) ? $myConfig[sfConfig::get('sf_environment')] : array()
    );
 
    // Set Up Servers
    $defaultServerConfig = array('host' => 'localhost',
                            'port' => 11211,
                            'persistent' => true,
                            'weight' => 1,
                            'timeout' => 1,
                            'retry_interval' => 15,
                            'status' => true,                                        
                            );                           
 
    if(!isset($myConfig['servers']) || !is_array($myConfig['servers']))
    {
        $myConfig['servers'] = array( 'default' => $defaultServerConfig );    
    }
 
    $myConfig['servers']['default'] = array_merge( $defaultServerConfig, isset($myConfig['servers']['default']) ? $myConfig['servers']['default'] : array() );  
 
    foreach($myConfig['servers'] as $serverName => &$server)
    {
        $server = array_merge($myConfig['servers']['default'], $server);
    }
 
    // Set Up Buckets
    if(!isset($myConfig['buckets']) || !is_array($myConfig['buckets']))
        throw new sfParseException(sprintf('Configuration file "%s" does not specify any cache buckets.', $configFiles[0]));        
 
    $inits = array();
    foreach($myConfig['buckets'] as $bucketName => &$bucket)
    {
        if(!isset($bucket['servers']))
        {
            $bucket['servers'] = 'default';
        }
 
        if(!is_array($bucket['servers']))
        {
            $bucket['servers'] = array( $bucket['servers'] );            
        }
 
 
        foreach($bucket['servers'] as $serverName => &$server)
        {
            if(!isset($myConfig['servers'][$server]))
                throw new sfParseException(sprintf('Configuration file "%s" requires server configuration \'%s\' for bucket \'%s\', but server configuration does not exist.', $configFiles[0], $server, $bucketName ));
 
            $server = $myConfig['servers'][$server];        
        }
 
        $inits[] = sprintf("sfAdvMemcachedCache::createInstance('%s', %s);", $bucketName, var_export($bucket, true) );
    }
 
    // Compile Return Value    
    return sprintf("<?php\n  %s", implode("\n", $inits));
  }
}

Once that code is in place, modify your config.php in your applications /config directory.

Add the following code:

include(sfConfigCache::getInstance()->checkConfig(sfConfig::get('sf_app_config_dir_name').'/memcache.yml'));

Lastly create a file called sfAdvMemcachedCache.php in your /lib folder. All of the above is optional, and is only needed if you wanted to use YAML for auto-initialization.

... it seems there was too much code in here for a snippet. Trying to save the snippet would cause a silent failure. You can download the code here:

http://lu.scio.us/files/sfAdvMemcachedCache.php.text

Using this code as a base, it is trivial to create a Memcached class to handle session data, cache view content, or cache propel objects automatically.

The first two classes I have already written, and may be released if I repackage this code into a plugin.

by Kum Sackey on 2007-07-28, tagged memcached  object 

Comments on this snippet

gravatar icon
#1 Damjan Malis on 2007-08-07 at 04:56

Tnx for this great snippet. It's realy usefull.

But could you please publish your memcached session storage implementation too? Ty in advance.

You need to create an account or log in to post a comment or rate this snippet.