104
CHRIS WANSTRATH ERR FREE [ http://errfree.com ]

Kickin' Ass with Cache-Fu (without notes)

  • Upload
    err

  • View
    9.541

  • Download
    2

Embed Size (px)

DESCRIPTION

My memcached talk at RailsConf 2007 (without notes). See the blog post: http://errtheblog.com/post/4872

Citation preview

Page 1: Kickin' Ass with Cache-Fu (without notes)

CHRIS WANSTRATHERR FREE

[ http://errfree.com ]

Page 2: Kickin' Ass with Cache-Fu (without notes)
Page 3: Kickin' Ass with Cache-Fu (without notes)
Page 4: Kickin' Ass with Cache-Fu (without notes)
Page 5: Kickin' Ass with Cache-Fu (without notes)
Page 6: Kickin' Ass with Cache-Fu (without notes)
Page 7: Kickin' Ass with Cache-Fu (without notes)
Page 8: Kickin' Ass with Cache-Fu (without notes)
Page 9: Kickin' Ass with Cache-Fu (without notes)
Page 10: Kickin' Ass with Cache-Fu (without notes)
Page 11: Kickin' Ass with Cache-Fu (without notes)
Page 12: Kickin' Ass with Cache-Fu (without notes)

50,000,000 pages

no downtime

Page 13: Kickin' Ass with Cache-Fu (without notes)

memcached.

Page 14: Kickin' Ass with Cache-Fu (without notes)

Memcaching Rails

CHRIS WANSTRATHERR FREE[ http://errfree.com ]

Page 15: Kickin' Ass with Cache-Fu (without notes)

Memcaching Rails

CHRIS WANSTRATHERR FREE[ http://errfree.com ]

Page 16: Kickin' Ass with Cache-Fu (without notes)

kickin’ asswith cache-fu

chris wanstrathrailsconf 2007

Page 17: Kickin' Ass with Cache-Fu (without notes)

{}

Page 18: Kickin' Ass with Cache-Fu (without notes)

class Memcache < Hash undef :each, :keysend

Page 19: Kickin' Ass with Cache-Fu (without notes)

class Memcache < DRbHash undef :each, :keysend

Page 20: Kickin' Ass with Cache-Fu (without notes)

$ memcached -vv<3 server listening<7 new client connection<7 get app-test:Story:1>7 END<7 set app-test:Story:2 0>7 STORED<7 delete app-test:Story:1 >7 DELETED

Page 21: Kickin' Ass with Cache-Fu (without notes)

$ memcached -vv<3 server listening<7 new client connection<7 get app-test:Story:1>7 END<7 set app-test:Story:2 0>7 STORED<7 delete app-test:Story:1 >7 DELETED

Page 22: Kickin' Ass with Cache-Fu (without notes)
Page 23: Kickin' Ass with Cache-Fu (without notes)
Page 24: Kickin' Ass with Cache-Fu (without notes)
Page 25: Kickin' Ass with Cache-Fu (without notes)

YAGNI

Page 26: Kickin' Ass with Cache-Fu (without notes)

UYRDNI

Page 27: Kickin' Ass with Cache-Fu (without notes)

UYRDNI(unless you really do need it)

Page 28: Kickin' Ass with Cache-Fu (without notes)
Page 29: Kickin' Ass with Cache-Fu (without notes)

class Presentation < ActiveRecord::Base

def self.get_cache(id) if data = @cache.get(id) data else data = find(id) @cache.set(id, data) data end end

end

Page 30: Kickin' Ass with Cache-Fu (without notes)

class Presentation < ActiveRecord::Base

def self.get_cache(id) @cache.get(id) || @cache.set(id, find(id)) end

end

Page 31: Kickin' Ass with Cache-Fu (without notes)

FragmentsActions

Sessions&

Objects

Page 32: Kickin' Ass with Cache-Fu (without notes)

memcache-client

Page 33: Kickin' Ass with Cache-Fu (without notes)

memcache-client

$ gem install memcache-client

Page 34: Kickin' Ass with Cache-Fu (without notes)

topfunky memcached

Page 35: Kickin' Ass with Cache-Fu (without notes)

CachedModel

Page 36: Kickin' Ass with Cache-Fu (without notes)

Fragment Cache Store

Page 37: Kickin' Ass with Cache-Fu (without notes)

Session Store

Page 38: Kickin' Ass with Cache-Fu (without notes)
Page 39: Kickin' Ass with Cache-Fu (without notes)
Page 40: Kickin' Ass with Cache-Fu (without notes)
Page 41: Kickin' Ass with Cache-Fu (without notes)

cache_fu

Page 42: Kickin' Ass with Cache-Fu (without notes)

cache_fu ( acts_as_cached 2.0 )

Page 43: Kickin' Ass with Cache-Fu (without notes)

FragmentsActions

Sessions&

Objects

Page 44: Kickin' Ass with Cache-Fu (without notes)

acts_as_cached

Page 45: Kickin' Ass with Cache-Fu (without notes)

defaults: ttl: 1800 namespace: railsconf sessions: false fragments: false servers: localhost:11211

config/memcached.yml

Page 46: Kickin' Ass with Cache-Fu (without notes)

defaults: ttl: 1800 namespace: railsconf sessions: true fragments: true servers: localhost:11211

config/memcached.yml

Page 47: Kickin' Ass with Cache-Fu (without notes)

production: benchmarking: false sessions: true fragments: true servers: - 192.185.254.121:11211 - 192.185.254.138:11211 - 192.185.254.160:11211

config/memcached.yml

Page 48: Kickin' Ass with Cache-Fu (without notes)

production: benchmarking: false sessions: true fragments: true servers: - 192.185.254.121:11211 - 192.185.254.138:11211 - 192.185.254.160:11211

config/memcached.yml

Page 49: Kickin' Ass with Cache-Fu (without notes)

class Presentation < ActiveRecord::Base

acts_as_cached

end

Page 50: Kickin' Ass with Cache-Fu (without notes)

get_cache

expire_cache

Page 51: Kickin' Ass with Cache-Fu (without notes)

class Presentation < ActiveRecord::Base

acts_as_cached

after_save :expire_cache

end

Page 52: Kickin' Ass with Cache-Fu (without notes)

class Presentation < ActiveRecord::Base

def self.get_cache(id) if data = @cache.get(id) data else data = find(id) @cache.set(id, data) data end end

end

Page 53: Kickin' Ass with Cache-Fu (without notes)

class Presentation < ActiveRecord::Base

def self.get_cache(id) if not (data = @cache.get(id)).nil? data else data = find(id) @cache.set(id, data) data end end

end

Page 54: Kickin' Ass with Cache-Fu (without notes)

class Presentation < ActiveRecord::Base

def self.get_cache(id) if not (data = @cache.get(id)).nil? data else data = find(id) || false @cache.set(id, data) data end end

end

Page 55: Kickin' Ass with Cache-Fu (without notes)

Presentation.get_cache(1337)

Page 56: Kickin' Ass with Cache-Fu (without notes)
Page 57: Kickin' Ass with Cache-Fu (without notes)
Page 58: Kickin' Ass with Cache-Fu (without notes)

class Presentation < ActiveRecord::Base

acts_as_cached :conditions => 'published = 1'

end

Page 59: Kickin' Ass with Cache-Fu (without notes)

class Presentation < ActiveRecord::Base

acts_as_cached :finder => :find_live

end

Page 60: Kickin' Ass with Cache-Fu (without notes)

Topic.find :all, :conditions => ["created_at > ?", 1.week.ago], :order => 'post_count desc', :limit => 5

Page 61: Kickin' Ass with Cache-Fu (without notes)
Page 62: Kickin' Ass with Cache-Fu (without notes)

class Topic < ActiveRecord::Base

def self.weekly_popular(limit = 5) find :all, :conditions => ["created_at > ?", 1.week.ago], :order => 'post_count desc', :limit => limit end

end

Page 63: Kickin' Ass with Cache-Fu (without notes)

Topic.weekly_popular

Page 64: Kickin' Ass with Cache-Fu (without notes)

DB: 0.00 (0%)

Page 65: Kickin' Ass with Cache-Fu (without notes)

class Topic < ActiveRecord::Base

def self.cached_weekly_popular get_cache(:weekly_popular) do weekly_popular end end

end

Page 66: Kickin' Ass with Cache-Fu (without notes)

Topic.cached_weekly_popular

Page 67: Kickin' Ass with Cache-Fu (without notes)
Page 68: Kickin' Ass with Cache-Fu (without notes)

ruby mocha

Page 69: Kickin' Ass with Cache-Fu (without notes)

bdd test spec

Page 70: Kickin' Ass with Cache-Fu (without notes)

A Ruby object acting as cached- should be able to retrieve a cached version of itself- should be able to set itself to the cache- should pass its cached self into a block when supplied- should be able to expire its cache- should be able to reset its cache- should be able to tell if it is cached- should be able to set itself to the cache with an arbitrary ttl

Finished in 0.028509 seconds.

28 specifications (53 requirements), 0 failures

Page 71: Kickin' Ass with Cache-Fu (without notes)

context "Calling #cached_weekly_popular" do specify "should call #weekly_popular if not cached" do Topic.expects(:fetch_cache).returns(nil) Topic.cached_weekly_popular.should.equal Topic.weekly_popular end

specify "should return if cached" do Topic.expects(:get_cache).returns(true) Topic.expects(:weekly_popular).never Topic.cached_weekly_popular endend

Page 72: Kickin' Ass with Cache-Fu (without notes)

Topic.cached(:weekly_popular)

Page 73: Kickin' Ass with Cache-Fu (without notes)
Page 74: Kickin' Ass with Cache-Fu (without notes)

def self.cache_key_with_date(id) date = Date.today.to_s.tr(' ', '_') cache_key_without_date(id) + ':' + date end

class << self alias_method_chain :cache_key, :date end

Page 75: Kickin' Ass with Cache-Fu (without notes)

class Topic < ActiveRecord::Base

def self.date_for_key Date.today.to_s.tr(' ', '_') end

def self.cached_weekly_popular key = 'weekly_popular' + date_for_key get_cache(key) { weekly_popular } end

end

Page 76: Kickin' Ass with Cache-Fu (without notes)
Page 77: Kickin' Ass with Cache-Fu (without notes)
Page 78: Kickin' Ass with Cache-Fu (without notes)

Topic.find(1, 2, 3)

Page 79: Kickin' Ass with Cache-Fu (without notes)

Topic.get_cache(1, 2, 3)

Page 80: Kickin' Ass with Cache-Fu (without notes)

user_ids = @topic.posts.map(&:user_id).uniq@users = User.get_cache(user_ids)

Page 81: Kickin' Ass with Cache-Fu (without notes)

class ApplicationController before_filter :local_cache_for_requestend

Page 82: Kickin' Ass with Cache-Fu (without notes)

# pulls from memcache@user = User.get_cache(1)

# pulls from local cache@user = User.get_cache(1)

Page 83: Kickin' Ass with Cache-Fu (without notes)

class ApplicationController before_filter :set_cache_override

def set_cache_override returning true do ActsAsCached.skip_cache_gets = !!params[:skip_cache] end end

end

Page 85: Kickin' Ass with Cache-Fu (without notes)
Page 86: Kickin' Ass with Cache-Fu (without notes)
Page 87: Kickin' Ass with Cache-Fu (without notes)
Page 88: Kickin' Ass with Cache-Fu (without notes)

reset_cache

Page 89: Kickin' Ass with Cache-Fu (without notes)

@topic.set_cache

Page 90: Kickin' Ass with Cache-Fu (without notes)

class Presentation < ActiveRecord::Base

acts_as_cached

after_save :reset_cache

end

Page 91: Kickin' Ass with Cache-Fu (without notes)
Page 92: Kickin' Ass with Cache-Fu (without notes)

class Presentation < ActiveRecord::Base

acts_as_cached :version => 1

end

Page 93: Kickin' Ass with Cache-Fu (without notes)
Page 94: Kickin' Ass with Cache-Fu (without notes)

monit

Page 95: Kickin' Ass with Cache-Fu (without notes)

libketama

Page 96: Kickin' Ass with Cache-Fu (without notes)

1

200

400

600

Page 97: Kickin' Ass with Cache-Fu (without notes)

1

200

400

600 cache_get :railsconf

Page 98: Kickin' Ass with Cache-Fu (without notes)

1

200

400

600

:railsconf == 100

Page 99: Kickin' Ass with Cache-Fu (without notes)

1

200

400

600

:railsconf == 200

Page 100: Kickin' Ass with Cache-Fu (without notes)

1

200600

:railsconf == 200

Page 101: Kickin' Ass with Cache-Fu (without notes)

1

200

400

600

:railsconf == 200

500 300

700

Page 102: Kickin' Ass with Cache-Fu (without notes)

l33t h4x0rs

• Rob Sanheim• Lourens Naudé• Corey Donohoe• Eric Hodel

• Geoffrey Grosenbach• Ryan King• Michael Moen• PJ Hyett

Page 103: Kickin' Ass with Cache-Fu (without notes)

{} ( thanks. any questions? )

Page 104: Kickin' Ass with Cache-Fu (without notes)

http://flickr.com/photos/seibuone/144588686/http://flickr.com/photos/j00zt1n/255430115/http://flickr.com/photos/jameswong/145397570/http://flickr.com/photos/xalpha/58368229/http://flickr.com/photos/63503896@N00/35723413/http://flickr.com/photos/mrcrash/145451993/http://flickr.com/photos/psybernoid/398301743/http://flickr.com/photos/45royale/422227291/http://flickr.com/photos/andrson/420810541/http://flickr.com/photos/joshuaweiland/370931770/http://flickr.com/photos/zesmerelda/27258314/http://flickr.com/photos/slice/390271923/http://flickr.com/photos/cocoen/411960476/http://flickr.com/photos/pinguino/198885132/http://flickr.com/photos/davidfmiller/468476118/http://laughingsquid.com - Scott Bealehttp://flickr.com/photos/bail56/313536999/http://flickr.com/photos/65995199@N00/272672183/

thanksflickr