MemCachier

This add-on is operated by MemCachier

Reliable and powerful memcache-as-a-service

MemCachier

Last Updated: 14 April 2014

Table of Contents

MemCachier is an implementation of the Memcache in-memory key/value store used for caching data. It is a key technology in modern web applications for scaling and reducing server loads. The MemCachier add-on manages and scales clusters of memcache servers so you can focus on your app. Tell us how much memory you need and get started for free instantly. Add capacity later as you need it.

Follow our blog or twitter (@memcachier), for status and product announcements.

Getting started

Start by installing the add-on:

$ heroku addons:add memcachier:dev

You can start with more memory if you know you’ll need it:

$ heroku addons:add memcachier:100
$ heroku addons:add memcachier:500
 ... etc ...

Once the add-on has been added you’ll notice three new variables in heroku config:

$ heroku config
...
MEMCACHIER_SERVERS    => mcX.ec2.memcachier.com
MEMCACHIER_USERNAME   => bobslob
MEMCACHIER_PASSWORD   => l0nGr4ndoMstr1Ngo5strang3CHaR4cteRS
...

Next, setup your app to start using the cache. We have documentation for the following languages and frameworks:

Your credentials may take up to three (3) minutes to be synced to our servers. You may see authentication errors if you start using the cache immediately.

Ruby

We’ve built a small Ruby example using Sinatra here: MemCachier Sinatra sample app.

Start by adding the memcachier and dalli gems to your Gemfile.

gem 'memcachier'
gem 'dalli'

Then bundle install:

$ bundle install

Dalli is a Ruby memcache client, and the memcachier gem modifies the environment (ENV) such that the environment variables set by MemCachier will work with Dalli. Once these gems are installed you can start writing code. The following is a basic example showing get and set.

require 'dalli'
require 'memcachier'
cache = Dalli::Client.new
cache.set("foo", "bar")
puts cache.get("foo")

Without the memcachier gem, you’ll need to pass the proper credentials to Dalli:

cache = Dalli::Client.new(ENV["MEMCACHIER_SERVERS"].split(","),
                    {:username => ENV["MEMCACHIER_USERNAME"],
                     :password => ENV["MEMCACHIER_PASSWORD"],
                     :failover => true,
                     :socket_timeout => 1.5,
                     :socket_failure_delay => 0.2
                    })

Testing (Ruby)

The easiest way to test that your setup is working is through the heroku console:

$ heroku run console --app <app>
>> require 'dalli'
>> require 'memcachier'
>> dc = Dalli::Client.new
>> dc.set('memcachier', 'rocks')
=> true

And then fetch the value back:

>> dc.get('memcachier')
=> "rocks"

You can also get an insight into your cache usage (number of keys stored and bytes) with the stats command:

>> dc.stats
=> {"memcachier.example.net:11211" => {"cur_items" => "49982", "bytes" => "89982234"} }

Rails 3 and 4

We’ve built a small Rails example here: MemCachier Rails sample app. We also have a tutorial on using MemCachier with Rails here.

Below explains how to setup and install MemCachier with Rails. Refer to the Rails caching guide for information on how to use MemCachier with Rails. Rails supports automatic whole site caching, per-view caching and fragment caching.

Start by adding the memcachier and dalli gems to your Gemfile.

gem 'memcachier'
gem 'dalli'

Then run bundle install:

$ bundle install

Dalli is a Ruby memcache client, and the memcachier gem modifies the environment (ENV) such that the environment variables set by MemCachier will work with Dalli. Once these gems are installed you’ll want to configure the Rails cache_store appropriately. Modify config/environments/production.rb with the following:

config.cache_store = :dalli_store

In your development environment, Rails.cache defaults to a simple in-memory store and so it doesn’t require a running memcached.

From here you can use the following code examples to use the cache in your Rails app:

Rails.cache.write("foo", "bar")
puts Rails.cache.read("foo")

Without the memcachier gem, you’ll need to pass the proper credentials to Dalli in config/environments/production.rb:

