Share
Embed
Transcript
61 slides
-
“There are only two hard problems in Computer Science: cache
invalidation and naming things.” — Phil Karlton -
1 1 request ativa geração de cache. As outras esperam
o cache ser gerado. -
2 1 request ativa geração de cache. As outras requests
são servidas com o cache antigo. http://blog.plataformatec.com.br/2009/09/how-to-avoid-dog-pile-effect-rails-app/ -
module ActiveSupport module Cache class SmartMemCacheStore < MemCacheStore alias_method :orig_read,
:read alias_method :orig_write, :write def read(key, options = nil) lock_expires_in = options.delete(:lock_expires_in) if !options.nil? lock_expires_in ||= 30 response = orig_read(key, options) return nil if response.nil? data, expires_at = response if Time.now > expires_at && !orig_read("lock_#{key}").present? orig_write("lock_#{key}", true, :expires_in => lock_expires_in) return nil else data end end def write(key, value, options = nil) expires_delta = options.delete(:expires_delta) if !options.nil? expires_delta ||= 300 expires_at = Time.now + expires_delta package = [value, expires_at] orig_write(key, package, options) delete("lock_#{key}") end end end end -
module ActiveSupport module Cache class SmartMemCacheStore < MemCacheStore alias_method :orig_read,
:read alias_method :orig_write, :write def read(key, options = nil) lock_expires_in = options.delete(:lock_expires_in) if !options.nil? lock_expires_in ||= 30 response = orig_read(key, options) return nil if response.nil? data, expires_at = response if Time.now > expires_at && !orig_read("lock_#{key}").present? orig_write("lock_#{key}", true, :expires_in => lock_expires_in) return nil else data end end def write(key, value, options = nil) expires_delta = options.delete(:expires_delta) if !options.nil? expires_delta ||= 300 expires_at = Time.now + expires_delta package = [value, expires_at] orig_write(key, package, options) delete("lock_#{key}") end end end end -
def write(key, value, options = nil) expires_delta = options.delete(:expires_delta) if
!options.nil? expires_delta ||= 300 expires_at = Time.now + expires_delta package = [value, expires_at] orig_write(key, package, options) delete("lock_#{key}") end -
def write(key, value, options = nil) expires_delta = options.delete(:expires_delta) if
!options.nil? expires_delta ||= 300 expires_at = Time.now + expires_delta package = [value, expires_at] orig_write(key, package, options) delete("lock_#{key}") end -
def write(key, value, options = nil) expires_delta = options.delete(:expires_delta) if
!options.nil? expires_delta ||= 300 expires_at = Time.now + expires_delta package = [value, expires_at] orig_write(key, package, options) delete("lock_#{key}") end Agora são: 12:00 expires_at: 12:05 -
def read(key, options = nil) lock_expires_in = options.delete(:lock_expires_in) if !options.nil?
lock_expires_in ||= 30 response = orig_read(key, options) return nil if response.nil? data, expires_at = response if Time.now > expires_at && !orig_read("lock_#{key}").present? orig_write("lock_#{key}", true, :expires_in => lock_expires_in) return nil else data end end -
def read(key, options = nil) lock_expires_in = options.delete(:lock_expires_in) if !options.nil?
lock_expires_in ||= 30 response = orig_read(key, options) return nil if response.nil? data, expires_at = response if Time.now > expires_at && !orig_read("lock_#{key}").present? orig_write("lock_#{key}", true, :expires_in => lock_expires_in) return nil else data end end -
def read(key, options = nil) lock_expires_in = options.delete(:lock_expires_in) if !options.nil?
lock_expires_in ||= 30 response = orig_read(key, options) return nil if response.nil? data, expires_at = response if Time.now > expires_at && !orig_read("lock_#{key}").present? orig_write("lock_#{key}", true, :expires_in => lock_expires_in) return nil else data end end Todas requests antes de 12:05 recebem cache hit do cache válido -
def read(key, options = nil) lock_expires_in = options.delete(:lock_expires_in) if !options.nil?
lock_expires_in ||= 30 response = orig_read(key, options) return nil if response.nil? data, expires_at = response if Time.now > expires_at && !orig_read("lock_#{key}").present? orig_write("lock_#{key}", true, :expires_in => lock_expires_in) return nil else data end end -
def read(key, options = nil) lock_expires_in = options.delete(:lock_expires_in) if !options.nil?
lock_expires_in ||= 30 response = orig_read(key, options) return nil if response.nil? data, expires_at = response if Time.now > expires_at && !orig_read("lock_#{key}").present? orig_write("lock_#{key}", true, :expires_in => lock_expires_in) return nil else data end end Ao 12:06 o cache vai estar stale -
def read(key, options = nil) lock_expires_in = options.delete(:lock_expires_in) if !options.nil?
lock_expires_in ||= 30 response = orig_read(key, options) return nil if response.nil? data, expires_at = response if Time.now > expires_at && !orig_read("lock_#{key}").present? orig_write("lock_#{key}", true, :expires_in => lock_expires_in) return nil else data end end request salva um lock no cache -
def read(key, options = nil) lock_expires_in = options.delete(:lock_expires_in) if !options.nil?
lock_expires_in ||= 30 response = orig_read(key, options) return nil if response.nil? data, expires_at = response if Time.now > expires_at && !orig_read("lock_#{key}").present? orig_write("lock_#{key}", true, :expires_in => lock_expires_in) return nil else data end end -
def read(key, options = nil) lock_expires_in = options.delete(:lock_expires_in) if !options.nil?
lock_expires_in ||= 30 response = orig_read(key, options) return nil if response.nil? data, expires_at = response if Time.now > expires_at && !orig_read("lock_#{key}").present? orig_write("lock_#{key}", true, :expires_in => lock_expires_in) return nil else data end end novas requests percebem que tem um lock criado -
def read(key, options = nil) lock_expires_in = options.delete(:lock_expires_in) if !options.nil?
lock_expires_in ||= 30 response = orig_read(key, options) return nil if response.nil? data, expires_at = response if Time.now > expires_at && !orig_read("lock_#{key}").present? orig_write("lock_#{key}", true, :expires_in => lock_expires_in) return nil else data end end elas serão servidas com o cache antigo novas requests percebem que tem um lock criado -
def write(key, value, options = nil) expires_delta = options.delete(:expires_delta) if
!options.nil? expires_delta ||= 300 expires_at = Time.now + expires_delta package = [value, expires_at] orig_write(key, package, options) delete("lock_#{key}") end -
def write(key, value, options = nil) expires_delta = options.delete(:expires_delta) if
!options.nil? expires_delta ||= 300 expires_at = Time.now + expires_delta package = [value, expires_at] orig_write(key, package, options) delete("lock_#{key}") end cria o novo cache -
def write(key, value, options = nil) expires_delta = options.delete(:expires_delta) if
!options.nil? expires_delta ||= 300 expires_at = Time.now + expires_delta package = [value, expires_at] orig_write(key, package, options) delete("lock_#{key}") end -
def write(key, value, options = nil) expires_delta = options.delete(:expires_delta) if
!options.nil? expires_delta ||= 300 expires_at = Time.now + expires_delta package = [value, expires_at] orig_write(key, package, options) delete("lock_#{key}") end deleta o lock