Memcached Talk
Memcached Talk
Rob Sharp
[email protected]
Lead Developer
The Sound Alliance
About Memcached
• conceived by Brad Fitzpatrick as a
solution to the scaling issues faced
by Livejournal
• “memcached is a high-
performance, distributed memory
object caching system, generic in
nature, but intended for use in
speeding up dynamic web
applications by alleviating
database load”
Who we are
• Sydney-based online media
publishing
• Community and Content Sites
• Fasterlouder.com.au
• Inthemix.com.au
• Samesame.com.au
• Thoughtbythem - Marketing
Agency
Who we are
• Inthemix.com.au
• Australia’s busiest music website
• ~ 250,000 pages per day
• Plus two other busy sites!
• Maximum performance for the
hardware we have
Current
Architechture
• 3 Linux servers
• Apache
• Lighttpd
• Memcache
• 1 MySQL Master
Why do we use
memcached?
• CMS written in OO style, using
Activerecord
• PHP4 and objects don't mix too
well
• Activerecord gave us fast
development but reduced
performance
• Call us greedy, but we want both
• Use Rails Memcache!
Our Application
• CMS written from the ground up
• Effectively three sites running on
one codebase
• Uses three seperate databases,
but aiming to consolidate more
• Has data namespacing
implemented in most places
• But seperation is not quite there
yet!
Our Memcache
Setup
• We have 3 webservers running
memcache
• Each server runs three daemons
on separate ports - one for each
site (more on this later!)
Memcache Pool
• Each daemon knows about the
other 2 daemons and connects to
them over TCP
• This allows us to store data once,
and access it from any server,
whether in the pool or not
• Hashing algorithm means that a
given key maps to a single server
• Efficient use of memory
• Efficient for cache clearing
Memcache Pool
• But what if we lose a server? We
can
• Ignore it - we simply get misses
for any keys we attempt to
retrieve
• Remove it - our hashing
algorithm breaks... :(
• We can also add new servers to
the pool after data has been
stored, but the same hashing
Memcache Pool
• Consistent hashing will solve the
problem of removing or adding
servers once data has been
hashed
• Currently in its infancy - not really
production ready
• We simply monitor our daemons
and restart if required
• Available in most Linux distros
• packaged
Installing
for Fedora, RHEL4/5,
Ubuntu, Debian, Gentoo and BSD
Memcached
• OSX? Use Ports!
• sudo port install memcache
• sudo gem install memcache-
client
• sudo gem install cached_model
Memcache and
Ruby
require 'memcache'
memcache_options = {
:compression => true,
:debug => false,
:namespace => 'my_favourite_artists',
:readonly => false,
:urlencode => false
}
Cache.delete 'favourite_artist'
Memcache
Namespaces
• Memcache doesn’t have
namespaces, so we have to
improvise
• Prefix your keys with a namespace
by setting the namespace when
you connect
• Our solution:
• Run multiple memcache
instances on different ports
• Makes it easier to clear out
Roll your own?
require 'cached_model'
memcache_options = {
:compression => true,
:debug => false,
:namespace => 'hifibuys',
:readonly => false,
:urlencode => false
}
end
cached_model
• Performance
CachedModel is not magic.
• CachedModel only accelerates simple
finds for single rows.
• CachedModel won’t cache every query
you run.
• CachedModel isn’t smart enough to
determine the dependencies between
your queries so that it can accelerate
more complicated queries. If you want to
cache more complicated queries you
Other options
• Joins Comments
• Joins ‘Rollcalls’
• Joins other secret developments
Our Example
• An article requires many data
facets
• Most don’t change that often
• We also know when they change
• Yay for the Observer pattern
• User content changes much
more regularly
• Can be changed from outside
our controlled area (e.g.
Our Example
Summary
• Data Summary
can be loosely divided into
editorially controlled and user-
generated
• Cache editorially controlled
content separately from user-
generated content
• Simplest way to implement is in
fragment caching
Fragment Caching
• Memcache allows timed expiry of
fragments
• Identify areas that change
infrequently and cache
• Remember to measure
performance before and after
• Evidence suggests very large
gains!
• Use memcache_fragments
Caching Fragments
rsharp$ sudo gem install memcache_fragments
require 'memcache_fragments'
memcache_options = {
:compression => true,
:debug => false,
:namespace => 'hifibuys',
:readonly => false,
:urlencode => false
}