config.cache_store = :dalli_store,
                    (ENV["MEMCACHIER_SERVERS"] || "").split(","),
                    {:username => ENV["MEMCACHIER_USERNAME"],
                     :password => ENV["MEMCACHIER_PASSWORD"],
                     :failover => true,
                     :socket_timeout => 1.5,
                     :socket_failure_delay => 0.2
                    }

It is possible you will run into a configuration problem if you are using Rails 3.1 and the Heroku Cedar platform. Information on how to fix that issue can be found at this Stackoverflow answer

Testing (Rails)

To test locally you can simply use the rails console:

rails console
>> Rails.cache.write('memcachier', 'rocks')
=> true
>> Rails.cache.read('memcachier')
=> "rocks"

To test against MemCachier itself, please refer to the Ruby testing instructions.

Rails 2

Start by adding the memcachier and dalli gems to your Gemfile. You will need to use dalli v1.0.5 as later versions of Dalli don’t support Rails 2.

gem 'memcachier'
gem 'dalli', '~>1.0.5'

Then run bundle install:

$ bundle install

Dalli is a Ruby memcache client, and the memcachier gem modifies the environment (ENV) such that the environment variables set by MemCachier will work with Dalli. Once these gems are installed you’ll want to configure the Rails cache_store appropriately. Modify config/environments/production.rb with the following:

require 'active_support/cache/dalli_store23'
config.cache_store = :dalli_store

In your development environment, Rails.cache defaults to a simple in-memory store and so it doesn’t require a running memcached.

In config/environment.rb:

config.gem 'dalli'

From here you can use the following code examples to use the cache in your Rails app:

Rails.cache.write("foo", "bar")
puts Rails.cache.read("foo")

Without the memcachier gem, you’ll need to pass the proper credentials to Dalli in config/environments/production.rb:

config.cache_store = :dalli_store,
                    (ENV["MEMCACHIER_SERVERS"] || "").split(","),
                    {:username => ENV["MEMCACHIER_USERNAME"],
                     :password => ENV["MEMCACHIER_PASSWORD"],
                     :failover => true,
                     :socket_timeout => 1.5,
                     :socket_failure_delay => 0.2
                    }

Testing (Rails)

To test locally you can simply use the rails console:

rails console
>> Rails.cache.write('memcachier', 'rocks')
=> true
>> Rails.cache.read('memcachier')
=> "rocks"

To test against MemCachier itself, please refer to the Ruby testing instructions.

Rails Rack::Cache

Rails can use a middle-ware component of the Rack web server architecture called Rack::Cache. This provides caching of static assets in Rails and is a simple alternative to use a full CDN.

Please see this article for information.

Django

We’ve built a small Django example here: MemCachier Django sample app. We also have a tutorial on using Django and MemCachier together here.

Below explains how to setup and install MemCachier with Django. Please refer to the Django caching guide for information on how to effectively use MemCachier. Django supports whole site caching, per-view caching and fragement caching.

MemCachier has been tested with the pylibmc memcache client, but the default client doesn’t support SASL authentication. Run the following commands on your local machine to install the necessary pips:

$ sudo port install libmemcached
$ LIBMEMCACHED=/opt/local pip install pylibmc
$ pip install django-pylibmc-sasl

Be sure to update your requirements.txt file with these new requirements (note that your versions may differ than what’s below):

pylibmc==1.2.2
django-pylibmc-sasl==0.2.4

Next, configure your settings.py file the following way:

os.environ['MEMCACHE_SERVERS'] = os.environ.get('MEMCACHIER_SERVERS', '').replace(',', ';')
os.environ['MEMCACHE_USERNAME'] = os.environ.get('MEMCACHIER_USERNAME', '')
os.environ['MEMCACHE_PASSWORD'] = os.environ.get('MEMCACHIER_PASSWORD', '')

