Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Mongoid Optimistic Locking

Mongoid Optimistic Locking

Mongoid Atomic Operations
findAndModify
Optimistic Locking
Presented on "Startup Day"

burgalon

June 27, 2012
Tweet

Other Decks in Technology

Transcript

  1. Overview Define the problem 3 examples with different solution 3rd

    example solution with Optimistic Locking • • •
  2. Locking: The Problem Multiple threads/processes trying to update the same

    DB entity row 1 row 1 row 3 row 1 row 2 Table Client Client do some processing do some processing
  3. Example 1: Counter Video 1 100 views Video 2 200

    views Video 3 300 views User 1 User 2 Increment +1 Increment +1 User 1: Find video 1 User 2: Find video 1 User 1: Update video views to 101 User 2: Update video views to 101 1. 2. 3. 4.
  4. Database atomic operation $set - set a particular value $unset

    - delete a particular field (v1.3+) $inc - increment a particular value by a certain amount $push - append a value to an array $pushAll - append several values to an array $pull - remove a value(s) from an existing array $pullAll - remove several value(s) from an existing array $bit - bitwise operations • • • • • • • Video.find(video_id).inc(:views, 1)
  5. Locking: Example 2 Job 1 state: init Client 1 Client

    2 state: processing state: processing Job 2 state: init Job 3 state: init 1) Query .... 2) Update • • •
  6. Example 3: Blog Post add update Requires server side logic

    in between Post text: “Good news, anyone. The Swedish robot from Pi-kea is here with the super collider I ordered.” addUpdate “Bad news, nobody” addUpdate “The super collider exploded” Farnsworth Farnsworth
  7. More specific code for Blog add_update example #### models/post.rb class

    Post include Mongoid::Document field :text end #### controllers/posts_controller.rb class PostController < ApplicationController ## Adds an "UPDATE: ...some text..." to an existing document def add_update post = Post.find(params[:id]) post.text += "---UPDATE--- " + params[:more_text] post.save end end
  8. Optimistic Locking Fetch the object. Modify the object locally. Send

    an update request that says "update the object to this new value if it still matches its old value". 1. 2. 3. Post text: “Good news, anyone. The Swedish robot from Pi-kea is here with the super collider I ordered.” version: 1 Farnsworth addUpdate “Bad news, nobody” Post text: “Good news, anyone. The Swedish robot from Pi-kea is here with the super collider I ordered. -- UPDATE -- Bad news, nobody” version: 2 1) Fetch object 2) Concatenate text and increment version 3) Save to DB if version=1 addUpdate “The super collider exploded” Farnsworth 1.5) Fetch object 2.5) Concatenate text and increment version 3.5) Save to DB if version=1 fails ==> retry Post text: “Good news, anyone. The Swedish robot from Pi-kea is here with the super collider I ordered. -- UPDATE -- Bad news, nobody --UPDATE-- The super collider exploded” version: 3 4) Fetch object 5) Concatenate text and increment version 6) Save to DB if version=2
  9. Rails gem for Mongoid mongoid_optimistic_locking #### models/post.rb class Post include

    Mongoid::Document include Mongoid::OptimisticLocking field :text end #### controllers/posts_controller.rb class PostController < ApplicationController ## Adds an "UPDATE: ...some text..." to an existing document def add_update begin post = Post.find(params[:id]) post.text += "---UPDATE--- " + params[:more_text] post.save rescue Mongoid::Errors::StaleDocument retry end end end