$30 off During Our Annual Pro Sale. View Details »

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. Lightning talk
    Alon Burg
    @burgalon
    Optimistic Locking

    View Slide

  2. Overview
    Define the problem
    3 examples with different solution
    3rd example solution with Optimistic
    Locking



    View Slide

  3. Preface: Our tools
    Ruby on Rails
    Mongo (no transactions)
    Mongoid



    View Slide

  4. 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

    View Slide

  5. 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.

    View Slide

  6. 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)

    View Slide

  7. 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



    View Slide

  8. Mongo findAndModify
    Queue.
    where(state: :init).
    asc(:created_at).
    find_and_modify({ "$set" => { state: false }}, new: true)

    View Slide

  9. 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

    View Slide

  10. 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

    View Slide

  11. 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

    View Slide

  12. 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

    View Slide

  13. Questions?

    View Slide

  14. View Slide