CACHES = {
  'default': {
    'BACKEND': 'django_pylibmc.memcached.PyLibMCCache',
    'TIMEOUT': 1000,
    'BINARY': True,
    'OPTIONS': {
        'tcp_nodelay': True,
        'remove_failed': 4
    }
  }
}

From here you can start writing cache code in your Django app:

from django.core.cache import cache
cache.set("foo", "bar")
print cache.get("foo")

You may be interested in the django-heroku-memcacheify pip, which fully configures MemCachier with one line of code for any Django app the pip supports.

A confusing error message you may get from pylibmc is MemcachedError: error 37 from memcached_set: SYSTEM ERROR(Resource temporarily unavailable). This indicates that you are trying to store a value larger than 1MB. MemCachier has a hard limit of 1MB for the size of key-value pairs. To work around this, either consider sharding the data or using a different technology. The benefit of an in-memory key-value store diminishes at 1MB and higher.

PHP

We’ve built a small PHP example here: MemCachier PHP sample app.

We recommend users utilize the PHPMemcacheSASL client as we have more experience in using and supporting it. Start by downloading the PHPMemcacheSASL library. From here you can start writing cache code in your PHP app:

include('MemcacheSASL.php');
$m = new MemcacheSASL;
$servers = explode(",", getenv("MEMCACHIER_SERVERS"));
foreach ($servers as $s) {
    $parts = explode(":", $s);
    $m->addServer($parts[0], $parts[1]);
}
$m->setSaslAuthData(getenv("MEMCACHIER_USERNAME"), getenv("MEMCACHIER_PASSWORD"));

$m->add("foo", "bar");
echo $m->get("foo");

The more common PHP memcache clients have limited support for working with MemCachier due to issues with SASL authentication. The Memcache simply doesn’t provide SASL authentication support and so is not an option. The Memcached, does provide SASL authentication and so is a fine option for using with MemCachier. We simply have less experience in using it at this time and so continue to recommend PHPMemcacheSASL.

Node.js

We’ve built a small Node.js example here: MemCachier Node.js sample app.

For Node.js we recommend the use of the memjs client library. It is written and supported by MemCachier itself! To install, use the node package manager (npm):

npm install memjs

Using it is straight-forward as memjs understands the MEMCACHIER_SERVERS, MEMCACHIER_USERNAME and MEMCACHIER_PASSWORD environment variables that the MemCachier add-on setups. For example:

var memjs = require('memjs')
var mc = memjs.Client.create()
mc.get('hello', function(val) {
    alert(val)
})

Java

We’ve built a small Java example here, using Jetty: MemCachier Java sample app.

For Java we recommend using the SpyMemcached client. We also recommend using the Apache Maven build manager for working with Java applications. If you aren’t using maven and are instead using Apache Ant or your own build system, then simply add the spymemcached jar file as a dependency of your application.

Please make sure to use version 2.8.9 or earlier! At the moment, version 2.8.10 and later have an issue with SASL authentication that makes them unusable with MemCachier.

For maven however, start by configuring it to have the proper spymemcached repository:

<repository>
  <id>spy</id>
  <name>Spy Repository</name>
  <layout>default</layout>
  <url>http://files.couchbase.com/maven2/</url>
  <snapshots>
    <enabled>false</enabled>
  </snapshots>
</repository>

Then add the spymemcached library to your dependencies:

<dependency>
  <groupId>spy</groupId>
  <artifactId>spymemcached</artifactId>
  <version>2.8.9</version>
  <scope>provided</scope>
</dependency>

Once your build system is configured, you can start adding caching to your Java app:

import java.io.IOException;
import net.spy.memcached.AddrUtil;
import net.spy.memcached.MemcachedClient;
import net.spy.memcached.ConnectionFactoryBuilder;
import net.spy.memcached.auth.PlainCallbackHandler;
import net.spy.memcached.auth.AuthDescriptor;

