Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What exactly does the Memcached size limit represent with file system entitystore?

Good afternoon,

I have Memcached hooked up in my app on Heroku. The limit for the free managed plan is 5MB for Memcached and 25MB for Memcachier. Being new to pretty much everything, I was just hoping for clarification of exactly what this represents.

I have the DalliStore set up in my config file, and the typical options set up for Rack::Cache. My metastore is in Memcache and the entitiy store is set up on the filesystem.

Questions:

  1. Does this mean that my 5/25MB limit is only being used by the meta information that I am storing about each cache fragment? This would mean that I'd be able to store a ton of information on just the free plans?
  2. What exactly is the breakdown / story between Rack::Cache and Memcache (via Dalli store?) Do they serve different purposes? Are they doing the same thing? i.e. is the following code redundant

    config.cache_store = :dalli_store

and

config.action_dispatch.rack_cache = {
  :verbose      => true,
  :metastore    => Dalli::Client.new,
  :entitystore  => 'file:tmp/cache/rack/body',
  :allow_reload => false
}
like image 912
Brandon Avatar asked Apr 11 '12 23:04

Brandon


People also ask

How much memory do I need for Memcached?

The more memory you can give to memcached, the better. We recommend at least 2GB, if you can afford it. Large deployments may want to give even more. To increase the amount of memory available to memcached, modify the value passed along with -m.

What happens when memcache is full?

First, when memcached gets full, it will start removing items from the cache using the Least Recently Used algorithm. Second, you can have multiple instances of memcached running, adding them gets complicated because it will change the hashing algorithm used to determine which cache the data is in.

How big is memcache?

memcached works equally well for all kinds of data. To memcached, any value you store is just a stream of data. Remember, though, that the maximum size of an object you can store in memcached is 1MB, but can be configured to be larger by using the -I option in memcached 1.4.

What are the some important features of Memcached?

Memcached can serve cached items in less than a millisecond, and enables you to easily and cost effectively scale for higher loads. Memcached is popular for database query results caching, session caching, web page caching, API caching, and caching of objects such as images, files, and metadata.


1 Answers

I've been wrestling with similar issues.

First of all, let's get our terminology straight.

  • Memcached: a process running on a server somewhere (d is for daemon) that actually stores key-value pairs in memory.
  • cache_store: Rails cache storage (Rails.cache) with a single API which can be configured to use different Ruby software implementations. One setting for config.cache_store is :memory_store to use an in-memory implementation. Another setting is :dalli_store that specifies using the dalli gem, which under the hood makes a possibly-remote connection to your memcached server.
  • Dalli Store: I assume you mean the Rails cache backed by the dalli gem, which physically stores values in memcached.
  • Rack::Cache: Rack middleware that inserts headers (Expires, Cache-Control, ETag, etc.) into your HTTP responses, and also acts as a reverse proxy cache, handling requests before they hit the Rails stack when possible. See website.

In order for Rack::Cache to handle requests before they hit the Rails stack and the rest of your app, it must store responses + metadata somewhere. Where it stores things are configured by the config.action_dispatch.rack_cache = { ... } setting.

Notice, this is a different setting from config.cache_store = :dalli_store. They don't have to be related. I think this is where a lot of confusion comes from. In practice, though, we may want them both to use memcached, which means using the dalli implementation. However, they each have their own Dalli::Client instance. (Also, your session_store could be related, but doesn't have to be.)

The Heroku cedar stack has an ephemeral file system that cannot be shared among dynos. However, Heroku themselves recommend using tmp file storage with Rack::Cache for the entitystore only, with memcached used for the metastore.

As for what actually gets stored in the Rack::Cache metastore, these are the docs from rack-cache v1.2 Rack::Cache::MetaStore class:

The MetaStore is responsible for storing meta information about a
request/response pair keyed by the request's URL.

The meta store keeps a list of request/response pairs for each canonical
request URL. A request/response pair is a two element Array of the form:
  [request, response]

The +request+ element is a Hash of Rack environment keys. Only protocol
keys (i.e., those that start with "HTTP_") are stored. The +response+
element is a Hash of cached HTTP response headers for the paired request.

So to answer your question, HTTP request headers and HTTP response headers are stored in the Rack::Cache metastore. On the other hand, the Rack::Cache entitystore stores entire response bodies (i.e. HTML).

Since you can't use page caching reliably on Heroku, this means you might be using action caching and fragment caching. Action and fragment caching use your Rails cache store (not rack cache). But if you've set them both to physically use the same memcached server, they'll both contribute to memory use. Action and partial caching store the actual HTML.

To get more insight of your actual usage, if you're using memcachier run the following command to open up an analytics dashboard in your browser.

heroku addons:open memcachier

See this question for more info about getting memcached stats.

like image 102
Jonathan Tran Avatar answered Sep 23 '22 09:09

Jonathan Tran