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

Riak on Ruby: Keys, Values and CRDTs

Riak on Ruby: Keys, Values and CRDTs

Basic intro to Riak through Ruby-colored glasses. Presented at the Atlanta Ruby Users Group on 8/14/2013: http://www.meetup.com/atlantaruby/events/104483692/

Tom Santero

August 14, 2013
Tweet

More Decks by Tom Santero

Other Decks in Programming

Transcript

  1. Riak on Ruby
    Keys Values & CRDTs
    8/14/2013

    View Slide

  2. tsantero
    { twitter
    github
    basho.com
    @

    View Slide

  3. https://identicons.github.com/tsantero.png

    View Slide

  4. Riak
    https://github.com/basho/riak
    http://docs.basho.com/riak/latest/downloads/

    View Slide

  5. masterless
    &
    distributed

    View Slide

  6. $  wget  http://$PATH/debian/6/riak_1.4.1-­‐1_amd64.deb
    -­‐-­‐2013-­‐08-­‐14  14:00:35-­‐-­‐    http://$PATH/riak_1.4.1-­‐1_amd64.deb
    Resolving  s3.amazonaws.com...  176.32.99.42
    Connecting  to  s3.amazonaws.com|176.32.99.42|:80...  connected.
    HTTP  request  sent,  awaiting  response...  200  OK
    Length:  26883312  (26M)  [application/x-­‐debian-­‐package]
    Saving  to:  ‘riak_1.4.1-­‐1_amd64.deb’
    100%[=========================>]  26,883,312      691KB/s      in  37s
    2013-­‐08-­‐14  14:01:13  (703  KB/s)  -­‐  ‘riak_1.4.1-­‐1_amd64.deb’  saved  
    [26883312/26883312]

    View Slide

  7. $  ls
    riak_1.4.1-­‐1_amd64.deb
    $  sudo  dpkg  -­‐i  riak_1.4.1-­‐1_amd64.deb
    #  repeat  for  all  nodes  in  cluster

    View Slide

  8. #  on  all  nodes  in  cluster  do:
    $  riak-­‐admin  cluster  join  [email protected]

    View Slide

  9. $  riak-­‐admin  cluster  plan
    ###############################################################################
                                                     After  cluster  transition  1/2
    ###############################################################################
    =================================  Membership  ==================================
    Status          Ring        Pending        Node
    -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐
    valid          100.0%          20.0%        '[email protected]'
    joining          0.0%          20.0%        '[email protected]'
    joining          0.0%          20.0%        '[email protected]'
    joining          0.0%          20.0%        '[email protected]'
    joining          0.0%          20.0%        '[email protected]'
    -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐
    Valid:1  /  Leaving:0  /  Exiting:0  /  Joining:4  /  Down:0
    ...
    $  riak-­‐admin  cluster  commit

    View Slide

  10. Riak Cluster
    Riak Node

    View Slide

  11. Riak Ruby Client
    https://github.com/basho/riak-ruby-client

    View Slide

  12. $ gem install riak-client

    View Slide

  13. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #!/usr/bin/env  ruby
    require  ‘riak’
    #  open  connection  to  Riak
    client  =  Riak::Client.new
    client.ping  
     
    #  =>  true

    View Slide

  14. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #!/usr/bin/env  ruby
    require  ‘riak’
    #  specify  a  list  of  nodes  to  connect  to
    client  =  Riak::Client.new(:nodes  =>  [
    {:host  =>  “riak1.domain.com”,  :pb_port  =>  8081},
    {:host  =>  “riak2.domain.com”,  :pb_port  =>  8081},
    {:host  =>  “riak3.domain.com”,  :pb_port  =>  8081},
    {:host  =>  “riak4.domain.com”,  :pb_port  =>  8081},
    {:host  =>  “riak5.domain.com”,  :pb_port  =>  8081}
    ])

    View Slide

  15. {“key” : “value”}

    View Slide

  16. Keys are namespaced
    => BUCKETS

    View Slide

  17. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #  create  a  Riak::Bucket  object
    zomg_bucket  =  client.bucket(‘my_bucket’)
    #  or  you  can  assign  buckets  like  a  hash
    zomg_bucket  =  client[‘my_bucket’]
    #  =>  #

    View Slide

  18. 1
    2
         
     
     
     
    #  list  bucket  properties
    pp  client[‘meow’].props
    {"name"=>"meow",
     "allow_mult"  =>  false,
     "basic_quorum"  =>  false,
     "big_vclock"  =>  50,
     "dw"  =>  "quorum",
     "last_write_wins"  =>  false,
     "n_val"=>  3,    
     "notfound_ok"  =>  true,
     "old_vclock"  =>  86400,
     "postcommit"=>  [],
     "pr"  =>  0,
     "precommit"  =>  [],
     "pw"  =>  0,
     "r"  =>  "quorum",
     "rw"  =>  "quorum",
     "small_vclock"  =>  50,
     "w"  =>  "quorum",
     "young_vclock"  =>  20}

    View Slide

  19. Quorum
    requests
    N R W
    PR/PW DW

    View Slide

  20. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #  let’s  change  some  bucket  properties
    client[‘meow’]  =  {“n_val”  =>  5,  “r”  =>  1,  “w”  =>  5}

    View Slide

  21. GET
    PUT
    DELETE
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD
    CRUD

    View Slide

  22. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    client[‘my_bucket’].exists?(‘my_key’)
    #  =>  false
    some_object  =  client[‘my_bucket’].get_or_new(‘my_key’)
    #  =>  #  
    some_object.data  =  [‘a’,  ‘list’,  ‘of’,  ‘strings’]
    some_object.store
    client[‘my_bucket’][‘my_key’]
    #  =>  #‘list’,  ‘of’,  ‘strings’]>  

    View Slide

  23. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #  create  and  store  a  new  object
    atlrug  =  {
    :title  =>  ‘Riak:  Keys,  Values  and  CRDTs’
    :speaker  =>  ‘Tom  Santero’
    :link  =>  ‘http://www.meetup.com/atlantaruby/events/104483692/’
    :date  =>  ‘2013-­‐08-­‐14’
    }
    meetups_bucket  =  client[‘meetups’]
    meetup_object  =  meetups.bucket.new(atlrug[date])
    meetup_object.data  =  atlrug
    meetup_object.store
    #  object  will  be  encoded  as  JSON

    View Slide

  24. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #  Tom’s  talk  was  horrible,  lets  forget  it  ever  happened
    toms_talk  =  client[‘meetups’][‘2013-­‐08-­‐14’]
    toms_talk.delete
    client[‘meetups’].exists?[‘2013-­‐08-­‐14’]
    #  =>  false

    View Slide

  25. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #  objects  in  Riak  are  opaque
    client[‘images’].new(‘kittah.jpg’).tap  do  |robject|
    robject.content_type  =  ‘image/jpeg’
    robject.raw_data  =  File.read(~/Desktop/kittah.jpg’)
    robject.store
    end
    #  =>  #

    View Slide

  26. View Slide

  27. View Slide

  28. Conflict-Free Replicated Data Types
    (CRDTs)

    View Slide

  29. Riak is
    Eventually
    Consistent

    View Slide

  30. A
    B

    View Slide

  31. Conflicts!

    View Slide

  32. CRDTs

    View Slide

  33. CRDTs
    C {Convergent
    Commutative

    View Slide

  34. CRDTs
    C {Convergent
    Commutative
    Conflict Free

    View Slide

  35. Counters

    View Slide

  36. G Counter
    Grow Only Counter

    View Slide

  37. Monotonic

    View Slide

  38. Convergent
    state-based

    View Slide

  39. {actor_id, value}

    View Slide

  40. A B C
    val_a: 4
    val_b: 7
    val_c: 10
    Total: 21
    val_a: 4
    val_b: 7
    val_c: 10
    Total: 21
    val_a: 4
    val_b: 7
    val_c: 10
    Total: 21

    View Slide

  41. A B C
    val_a: 5
    val_b: 7
    val_c: 10
    Total: 22
    val_a: 4
    val_b: 8
    val_c: 10
    Total: 22
    val_a: 4
    val_b: 7
    val_c: 10
    Total: 21

    View Slide

  42. A B C
    val_a: 5
    val_b: 7
    val_c: 10
    Total: 22
    val_a: 4
    val_b: 8
    val_c: 10
    Total: 22
    val_a: 4
    val_b: 7
    val_c: 10
    Total: 21
    MERGE!

    View Slide

  43. A B C
    val_a: 5
    val_b: 8
    val_c: 10
    Total: 23
    val_a: 5
    val_b: 8
    val_c: 10
    Total: 23
    val_a: 5
    val_b: 8
    val_c: 10
    Total: 23

    View Slide

  44. :)

    View Slide

  45. :(

    View Slide

  46. PN Counter

    View Slide

  47. {P_val, N_val}
    + -

    View Slide

  48. {P_val, N_val}
    + -
    Value = P - N

    View Slide

  49. Sets, Registers, Maps...
    other types:

    View Slide

  50. CRDTs
    no more conflicts!

    View Slide

  51. fin

    View Slide