public class Foo {
  public static void main(String[] args) {
    AuthDescriptor ad = new AuthDescriptor(new String[] { "PLAIN" },
        new PlainCallbackHandler(System.getenv("MEMCACHIER_USERNAME"),
            System.getenv("MEMCACHIER_PASSWORD")));

    try {
      MemcachedClient mc = new MemcachedClient(
          new ConnectionFactoryBuilder()
              .setProtocol(ConnectionFactoryBuilder.Protocol.BINARY)
              .setAuthDescriptor(ad).build(),
          AddrUtil.getAddresses(System.getenv("MEMCACHIER_SERVERS")));
      mc.set("foo", "bar");
      System.out.println(mc.get("foo"));
    } catch (IOException ioe) {
      System.err.println("Couldn't create a connection to MemCachier: \nIOException "
              + ioe.getMessage());
    }
  }
}

It is possible that you will run into Java exceptions about the class loader. (See Spymemcached issue 155. The reported issue also contains a suggested work around.

You may wish to look the spymemcached JavaDocs or some more example code to help in using MemCachier effectively. There is also a guide on using WebRunner, Heroku’s framework to handle sessions with MemCachier.

Library support

MemCachier will work with any memcached binding that supports SASL authentication and the binary protocol. We have tested MemCachier with the following language bindings, although the chances are good that other SASL binary protocol packages will also work.

Language Bindings
Ruby dalli
Python pylibmc
Django django-pylibmc
PHP PHPMemcacheSASL or PHP Memcached
Node.js memjs
Java spymemcached (version 2.8.9 or earlier) or xmemcached
Go mc
Haskell memcache

Sample apps

We’ve built a number of working sample apps, too:

Local usage

To test your Heroku application locally, you will need to run a local memcached server. MemCachier can only run in Heroku, but because MemCachier and memcached speak the same protocol, you shouldn’t have any issues testing locally. Installation depends on your platform.

This will install memcached without SASL authentication support. This is generally what you want as client code can still try to use SASL auth and memcached will simply ignore the requests which is the same as allowing any credentials. So your client code can run without modification locally and on Heroku.

On Ubuntu:

$ sudo apt-get install memcached

Or on OS X (with Homebrew):

$ brew install memcached

Or for Windows please refer to these instructions.

For further information and resources (such as the memcached source code) please refer to the Memcache.org homepage

To run memcached simply execute the following command:

$ memcached -v

Usage analytics

Our analytics dashboard is a simple tool that gives you more insight into how you’re using memcache. Here’s a screenshot of the dashboard:

Analytics Dashboard

To access your application’s analytics dashboard run:

$ heroku addons:open memcachier

Or open MemCachier from your application’s dashboard on heroku.com.

The analytics displayed are:

  • Limit – Your current cache size and memory limit. Once usage comes close to this amount you will start seeing evictions.
  • Live Connections – Number of connections currently open to your cache.
  • Total connections – Number of connections ever made to your cache. (So always larger than live connections).
  • Items – Number of items currently stored in your cache.
  • Evictions – Number of items ever evicted from your cache due to memory pressure. Items are evicted in an LRU order.
  • New Evictions – Number of evictions that have occured since the last time we sampled your cache.
  • Hit Rate – The ratio of get commands that return an item (hit) vs. the number that return nothing (miss). This ratio is for the period between now and when we last sampled your cache.
  • Set Cmds – Number of times you have ever performed a set command.
  • Flush Cmds – Number of times you have ever performned a flush command.

With the basic analytics dashboard we sample your cache once per hour. With the advance dashboard we sample it once every 30 minutes.

Advanced analytics

We offer higher paying customers an advance version of our analytics dashboard. Currently, this offers two primary advantages:

  • Higher Sample Rate – We sample the cache for collecting analytics once every thirty minutes, twice the rate of the basic analytics dashboard. We don’t sample more often than that as a higher granularity hasn’t proven to be useful, it leads to more noise and less signal.
  • More Graphs – We offer two additional graphs for the advanced analytics dashboard.
    • Eviction Graph – Your new evictions tracked over time.
    • Connection Graph – Your new connecions tracked over time.

New Relic integration

MemCachier supports integration with your New Relic dashboard if you happen to be a customer of both MemCachier and New Relic. Currently this feature is only available to caches of 500MB or larger. A blog post showing the integration can be found here.

To setup the integration you will need to find your New Relic license key. This can be done by going to your “Account Settings” page when logged in to New Relic by click on your New Relic username in the top right corner. Then you will find your license key in the right side information column. It should be exactly 40 characters long. Please refer to the blog post for a visual walkthrough.

Once you have your New Relic licence key, it can be entered for your cache on the analytics dashboard page. In the bottom right corner there is a button to do this.

Upgrading and downgrading

Changing your plan, either by upgrading or downgrading, can be done easily at any time through Heroku.

  • No code changes are required.
  • Your cache won’t be lost or reset*.
  • You are charged by the hour for plans, so try experimenting with different cache sizes with low cost.

When moving between the development plan to a production plan, you will loose your cache. This is unavoidable due to the strong separation between the development and production clusters.

Using MemCachier

Please refer to your client or framework documentation for how to use MemCachier effectively. We have also written a guide on advanced memcache usage.

Framework and Client Documentation:

Key-Value size limit (1MB)

MemCachier has a maximum size that a key-value object can be of 1MB. This applies to both key-value pairs created through a set command, or existing key-value pairs grown through the use of an append or prepend command. In the later case, the size of the key-value pair with the new data added to it, must still be less than 1MB.

The 1MB limit applies to the size of the key and the value together. A key of size 512KB with a value of 712KB would be in violation of the 1MB limit.

The reason for this has partially to do with how memory is managed in MemCachier. A limitation of the high performance design is a restriction on how large key-value pairs can become. Another reason is that storing values larger than 1MB doesn’t normally make sense in a high-performance key-value store. The network transfer time in these situations becomes the limiting factor for performance. A disk cache or even a database makes sense for this size value.

Errors about app trying to connect to localhost

By default, most memcache client look for the environment variables, MEMCACHE_SERVERS, MEMCACHE_USERNAME and MEMCACHE_PASSWORD for their configuration. These variables are used when the initialization code for the memcache client doesn’t specifically specify these values.

If these environment variables aren’t set, clients generally default to connecting to 127.0.0.1:11211 (i.e., localhost), with no username and password.

The MemCachier add-on sets the MEMCACHIER_SERVERS, MEMCACHIER_USERNAME and MEMCACHIER_PASSWORD environment variables. So you need to either set the equivalent MEMCACHE_* variables from these, or pass these values to your client when you create a new one in your code.

For example, pseudo-code for the first approach is:

env[MEMCACHE_SERVERS] = env[MEMCACHIER_SERVERS]
env[MEMCACHE_USERNAME] = env[MEMCACHIER_USERNAME]
env[MEMCACHE_PASSWORD] = env[MEMCACHIER_PASSWORD]

While pseudo-code for the second approach is:

memClient = new MemcacheClient(ENV['MEMCACHIER_SERVERS'],
                               ENV['MEMCACHIER_USERNAME'],
                               ENV['MEMCACHIER_PASSWORD'])

Please be careful that you have setup the your client in all locations. Many frameworks, such as Rails, use memcache in multiple ways and may require you to setup initialization properly in a few locations. Generally the first approach is preferred as it is global while the second approach is local to each initialization.

For example, with Ruby on Rails, you’ll need to setup cache_store, Rack::Cache and the session_store.

Support

All MemCachier support and runtime issues should be submitted via on of the Heroku Support channels. You can also reach us directly at support@memcachier.com. We encourage you to CC us on any urgent support tickets sent to Heroku. Please include your MEMCACHIER_USERNAME with support tickets.

Any non-support related issues or product feedback is welcome via email at: support@memcachier.com.

Any issues related to MemCachier service are reported at MemCachier Status.

Please also follow us on twitter, @memcachier, for status and product announcements.