2

I know Rails.cache is ActiveSupport::Cache::MemoryStore, and it is not thread safe.

I don't understand, why rails use a thread-unsafe cache as its default? Why not use ActiveSupport::Cache::SynchronizedMemoryStore? In my opinion, in a web site, if a cache is not thread-safe, it almost useless, because the requests are not handled in ONE thread.

Do you use Rails.cache in you webapp? And how do you use it?

igauravsehrawat
  • 3,696
  • 3
  • 33
  • 46
Freewind
  • 193,756
  • 157
  • 432
  • 708
  • I know this is an old question, trying to help stop the chasing of wild geese. The thread safety issues in MemoryStore have apparently been fixed and SynchronizedMemoryStore has been deprecated. [https://github.com/rails/rails/commit/ee51b51b60f9e6cce9babed2c8a65a14d87790c8] – Andy Davis Dec 21 '12 at 17:08

3 Answers3

5

The default cache store in Rails is ActiveSupport::Cache::FileStore, not MemoryStore.

The memory store is of limited use in practice, since it is restricted to a single process, which makes it useless for Rails apps that are deployed using Passenger or a Mongrel cluster where requests are handled in separate processes, not in separate threads.

For small to medium-sized applications you'll probably do fine with the default file store. If you need to scale beyond that, you should have a look at ActiveSupport::Cache::MemCacheStore.

Pär Wieslander
  • 28,374
  • 7
  • 55
  • 54
  • thanks for your answer. I was a Java developer, and I thought rails is like java, one process and many threads. Do you mean, when a request comes, there is exactly one process(so one thread) to handle it? If I want a globe cache, I have to consider other cache product, like 'memcached'? – Freewind Jun 18 '10 at 07:29
  • @Freewind: There are several processes, but each process only handles one request at a time. I suggest that you start with a `FileStore` cache. It is a global cache that usually doesn't require any additional configuration, so it's easy to get started with. You can always switch to `memcached` later on if the need arises, but since it requires additional configuration (you have to keep a `memcached` server running), it's easier to start with a `FileStore` and only switch to `memcached` later on if you need to. – Pär Wieslander Jun 18 '10 at 07:40
3

The default Rails cache (ActiveSupport::Cache MemoryStore) is thread-safe as of Rails version 3.1: http://api.rubyonrails.org/v3.1.0/files/activesupport/CHANGELOG.html As the CHANGELOG notes: "Make thread safe so that the default cache implementation used by Rails is thread safe."

2

Most deployment scenario's for Rails are actually single-threaded. Concurrency is achieved by spawning multiple processes, either automatically or beforehand. For many people, thread-safety won't matter that much.

Multi-threaded options do exist (especially with JRuby), so your question is still valid. Which is why in Rails 3, the old ActiveSupport::Cache::MemoryStore has been removed and replaced with ActiveSupport::Cache::SynchronizedMemoryStore, making it thread-safe by default.

If you need the thread-safety in a Rails 2 app, put the following somewhere in your environment.

ActionController::Base.cache_store = :synchronized_memory_store
molf
  • 73,644
  • 13
  • 135
  • 118
  • 1
    @Freewind: Yes, that's right. As both molf and I answered, requests are usually handled in separate processes. Often you have a pool of worker processes, and each new request goes to the first process that's not busy with another request. So yes, if you want a global cache you should go with for example `FileStore` or `MemCacheStore` which both work across processes. – Pär Wieslander Jun 18 '10 at 07:27