2009-06-30 9 views
6

Estoy buscando un ruby ​​gem (o complemento de rails) que abstraiga los detalles de memcached de la misma manera que ActiveRecord abstrae los detalles de SQL. Estoy NO buscando algo para ayudar a almacenar en caché los modelos ActiveRecord en memcached. Estoy seguro de que hay aproximadamente 4215 gemas que ayudarán con ese problema.¿Hay un contenedor tipo ORM para memcached

Lo ideal sería que lo que me gustaría es ser capaz de hacer algo como:

class Apple < MemcachedModel 
# whatever else here 
end 

y luego ser capaz de hacer cosas como:

my_apple = Apple.find('some memcached key') 

que buscar la representación JSON de esta clase en memcached y deserialize it. También me puede que sea capaz de hacer cosas como:

my_apple.color = "red" 

# persist changes back to memcached 
my_apple.save 

# load any changes from memcached into local model 
my_apple.update 

Parece que alguien debe haber arañado la picazón por ahora y ha creado algo en este sentido, pero cada vez que Google para una joya Acabo de seguir girando hasta Lo que ayuda a almacenar en ca modelos AR utilizando memcached.

Respuesta

11

Puede echar un vistazo a mi gema moneta, que es una característica ORM'ish para todo tipo de tiendas de valores-clave. Puede verlo en: http://github.com/wycats/moneta/tree/master

La idea básica detrás de moneta es que todos los KVS deben comportarse exactamente como un subconjunto de los hash normales de Ruby.Apoyamos:

#[] 
#[]= 
#delete 
#fetch 
#key? 
#store 
#update_key 
#clear 

Los store y update_key métodos toman un hash de opciones adicionales que se pueden utilizar de esta manera:

cache = Moneta::Memcache.new(:server => "localhost:11211", :namespace => "me") 
cache.store("name", "wycats", :expires_in => 2) 
cache.update_key("name", :expires_in => 10) 

Apoyamos un gran número de KVSs:

  • BerkeleyDB
  • CouchDB
  • DataMapper (Lo que significa cualquier tienda apoyado por DM)
  • Archivos
  • LMC
  • Memcache
  • En-proceso de la memoria
  • MongoDB
  • Redis
  • Tokyo Cabinet
  • Tokyo Tyrant
  • S3
  • SDBM
  • archivos utilizando XAttrs

Cada tienda es compatible con caducidad, ya sea de forma nativa (como en memcached) o utilizando un módulo estándar que emula caducidad de estilo Memcache. La API siempre es idéntica y existe una especificación compartida con la que se ejecutan todos los adaptadores para garantizar el cumplimiento.

También es bastante fácil agregar su propio adaptador, por lo que existen muchos.

+0

Esa es una biblioteca realmente interesante. ¡Gracias por publicarlo aquí! –

+0

Cool. gracias Yehuda, voy a verificar esto. He estado buscando una excusa para jugar con todas estas nuevas tiendas de hash persistentes que están surgiendo. –

3

No conozco ningún adaptador Ruby ActiveRecord para Memcached. Una biblioteca similar probablemente sería difícil de crear porque Memcached no actúa como una base de datos relacional.

El resultado es que la biblioteca no podría implementar aproximadamente el 80% de las características admitidas por ActiveRecord, entonces, ¿cuál es el beneficio de tal implementación? Ya tiene todo lo que necesita en Rails para trabajar con Memcache con un patrón "CRUD".

Rails.cache.read('key') 
Rails.cache.write('key', 'value') 
Rails.cache.delete('key') 
Rails.cache.increment('key', 5) 
Rails.cache.fetch('key') { 'value' } 

Si se siente más cómodo, puede crear un contenedor y el proxy de estos métodos con los correspondientes nuevos/crear/actualizar/Save/destruir métodos. Sin embargo, nunca podrá ir más allá de un sistema CRUD básico simplemente porque Memcached no pretende ser una base de datos relacional.

2

Es bastante fácil de implementar.

require 'ostruct' 
require 'active_support/cache' 

class StoredStruct < OpenStruct 
    attr_writer :store 
    def self.store 
    @store || superclass.store 
    end 

    def self.expand_key(key) 
    'StoredStruct_' + (superclass == OpenStruct ? '' : "#{self}_") + key.to_s 
    end 

    def self.get_unique_id 
    key = expand_key('unique_id') 
    store.write(key, 0, :unless_exist => true) 
    store.increment(key) 
    end 

    def self.save(instance) 
    id = instance.id || get_unique_id 
    store.write(expand_key(id), instance) 
    id 
    end 

    def self.find(id) 
    store.read(expand_key(id)) 
    end 

    attr_reader :id 

    def attributes 
    @table 
    end 

    def attributes=(hash) 
    @table = hash 
    end 

    def new_record? 
    self.id.nil? 
    end 

    def save 
    @id = self.class.save(self) 
    true 
    end 

    def reload 
    instance = self.class.find(self.id) 
    self.attributes = instance.attributes unless self == instance 
    self 
    end 
end 

utilizar de esta manera:

# connect to memcached 
StoredStruct.store = ActiveSupport::Cache::MemCacheStore.new("localhost:11211") 

class Apple < StoredStruct 
end 

fruit = Apple.new 
fruit.color = "red" 
fruit.taste = "delicious" 

fruit.id 
#=> nil 

fruit.save 
#=> true 
fruit.id 
#=> 1 

# to load any changes: 
fruit.reload 

Apple.find(1) 
#=> fruit 
+0

Agradable. Me gusta especialmente cómo implementó get_unique_id. Idealmente, estoy buscando utilizar una biblioteca existente en lugar de volver a inventar la rueda, pero si tuviera que hacer esto desde el principio, me encantaría robar lo que tienes aquí :) –

0

Usted puede estar buscando Nick Kallen's cache-money.

+0

Gracias Sarah, pero eso es específicamente lo que soy NO está buscando: una biblioteca de almacenamiento en caché para ActiveRecord. –

+0

Ah, veo que he entendido mal tu pregunta. ¿Desea prescindir de ActiveRecord por completo y solo almacenar los objetos en memcached? Tengo curiosidad por saber qué tipo de cosas vas a guardar. –

+0

Sí, tengo datos transitorios que obtengo de otra API. Quiero guardar en caché los datos localmente para no tener que hacer un viaje de ida y vuelta a esta otra API cada vez que atiendo una solicitud. Lo que estoy almacenando en caché es información de la cuenta: objetos como un usuario, una organización, etc. etc. –

1

Como escribió Simone Carletti, Memcached no es una base de datos relacional; ni siquiera puede enumerar todas sus claves. Como tal, cualquier modelo similar a ActiveRecord que almacene datos en Memcached no contendrá toda la funcionalidad de ActiveRecord. No obstante, creo que tiene algún valor tener una API consistente para todos sus modelos, por lo que si tiene sentido que uno de sus modelos almacene sus datos en Memcached, puede usar este módulo que creé para ese fin:

http://blog.slashpoundbang.com/post/1455548868/memcachemodel-make-any-ruby-object-that-persists-in

Cuestiones relacionadas