Rails MongoDB, как вставить последний документ и быть уверенным, что он потокобезопасен? - PullRequest
2 голосов
/ 24 мая 2011

Мне нужно, когда я добавляю новый документ в свою коллекцию X, чтобы получить последний документ, который был вставлен в эту же коллекцию, потому что некоторые значения этого документа должны влиять на документ, который я сейчас вставляю.

В основномв качестве простого примера мне нужно сделать это:

class X
  include Mongoid::Document
  include Mongoid::Timestamps

  before_save :set_sum

  def set_sum
   self.sum = X.last.sum + self.misc
  end

  field :sum, :type => Integer

  field :misc, :type => Integer
end

Как я могу убедиться, что тип процесса никогда не сломается, если есть одновременная вставка?Я должен убедиться, что когда self.sum = X.last.sum + self.misc рассчитывается, что X.last.sum абсолютно соответствует последнему возможному документу, вставленному в коллекцию?

Это очень важно для моей системы.Он должен быть потокобезопасным.

Alex

ps: это также должно быть быстродействующим, когда в коллекциях содержится 50 тыс. Документов, для получения последнего значения может не потребоваться время...

Ответы [ 2 ]

1 голос
/ 01 июня 2011

Такое поведение эквивалентно наличию идентификатора автоинкремента. http://www.mongodb.org/display/DOCS/How+to+Make+an+Auto+Incrementing+Field Самый простой способ - создать боковую коллекцию с одним (или несколькими) документами, представляющими текущие итоговые значения. Затем в своем клиенте, перед вставкой нового документа, выполните findAndModify (), который атомарно обновляет итоги и извлекает текущий итоговый документ. Частью текущего документа может быть автоматическое увеличение _id, так что даже если есть одновременные вставки, ваш документ будет правильно упорядочен, пока вы сортируете по _id. Единственное предостережение: если ваше клиентское приложение умирает после findAndModify и до вставки, у вас будет пробел. Либо это нормально, либо вам нужно добавить дополнительные средства защиты, такие как ведение бокового журнала.

Если вы хотите быть на 100% в безопасности, вы также можете получить вдохновение от 2-фазного коммита http://www.mongodb.org/display/DOCS/two-phase+commit По сути, это правильный способ сделать транзакцию с любой БД, которая охватывает более 1 сервера (даже sql там не поможет) Лучший AG

0 голосов
/ 25 мая 2011

Если вам нужно сохранить промежуточную сумму, это, вероятно, следует сделать для другого документа в другой коллекции. Лучший способ сохранить эту промежуточную сумму - использовать атомарную операцию $inc. Нет необходимости выполнять какие-либо операции чтения при расчете этой суммы.

Вы захотите вставить свой X-документ в его коллекцию, а затем $inc значение в другом документе, предназначенное для хранения этого списка всех misc значений из X-документов.

Примечание. Это все равно не будет транзакционным, потому что вы обновляете два документа в двух разных коллекциях по отдельности, но это будет высокопроизводительным и полностью безопасным для потоков.

Для получения дополнительной информации ознакомьтесь со всеми Атомными операциями MongoDB .

...