Есть ли ORM-подобная оболочка для memcached?

Я ищу рубиновый драгоценный камень (или плагин для рельсов), который абстрагирует детали memcached так же, как ActiveRecord абстрагирует детали SQL. Я НЕ ищу что-то, что поможет кэшировать модели ActiveRecord в memcached. Я уверен, что есть примерно 4215 драгоценных камней, которые помогут решить эту проблему.

В идеале я хотел бы иметь возможность сделать что-то вроде:

class Apple < MemcachedModel
# whatever else here
end

а затем иметь возможность делать такие вещи, как:

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

который будет искать JSON-представление этого класса в memcached и десериализовать его. Я также мог бы делать такие вещи, как:

my_apple.color = "red"

# persist changes back to memcached
my_apple.save 

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

Кажется, что кто-то, должно быть, уже избавился от этого зуда и создал что-то в этом духе, но всякий раз, когда я ищу в Google такую ​​жемчужину, я просто продолжаю находить вещи, которые помогают кэшировать модели AR с помощью memcached.


person Pete Hodgson    schedule 30.06.2009    source источник


Ответы (5)


Вы можете взглянуть на мой драгоценный камень moneta, который представляет собой ORM-подобную вещь для всех видов хранилищ ключ-значение. Вы можете увидеть его по адресу: http://github.com/wycats/moneta/tree/master

Основная идея moneta заключается в том, что все KVS должны вести себя точно так же, как подмножество обычных хэшей Ruby. Мы поддерживаем:

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

Методы store и update_key принимают дополнительный хеш параметров, который вы можете использовать следующим образом:

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

Мы поддерживаем большое количество KVS:

  • БерклиДБ
  • CouchDB
  • DataMapper (что означает любое хранилище, поддерживаемое DM)
  • Файлы
  • БМО
  • Кэш памяти
  • Внутрипроцессная память
  • MongoDB
  • Редис
  • Кабинет Токио
  • Токийский тиран
  • S3
  • СДБМ
  • Файлы, использующие XAttrs

Каждое хранилище поддерживает истечение срока действия либо изначально (например, в memcached), либо с помощью стандартного модуля, который эмулирует истечение срока действия в стиле memcache. API всегда идентичен, и существует общая спецификация, с которой работают все адаптеры для обеспечения соответствия.

Также довольно легко добавить свой собственный адаптер, поэтому их так много.

person Yehuda Katz    schedule 02.07.2009
comment
Это действительно интересная библиотека. Спасибо, что разместили его здесь! - person Simone Carletti; 02.07.2009
comment
Прохладный. спасибо Иегуда, я проверю это. Я искал предлог, чтобы поиграть со всеми этими новыми хранилищами постоянных хэшей, которые появляются. - person Pete Hodgson; 06.07.2009

Я не знаю ни о каком Ruby ActiveRecord-подобном адаптере для Memcached. Подобную библиотеку, вероятно, будет трудно создать, потому что Memcached не действует как реляционная база данных.

В результате библиотека не сможет реализовать около 80% функций, поддерживаемых ActiveRecord, так в чем же польза от такой реализации? У вас уже есть все необходимое в Rails для работы с memcache с паттерном "CRUD".

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

Если вы чувствуете себя более комфортно, вы можете создать оболочку и проксировать эти методы с помощью соответствующих методов new/create/update/save/destroy. Однако вы никогда не сможете выйти за рамки базовой системы CRUD только потому, что Memcached не предназначен для использования в качестве реляционной базы данных.

person Simone Carletti    schedule 30.06.2009

Это довольно легко реализовать.

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

Используйте это так:

# 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
person mislav    schedule 30.06.2009
comment
Хороший. Мне особенно нравится, как вы реализовали get_unique_id. В идеале я хочу использовать существующую библиотеку, а не заново изобретать колесо, но если бы мне нужно было сделать это с нуля, я бы хотел украсть то, что у вас есть здесь :) - person Pete Hodgson; 01.07.2009

Как писала Симона Карлетти, Memcached не является реляционной базой данных; он даже не может перечислить все свои ключи. Таким образом, любая модель, подобная ActiveRecord, хранящая данные в Memcached, не будет содержать всех функций ActiveRecord. Тем не менее, я считаю, что наличие согласованного API для всех ваших моделей имеет определенную ценность, поэтому, если имеет смысл хранить данные одной из ваших моделей в Memcached, вы можете использовать этот модуль, который я создал для этой цели:

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

person James McKinney    schedule 01.11.2010

Возможно, вы ищете кэш-деньги Ника Каллена.

person Sarah Mei    schedule 30.06.2009
comment
Спасибо, Сара, но это именно то, что я НЕ ищу - кэширующая библиотека для ActiveRecord. - person Pete Hodgson; 01.07.2009
comment
А, я вижу, я неправильно понял ваш вопрос. Вы хотите вообще отказаться от ActiveRecord и хранить объекты только в memcached? Мне любопытно, какие вещи вы будете хранить. - person Sarah Mei; 02.07.2009
comment
Да, у меня есть временные данные, которые я получаю из другого API. Я хочу кэшировать данные локально, чтобы мне не приходилось обращаться к этому другому API каждый раз, когда я обслуживаю запрос. Материал, который я кэширую, — это информация об учетной записи — такие объекты, как пользователь, организация и т. д. и т. д. - person Pete Hodgson; 06.07.2009