Your SlideShare is downloading. ×
0
Introduction to Riak
Sean Cribbs



basho
system “whoami”
system “whoami”

BCS (Tulsa), three years as a musician
system “whoami”

BCS (Tulsa), three years as a musician
Started with Ruby in early 2006
system “whoami”

BCS (Tulsa), three years as a musician
Started with Ruby in early 2006
Rails freelancer 2007-2010
system “whoami”

BCS (Tulsa), three years as a musician
Started with Ruby in early 2006
Rails freelancer 2007-2010
Radiant...
system “whoami”

BCS (Tulsa), three years as a musician
Started with Ruby in early 2006
Rails freelancer 2007-2010
Radiant...
Rails Can’t Scale
Rails Can’t Scale
  what does it mean?
Ruby Rails Can’t Scale
        what does it mean?
MySQL
Ruby Rails Can’t Scale
        what does it mean?
insert straw man here


  MySQL
Ruby Rails Can’t Scale
        what does it mean?
Mythbusting “scalability”
Mythbusting “scalability”

 Scalability is not a yes/no question
Mythbusting “scalability”

 Scalability is not a yes/no question
 It’s a ratio of benefit to cost
Mythbusting “scalability”

 Scalability is not a yes/no question
 It’s a ratio of benefit to cost
   Benefits: low latency, ...
Mythbusting “scalability”

 Scalability is not a yes/no question
 It’s a ratio of benefit to cost
   Benefits: low latency, ...
Mythbusting “scalability”

 Scalability is not a yes/no question
 It’s a ratio of benefit to cost
   Benefits: low latency, ...
Scaling goes both ways
Scaling goes both ways


Up/Out - high traffic, “Big Data”, multi-datacenter
Scaling goes both ways


Up/Out - high traffic, “Big Data”, multi-datacenter
Down/In - laptop, set-top, mobile
How do you scale?
How do you scale?


Vertically - get bigger, expensive machines
How do you scale?


Vertically - get bigger, expensive machines
Horizontally - get more commodity machines
What is Riak?
     (the horizontal scaling bits)
What is Riak?
       (the horizontal scaling bits)

Based on Amazon’s Dynamo (2007)
What is Riak?
        (the horizontal scaling bits)

Based on Amazon’s Dynamo (2007)
  key-value storage
What is Riak?
        (the horizontal scaling bits)

Based on Amazon’s Dynamo (2007)
  key-value storage
  masterless, pee...
What is Riak?
        (the horizontal scaling bits)

Based on Amazon’s Dynamo (2007)
  key-value storage
  masterless, pee...
What is Riak?
        (the horizontal scaling bits)

Based on Amazon’s Dynamo (2007)
  key-value storage
  masterless, pee...
What is Riak?
        (the horizontal scaling bits)

Based on Amazon’s Dynamo (2007)
  key-value storage
  masterless, pee...
“O/RM is the Vietnam of Computer Science.”
                       -- Ted Neward, 2004/6
“O/RM is the Vietnam of Computer Science.”
                       -- Ted Neward, 2004/6
     slippery slope
“O/RM is the Vietnam of Computer Science.”
                       -- Ted Neward, 2004/6
     slippery slope   diminishing ...
Impedance mismatch
Impedance mismatch


Relational = predicate logic, truth statements
Impedance mismatch


Relational = predicate logic, truth statements
Object = identity, state, behavior, encapsulation
Pick your poison
Pick your poison

Make the objects fit the database
Pick your poison

Make the objects fit the database
  Active Record
Pick your poison

Make the objects fit the database
  Active Record
Make the database fit the objects
Pick your poison

Make the objects fit the database
  Active Record
Make the database fit the objects
  OODBMS, Graph DBs
Middle ground
Middle ground

Document databases (identity and state)
Middle ground

Document databases (identity and state)
  No JOINs - denormalized / composed
Middle ground

Document databases (identity and state)
  No JOINs - denormalized / composed
  Loosely structured
Middle ground

Document databases (identity and state)
  No JOINs - denormalized / composed
  Loosely structured
  Friendl...
What is Riak?
    (the document database bits)
What is Riak?
       (the document database bits)



Store your objects as JSON (or any format)
What is Riak?
       (the document database bits)



Store your objects as JSON (or any format)
Link between objects (like...
What is Riak?
       (the document database bits)



Store your objects as JSON (or any format)
Link between objects (like...
DevOps - agile infrastructure
DevOps - agile infrastructure
     programming your infrastructure
DevOps - agile infrastructure
     programming your infrastructure
    better communication and planning
Befriend your sysadmin
Befriend your sysadmin


Integrate with existing infrastructure
Befriend your sysadmin


Integrate with existing infrastructure
Reduce the amount of hands-on work
Befriend your sysadmin


Integrate with existing infrastructure
Reduce the amount of hands-on work
Have a growth plan
What is Riak?
      (the ops-friendly bits)
What is Riak?
          (the ops-friendly bits)

Web-shaped storage
What is Riak?
            (the ops-friendly bits)

Web-shaped storage
  Store data in its original format
What is Riak?
            (the ops-friendly bits)

Web-shaped storage
  Store data in its original format
  It’s just HTTP...
What is Riak?
            (the ops-friendly bits)

Web-shaped storage
  Store data in its original format
  It’s just HTTP...
What is Riak?
            (the ops-friendly bits)

Web-shaped storage
  Store data in its original format
  It’s just HTTP...
What is Riak?
            (the ops-friendly bits)

Web-shaped storage
  Store data in its original format
  It’s just HTTP...
To review, Riak is...
To review, Riak is...

 Magical Horizontally-
 Scaling Unicorns
To review, Riak is...

 Magical Horizontally-
 Scaling Unicorns
 Application-Friendly
 Rainbows in the Cloud
To review, Riak is...

 Magical Horizontally-
 Scaling Unicorns
 Application-Friendly
 Rainbows in the Cloud
 Data-Shreddi...
soapbox do
http://www.flickr.com/photos/mullica/2769082212/
http://www.flickr.com/photos/bike/236125877/



Stop Cargo-Culting
You are not 37signals, Twitter, or github.
http://www.flickr.com/photos/library_of_virginia/2898496299/



Ignore the Salesperson
Do your own evaluation. Don’t parrot...
http://bit.ly/cGVPv7



Understand your Data
One size does not fit all. Give up your crutches.
Plan for Failure
Your code is not perfect. Your server will go down.
http://www.solarnavigator.net/animal_kingdom/humans/simon_hall.htm



Take Responsibility
Own your choice. Understand the ...
end
Getting Started with Riak
http://192.168.0.87/~sean/riak-training/
Starting up a cluster
Starting up a cluster


 make all devrel
Starting up a cluster


 make all devrel
 dev{1,2,3}/bin/riak start
Starting up a cluster


 make all devrel
 dev{1,2,3}/bin/riak start
 dev{2,3}/bin/riak-admin join dev1@127.0.0.1
Riak CRUD
      http://127.0.0.1:8091/
Riak CRUD
            http://127.0.0.1:8091/

POST /riak/bucket (C - random key)
Riak CRUD
            http://127.0.0.1:8091/

POST /riak/bucket (C - random key)
GET /riak/bucket/key (R)
Riak CRUD
            http://127.0.0.1:8091/

POST /riak/bucket (C - random key)
GET /riak/bucket/key (R)
PUT /riak/bucket...
Riak CRUD
            http://127.0.0.1:8091/

POST /riak/bucket (C - random key)
GET /riak/bucket/key (R)
PUT /riak/bucket...
gem install riak-client
  http://192.168.0.87/~sean/riak-training/
require ‘riak’
require ‘riak’
Make a client object
client = Riak::Client.new
require ‘riak’
Make a client object
client = Riak::Client.new

Get a bucket
bucket = client.bucket(‘foo’) # Riak::Bucket
require ‘riak’
Make a client object
client = Riak::Client.new

Get a bucket
bucket = client.bucket(‘foo’) # Riak::Bucket

...
require ‘riak’
Make a client object
client = Riak::Client.new

Get a bucket
bucket = client.bucket(‘foo’) # Riak::Bucket

...
Riak::RObject
Riak::RObject
Get/set object key
obj.key = “bar”
Riak::RObject
Get/set object key
obj.key = “bar”

Get/set content-type
obj.content_type = ‘application/json’
Riak::RObject
Get/set object key
obj.key = “bar”

Get/set content-type
obj.content_type = ‘application/json’

Get/set the ...
Riak::RObject
Get/set object key
obj.key = “bar”

Get/set content-type
obj.content_type = ‘application/json’

Get/set the ...
LAB
LAB


Build Riak 3-node developer setup
(install Erlang as necessary)
LAB


Build Riak 3-node developer setup
(install Erlang as necessary)
Store an image in Riak via REST API with curl
LAB


Build Riak 3-node developer setup
(install Erlang as necessary)
Store an image in Riak via REST API with curl
Store ...
Riak Influences
Riak Influences


CAP Theorem
Riak Influences


CAP Theorem
Amazon Dynamo Paper
Riak Influences


CAP Theorem
Amazon Dynamo Paper
Operational experience running large networks
CAP Theorem
CAP Theorem


Consistency - globally consistent state
CAP Theorem


Consistency - globally consistent state
Availability - system accepts reads and writes
CAP Theorem


Consistency - globally consistent state
Availability - system accepts reads and writes
Partition Tolerance -...
CAP: Pick two
Riak: Pick two...
     for each operation
Amazon Dynamo
Amazon Dynamo
originally for their shopping cart storage
Amazon Dynamo
originally for their shopping cart storage
masterless, peer-to-peer replication
Amazon Dynamo
originally for their shopping cart storage
masterless, peer-to-peer replication
evenly-distributed key space...
Amazon Dynamo
originally for their shopping cart storage
masterless, peer-to-peer replication
evenly-distributed key space...
Amazon Dynamo
originally for their shopping cart storage
masterless, peer-to-peer replication
evenly-distributed key space...
Amazon Dynamo
originally for their shopping cart storage
masterless, peer-to-peer replication
evenly-distributed key space...
Dynamo Quorums
Dynamo Quorums


N = number of replicas
Dynamo Quorums


N = number of replicas
R = quorum for a successful read
Dynamo Quorums


N = number of replicas
R = quorum for a successful read
W = quorum for a successful write
Dynamo Math
Dynamo Math


N - R = read fault tolerance
Dynamo Math


N - R = read fault tolerance
N - W = write fault tolerance
Dynamo Math
Dynamo Math


N = 4, W = 2, R = 2
Dynamo Math


N = 4, W = 2, R = 2
N - R = 2 (nodes can be down and Riak can still
perform reads)
Dynamo Math


N = 4, W = 2, R = 2
N - R = 2 (nodes can be down and Riak can still
perform reads)
N - W = 2 (nodes that wil...
Riak Improvements




    R=W -- “read your writes consistency”
      R+W > N -- “strong consistency”
Riak Improvements


N can vary per bucket



        R=W -- “read your writes consistency”
          R+W > N -- “strong co...
Riak Improvements


N can vary per bucket
R and W can vary per operation


        R=W -- “read your writes consistency”
 ...
Setting N (replication factor)
Setting N (replication factor)

 PUT /riak/bucket
 Content-Type: application/json

 {“props”:{“n_val”:5}}
Setting N (replication factor)

 PUT /riak/bucket
 Content-Type: application/json

 {“props”:{“n_val”:5}}
 bucket.n_value ...
Request-time quorums
Request-time quorums


GET /riak/bucket/key?r=1
bucket.get(‘key’, :r => 1)
Request-time quorums


GET /riak/bucket/key?r=1
bucket.get(‘key’, :r => 1)
PUT /riak/bucket/key?w=4
object.store(:w => 4)
Other quorums
Other quorums


DW = durable writes (stored to disk)
Other quorums


DW = durable writes (stored to disk)
RW = quorum for deletes (delete is a write!)
LAB
LAB


Change the n_val for a bucket
LAB


Change the n_val for a bucket
Stop a node, test R/W quorums
Links
Links


Simple, one-way relationships between objects
Links


Simple, one-way relationships between objects
Like <a> or <link> tags in HTML
Links


Simple, one-way relationships between objects
Like <a> or <link> tags in HTML
Can be efficiently followed via “link...
The Link Header

     bucket       tag




          key
The Link Header

           bucket                    tag

Link: </riak/demo/test1>; riaktag=”userinfo”


                ...
Links in Ruby API
Links in Ruby API

 Create a link
 Riak::Link.new(“/riak/bucket/key”, “tag”)
Links in Ruby API

 Create a link
 Riak::Link.new(“/riak/bucket/key”, “tag”)

 Read an object’s links
 obj.links # Set<Ria...
Links in Ruby API

 Create a link
 Riak::Link.new(“/riak/bucket/key”, “tag”)

 Read an object’s links
 obj.links # Set<Ria...
Link-Walking (traversal)
Link-Walking (traversal)

 Ask Riak to “walk” a sequence of links filtered by
 bucket, tag, or a combination
Link-Walking (traversal)

 Ask Riak to “walk” a sequence of links filtered by
 bucket, tag, or a combination
 Optionally, c...
Link-Walking (traversal)

 Ask Riak to “walk” a sequence of links filtered by
 bucket, tag, or a combination
 Optionally, c...
Link-Walking (traversal)

 Ask Riak to “walk” a sequence of links filtered by
 bucket, tag, or a combination
 Optionally, c...
Link-Walking Example
Link-Walking Example

GET /riak/demo/test1/_,_,1

Start at demo/test1, follow all links and return the
objects

obj = clie...
Link-Walking Example
Link-Walking Example

GET /riak/demo/test1/demo,_,1

Start at demo/test1, follow all links pointing to the
demo bucket and...
Link-Walking Example
Link-Walking Example

GET /riak/demo/test1/_,friend,1

Start at demo/test1, follow all links tagged “friend”
and return th...
Link-Walking Example
Link-Walking Example

GET /riak/demo/test1/_,_,_/_,_,1

Start at demo/test1, follow all links, follow all links from
those...
LAB
LAB


Create a network of mutual friends using Ruby:
Justin, Andy, Bryan, Tony
LAB


Create a network of mutual friends using Ruby:
Justin, Andy, Bryan, Tony
Find all of Justin’s friends’ friends via c...
LAB


Create a network of mutual friends using Ruby:
Justin, Andy, Bryan, Tony
Find all of Justin’s friends’ friends via c...
Riak Map-Reduce
I believe I did, Bob.
Riak Map-Reduce
Riak Map-Reduce

Based on Google’s Map-Reduce idea
Riak Map-Reduce

Based on Google’s Map-Reduce idea
Some similarities to Hadoop and CouchDB
Riak Map-Reduce

Based on Google’s Map-Reduce idea
Some similarities to Hadoop and CouchDB
High data-locality
Riak Map-Reduce

Based on Google’s Map-Reduce idea
Some similarities to Hadoop and CouchDB
High data-locality
Phases can b...
Map-Reduce Terminology
Map-Reduce Terminology

Job: a query, composed of inputs and phases
Map-Reduce Terminology

Job: a query, composed of inputs and phases
Phase: a single map or reduce function application
Map-Reduce Terminology

Job: a query, composed of inputs and phases
Phase: a single map or reduce function application
Map...
Map-Reduce Terminology

Job: a query, composed of inputs and phases
Phase: a single map or reduce function application
Map...
Map Phases
Map Phases


Inputs are bucket-key pairs (with optional key-specific
data)
Map Phases


Inputs are bucket-key pairs (with optional key-specific
data)
Must return a list
Map Phases


Inputs are bucket-key pairs (with optional key-specific
data)
Must return a list
Parallel results are aggregat...
Map Built-ins
Map Built-ins


 Riak.mapValues
Map Built-ins


 Riak.mapValues
 Riak.mapValuesJson
Reduce Phases
Reduce Phases


Performed on a single node
Reduce Phases


Performed on a single node
Two processes per reduce phase increase parallelism
Reduce Phases


Performed on a single node
Two processes per reduce phase increase parallelism
Must return a list
Reduce Built-ins
Reduce Built-ins


 Riak.reduceMin
Reduce Built-ins


 Riak.reduceMin
 Riak.reduceMax
Reduce Built-ins


 Riak.reduceMin
 Riak.reduceMax
 Riak.reduceSort
Build a M/R Job
Build a M/R Job

Specify inputs
Build a M/R Job

Specify inputs
  bucket/key, bucket/key/key-specific-arg, bucket
Build a M/R Job

Specify inputs
  bucket/key, bucket/key/key-specific-arg, bucket
Specify phases
Build a M/R Job

Specify inputs
  bucket/key, bucket/key/key-specific-arg, bucket
Specify phases
  Each can receive a stati...
Build a M/R Job

Specify inputs
  bucket/key, bucket/key/key-specific-arg, bucket
Specify phases
  Each can receive a stati...
Map-Reduce on HTTP
Map-Reduce on HTTP


Job is a JSON object
Map-Reduce on HTTP


Job is a JSON object
POST /mapred
A simple M/R job
{“inputs”: “goog”,

“query”: [{“map”:

         {“language”:”javascript”,

          “name”: “Riak.mapVal...
A simple M/R job
{“inputs”: “goog”,

“query”: [{“map”:

         {“language”:”javascript”,

          “name”: “Riak.mapVal...
Another M/R Job
Another M/R Job
 {“inputs”: “goog”,
Another M/R Job
 {“inputs”: “goog”,
 “query”: [{“map”:{“language”:”javascript”,
Another M/R Job
 {“inputs”: “goog”,
 “query”: [{“map”:{“language”:”javascript”,
             “name”: “App.findHighGreater”,
Another M/R Job
 {“inputs”: “goog”,
 “query”: [{“map”:{“language”:”javascript”,
             “name”: “App.findHighGreater”,...
Another M/R Job
 {“inputs”: “goog”,
 “query”: [{“map”:{“language”:”javascript”,
             “name”: “App.findHighGreater”,...
Another M/R Job
 {“inputs”: “goog”,
 “query”: [{“map”:{“language”:”javascript”,
             “name”: “App.findHighGreater”,...
Another M/R Job
 {“inputs”: “goog”,
 “query”: [{“map”:{“language”:”javascript”,
             “name”: “App.findHighGreater”,...
Another M/R Job
 {“inputs”: “goog”,
 “query”: [{“map”:{“language”:”javascript”,
             “name”: “App.findHighGreater”,...
Another M/R Job
 {“inputs”: “goog”,
 “query”: [{“map”:{“language”:”javascript”,
             “name”: “App.findHighGreater”,...
LAB
LAB

Load the Google historical stock data
LAB

Load the Google historical stock data
Use Map-Reduce to:
LAB

Load the Google historical stock data
Use Map-Reduce to:
  Find the highest high price in the first week of March
LAB

Load the Google historical stock data
Use Map-Reduce to:
  Find the highest high price in the first week of March
  Fi...
Ripple
         gem install ripple
Ripple
              gem install ripple
Document-style persistence/modeling library
Ripple
              gem install ripple
Document-style persistence/modeling library
ActiveModel niceties
Ripple
              gem install ripple
Document-style persistence/modeling library
ActiveModel niceties
  Callbacks
Ripple
                gem install ripple
Document-style persistence/modeling library
ActiveModel niceties
  Callbacks
  V...
Ripple
                gem install ripple
Document-style persistence/modeling library
ActiveModel niceties
  Callbacks
  V...
Ripple Roadmap
Ripple Roadmap

Associations
Ripple Roadmap

Associations
Indexes
Ripple Roadmap

Associations
Indexes
Use a property/method as the key
Ripple Roadmap

Associations
Indexes
Use a property/method as the key
Dynamic finders
Ripple Roadmap

Associations
Indexes
Use a property/method as the key
Dynamic finders
Session store
Create a Ripple::Document
Create a Ripple::Document


class Person
 include Ripple::Document

 property :name, String, :presence => true
end
Sample app walkthrough
Sample app walkthrough



http://github.com/seancribbs/riak-url-shortener
Create a shortened URL
Create a shortened URL
post '/' do
Create a shortened URL
post '/' do
 client = Riak::Client.new
Create a shortened URL
post '/' do
 client = Riak::Client.new
 key = create_shortcode.call(params[:url])
Create a shortened URL
post '/' do
 client = Riak::Client.new
 key = create_shortcode.call(params[:url])
 bucket = Riak::B...
Create a shortened URL
post '/' do
 client = Riak::Client.new
 key = create_shortcode.call(params[:url])
 bucket = Riak::B...
Create a shortened URL
post '/' do
 client = Riak::Client.new
 key = create_shortcode.call(params[:url])
 bucket = Riak::B...
Create a shortened URL
post '/' do
 client = Riak::Client.new
 key = create_shortcode.call(params[:url])
 bucket = Riak::B...
Create a shortened URL
post '/' do
 client = Riak::Client.new
 key = create_shortcode.call(params[:url])
 bucket = Riak::B...
Create a shortened URL
post '/' do
 client = Riak::Client.new
 key = create_shortcode.call(params[:url])
 bucket = Riak::B...
Create a shortened URL
post '/' do
 client = Riak::Client.new
 key = create_shortcode.call(params[:url])
 bucket = Riak::B...
Embiggen the short URL
Embiggen the short URL
get '/:code' do
 begin
  client = Riak::Client.new
Embiggen the short URL
get '/:code' do
 begin
  client = Riak::Client.new
  obj = Riak::Bucket.new(client, 'urls').get(par...
Embiggen the short URL
get '/:code' do
 begin
  client = Riak::Client.new
  obj = Riak::Bucket.new(client, 'urls').get(par...
Embiggen the short URL
get '/:code' do
 begin
  client = Riak::Client.new
  obj = Riak::Bucket.new(client, 'urls').get(par...
Embiggen the short URL
get '/:code' do
 begin
  client = Riak::Client.new
  obj = Riak::Bucket.new(client, 'urls').get(par...
fin
sean@basho.com
                             @seancribbs
       “seancribbs” on Freenode IRC #riak




Questions?
         ...
Introduction to Riak - Red Dirt Ruby Conf Training
Introduction to Riak - Red Dirt Ruby Conf Training
Upcoming SlideShare
Loading in...5
×

Introduction to Riak - Red Dirt Ruby Conf Training

10,214

Published on

An introduction to the concepts behind Riak, Basho's distributed database, with a focus on using the database with Ruby.

Published in: Technology
0 Comments
8 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
10,214
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
215
Comments
0
Likes
8
Embeds 0
No embeds

No notes for slide









































































































































































































































  • Transcript of "Introduction to Riak - Red Dirt Ruby Conf Training"

    1. 1. Introduction to Riak Sean Cribbs basho
    2. 2. system “whoami”
    3. 3. system “whoami” BCS (Tulsa), three years as a musician
    4. 4. system “whoami” BCS (Tulsa), three years as a musician Started with Ruby in early 2006
    5. 5. system “whoami” BCS (Tulsa), three years as a musician Started with Ruby in early 2006 Rails freelancer 2007-2010
    6. 6. system “whoami” BCS (Tulsa), three years as a musician Started with Ruby in early 2006 Rails freelancer 2007-2010 Radiant CMS
    7. 7. system “whoami” BCS (Tulsa), three years as a musician Started with Ruby in early 2006 Rails freelancer 2007-2010 Radiant CMS March 2010 - Developer Advocate basho
    8. 8. Rails Can’t Scale
    9. 9. Rails Can’t Scale what does it mean?
    10. 10. Ruby Rails Can’t Scale what does it mean?
    11. 11. MySQL Ruby Rails Can’t Scale what does it mean?
    12. 12. insert straw man here MySQL Ruby Rails Can’t Scale what does it mean?
    13. 13. Mythbusting “scalability”
    14. 14. Mythbusting “scalability” Scalability is not a yes/no question
    15. 15. Mythbusting “scalability” Scalability is not a yes/no question It’s a ratio of benefit to cost
    16. 16. Mythbusting “scalability” Scalability is not a yes/no question It’s a ratio of benefit to cost Benefits: low latency, throughput, uptime, concurrency, reliability
    17. 17. Mythbusting “scalability” Scalability is not a yes/no question It’s a ratio of benefit to cost Benefits: low latency, throughput, uptime, concurrency, reliability Costs: CPU, RAM, disk, bandwidth, power, hw/sw
    18. 18. Mythbusting “scalability” Scalability is not a yes/no question It’s a ratio of benefit to cost Benefits: low latency, throughput, uptime, concurrency, reliability Costs: CPU, RAM, disk, bandwidth, power, hw/sw scalability = bang for your buck (ROI)
    19. 19. Scaling goes both ways
    20. 20. Scaling goes both ways Up/Out - high traffic, “Big Data”, multi-datacenter
    21. 21. Scaling goes both ways Up/Out - high traffic, “Big Data”, multi-datacenter Down/In - laptop, set-top, mobile
    22. 22. How do you scale?
    23. 23. How do you scale? Vertically - get bigger, expensive machines
    24. 24. How do you scale? Vertically - get bigger, expensive machines Horizontally - get more commodity machines
    25. 25. What is Riak? (the horizontal scaling bits)
    26. 26. What is Riak? (the horizontal scaling bits) Based on Amazon’s Dynamo (2007)
    27. 27. What is Riak? (the horizontal scaling bits) Based on Amazon’s Dynamo (2007) key-value storage
    28. 28. What is Riak? (the horizontal scaling bits) Based on Amazon’s Dynamo (2007) key-value storage masterless, peer-to-peer replication
    29. 29. What is Riak? (the horizontal scaling bits) Based on Amazon’s Dynamo (2007) key-value storage masterless, peer-to-peer replication consistent hashing
    30. 30. What is Riak? (the horizontal scaling bits) Based on Amazon’s Dynamo (2007) key-value storage masterless, peer-to-peer replication consistent hashing eventual consistency
    31. 31. What is Riak? (the horizontal scaling bits) Based on Amazon’s Dynamo (2007) key-value storage masterless, peer-to-peer replication consistent hashing eventual consistency failover - quorums, hinted handoff
    32. 32. “O/RM is the Vietnam of Computer Science.” -- Ted Neward, 2004/6
    33. 33. “O/RM is the Vietnam of Computer Science.” -- Ted Neward, 2004/6 slippery slope
    34. 34. “O/RM is the Vietnam of Computer Science.” -- Ted Neward, 2004/6 slippery slope diminishing returns
    35. 35. Impedance mismatch
    36. 36. Impedance mismatch Relational = predicate logic, truth statements
    37. 37. Impedance mismatch Relational = predicate logic, truth statements Object = identity, state, behavior, encapsulation
    38. 38. Pick your poison
    39. 39. Pick your poison Make the objects fit the database
    40. 40. Pick your poison Make the objects fit the database Active Record
    41. 41. Pick your poison Make the objects fit the database Active Record Make the database fit the objects
    42. 42. Pick your poison Make the objects fit the database Active Record Make the database fit the objects OODBMS, Graph DBs
    43. 43. Middle ground
    44. 44. Middle ground Document databases (identity and state)
    45. 45. Middle ground Document databases (identity and state) No JOINs - denormalized / composed
    46. 46. Middle ground Document databases (identity and state) No JOINs - denormalized / composed Loosely structured
    47. 47. Middle ground Document databases (identity and state) No JOINs - denormalized / composed Loosely structured Friendly transport formats, e.g. JSON
    48. 48. What is Riak? (the document database bits)
    49. 49. What is Riak? (the document database bits) Store your objects as JSON (or any format)
    50. 50. What is Riak? (the document database bits) Store your objects as JSON (or any format) Link between objects (like hypertext)
    51. 51. What is Riak? (the document database bits) Store your objects as JSON (or any format) Link between objects (like hypertext) No SQL - query with Javascript Map-Reduce
    52. 52. DevOps - agile infrastructure
    53. 53. DevOps - agile infrastructure programming your infrastructure
    54. 54. DevOps - agile infrastructure programming your infrastructure better communication and planning
    55. 55. Befriend your sysadmin
    56. 56. Befriend your sysadmin Integrate with existing infrastructure
    57. 57. Befriend your sysadmin Integrate with existing infrastructure Reduce the amount of hands-on work
    58. 58. Befriend your sysadmin Integrate with existing infrastructure Reduce the amount of hands-on work Have a growth plan
    59. 59. What is Riak? (the ops-friendly bits)
    60. 60. What is Riak? (the ops-friendly bits) Web-shaped storage
    61. 61. What is Riak? (the ops-friendly bits) Web-shaped storage Store data in its original format
    62. 62. What is Riak? (the ops-friendly bits) Web-shaped storage Store data in its original format It’s just HTTP - same techniques apply
    63. 63. What is Riak? (the ops-friendly bits) Web-shaped storage Store data in its original format It’s just HTTP - same techniques apply load balancing, proxy caches, round-robin DNS
    64. 64. What is Riak? (the ops-friendly bits) Web-shaped storage Store data in its original format It’s just HTTP - same techniques apply load balancing, proxy caches, round-robin DNS No node is special - grow horizontally
    65. 65. What is Riak? (the ops-friendly bits) Web-shaped storage Store data in its original format It’s just HTTP - same techniques apply load balancing, proxy caches, round-robin DNS No node is special - grow horizontally Get some sleep, fix it in the morning
    66. 66. To review, Riak is...
    67. 67. To review, Riak is... Magical Horizontally- Scaling Unicorns
    68. 68. To review, Riak is... Magical Horizontally- Scaling Unicorns Application-Friendly Rainbows in the Cloud
    69. 69. To review, Riak is... Magical Horizontally- Scaling Unicorns Application-Friendly Rainbows in the Cloud Data-Shredding MapReduce Ninjas
    70. 70. soapbox do
    71. 71. http://www.flickr.com/photos/mullica/2769082212/
    72. 72. http://www.flickr.com/photos/bike/236125877/ Stop Cargo-Culting You are not 37signals, Twitter, or github.
    73. 73. http://www.flickr.com/photos/library_of_virginia/2898496299/ Ignore the Salesperson Do your own evaluation. Don’t parrot the hype.
    74. 74. http://bit.ly/cGVPv7 Understand your Data One size does not fit all. Give up your crutches.
    75. 75. Plan for Failure Your code is not perfect. Your server will go down.
    76. 76. http://www.solarnavigator.net/animal_kingdom/humans/simon_hall.htm Take Responsibility Own your choice. Understand the consequences.
    77. 77. end
    78. 78. Getting Started with Riak http://192.168.0.87/~sean/riak-training/
    79. 79. Starting up a cluster
    80. 80. Starting up a cluster make all devrel
    81. 81. Starting up a cluster make all devrel dev{1,2,3}/bin/riak start
    82. 82. Starting up a cluster make all devrel dev{1,2,3}/bin/riak start dev{2,3}/bin/riak-admin join dev1@127.0.0.1
    83. 83. Riak CRUD http://127.0.0.1:8091/
    84. 84. Riak CRUD http://127.0.0.1:8091/ POST /riak/bucket (C - random key)
    85. 85. Riak CRUD http://127.0.0.1:8091/ POST /riak/bucket (C - random key) GET /riak/bucket/key (R)
    86. 86. Riak CRUD http://127.0.0.1:8091/ POST /riak/bucket (C - random key) GET /riak/bucket/key (R) PUT /riak/bucket/key (U,C - known key)
    87. 87. Riak CRUD http://127.0.0.1:8091/ POST /riak/bucket (C - random key) GET /riak/bucket/key (R) PUT /riak/bucket/key (U,C - known key) DELETE /riak/bucket/key (D)
    88. 88. gem install riak-client http://192.168.0.87/~sean/riak-training/
    89. 89. require ‘riak’
    90. 90. require ‘riak’ Make a client object client = Riak::Client.new
    91. 91. require ‘riak’ Make a client object client = Riak::Client.new Get a bucket bucket = client.bucket(‘foo’) # Riak::Bucket
    92. 92. require ‘riak’ Make a client object client = Riak::Client.new Get a bucket bucket = client.bucket(‘foo’) # Riak::Bucket Get an object from the bucket obj = bucket.get(‘bar’) # Riak::RObject
    93. 93. require ‘riak’ Make a client object client = Riak::Client.new Get a bucket bucket = client.bucket(‘foo’) # Riak::Bucket Get an object from the bucket obj = bucket.get(‘bar’) # Riak::RObject Initialize a new object obj = bucket.new(‘baz’)
    94. 94. Riak::RObject
    95. 95. Riak::RObject Get/set object key obj.key = “bar”
    96. 96. Riak::RObject Get/set object key obj.key = “bar” Get/set content-type obj.content_type = ‘application/json’
    97. 97. Riak::RObject Get/set object key obj.key = “bar” Get/set content-type obj.content_type = ‘application/json’ Get/set the object body data (JSON auto enc/dec) obj.data = {“name” => “Sean”}
    98. 98. Riak::RObject Get/set object key obj.key = “bar” Get/set content-type obj.content_type = ‘application/json’ Get/set the object body data (JSON auto enc/dec) obj.data = {“name” => “Sean”} Store the object obj.store
    99. 99. LAB
    100. 100. LAB Build Riak 3-node developer setup (install Erlang as necessary)
    101. 101. LAB Build Riak 3-node developer setup (install Erlang as necessary) Store an image in Riak via REST API with curl
    102. 102. LAB Build Riak 3-node developer setup (install Erlang as necessary) Store an image in Riak via REST API with curl Store a JSON object via Ruby client
    103. 103. Riak Influences
    104. 104. Riak Influences CAP Theorem
    105. 105. Riak Influences CAP Theorem Amazon Dynamo Paper
    106. 106. Riak Influences CAP Theorem Amazon Dynamo Paper Operational experience running large networks
    107. 107. CAP Theorem
    108. 108. CAP Theorem Consistency - globally consistent state
    109. 109. CAP Theorem Consistency - globally consistent state Availability - system accepts reads and writes
    110. 110. CAP Theorem Consistency - globally consistent state Availability - system accepts reads and writes Partition Tolerance - system handles network failure
    111. 111. CAP: Pick two
    112. 112. Riak: Pick two... for each operation
    113. 113. Amazon Dynamo
    114. 114. Amazon Dynamo originally for their shopping cart storage
    115. 115. Amazon Dynamo originally for their shopping cart storage masterless, peer-to-peer replication
    116. 116. Amazon Dynamo originally for their shopping cart storage masterless, peer-to-peer replication evenly-distributed key space “ring” (consistent hashing)
    117. 117. Amazon Dynamo originally for their shopping cart storage masterless, peer-to-peer replication evenly-distributed key space “ring” (consistent hashing) eventually consistent (AP)
    118. 118. Amazon Dynamo originally for their shopping cart storage masterless, peer-to-peer replication evenly-distributed key space “ring” (consistent hashing) eventually consistent (AP) robust failure tolerance
    119. 119. Amazon Dynamo originally for their shopping cart storage masterless, peer-to-peer replication evenly-distributed key space “ring” (consistent hashing) eventually consistent (AP) robust failure tolerance hinted handoff
    120. 120. Dynamo Quorums
    121. 121. Dynamo Quorums N = number of replicas
    122. 122. Dynamo Quorums N = number of replicas R = quorum for a successful read
    123. 123. Dynamo Quorums N = number of replicas R = quorum for a successful read W = quorum for a successful write
    124. 124. Dynamo Math
    125. 125. Dynamo Math N - R = read fault tolerance
    126. 126. Dynamo Math N - R = read fault tolerance N - W = write fault tolerance
    127. 127. Dynamo Math
    128. 128. Dynamo Math N = 4, W = 2, R = 2
    129. 129. Dynamo Math N = 4, W = 2, R = 2 N - R = 2 (nodes can be down and Riak can still perform reads)
    130. 130. Dynamo Math N = 4, W = 2, R = 2 N - R = 2 (nodes can be down and Riak can still perform reads) N - W = 2 (nodes that will receive hinted writes)
    131. 131. Riak Improvements R=W -- “read your writes consistency” R+W > N -- “strong consistency”
    132. 132. Riak Improvements N can vary per bucket R=W -- “read your writes consistency” R+W > N -- “strong consistency”
    133. 133. Riak Improvements N can vary per bucket R and W can vary per operation R=W -- “read your writes consistency” R+W > N -- “strong consistency”
    134. 134. Setting N (replication factor)
    135. 135. Setting N (replication factor) PUT /riak/bucket Content-Type: application/json {“props”:{“n_val”:5}}
    136. 136. Setting N (replication factor) PUT /riak/bucket Content-Type: application/json {“props”:{“n_val”:5}} bucket.n_value = 5
    137. 137. Request-time quorums
    138. 138. Request-time quorums GET /riak/bucket/key?r=1 bucket.get(‘key’, :r => 1)
    139. 139. Request-time quorums GET /riak/bucket/key?r=1 bucket.get(‘key’, :r => 1) PUT /riak/bucket/key?w=4 object.store(:w => 4)
    140. 140. Other quorums
    141. 141. Other quorums DW = durable writes (stored to disk)
    142. 142. Other quorums DW = durable writes (stored to disk) RW = quorum for deletes (delete is a write!)
    143. 143. LAB
    144. 144. LAB Change the n_val for a bucket
    145. 145. LAB Change the n_val for a bucket Stop a node, test R/W quorums
    146. 146. Links
    147. 147. Links Simple, one-way relationships between objects
    148. 148. Links Simple, one-way relationships between objects Like <a> or <link> tags in HTML
    149. 149. Links Simple, one-way relationships between objects Like <a> or <link> tags in HTML Can be efficiently followed via “link-walking”
    150. 150. The Link Header bucket tag key
    151. 151. The Link Header bucket tag Link: </riak/demo/test1>; riaktag=”userinfo” key
    152. 152. Links in Ruby API
    153. 153. Links in Ruby API Create a link Riak::Link.new(“/riak/bucket/key”, “tag”)
    154. 154. Links in Ruby API Create a link Riak::Link.new(“/riak/bucket/key”, “tag”) Read an object’s links obj.links # Set<Riak::Link>
    155. 155. Links in Ruby API Create a link Riak::Link.new(“/riak/bucket/key”, “tag”) Read an object’s links obj.links # Set<Riak::Link> Convert an object to a link obj.links << obj2.to_link(“next”) obj.store
    156. 156. Link-Walking (traversal)
    157. 157. Link-Walking (traversal) Ask Riak to “walk” a sequence of links filtered by bucket, tag, or a combination
    158. 158. Link-Walking (traversal) Ask Riak to “walk” a sequence of links filtered by bucket, tag, or a combination Optionally, collect results along the way and return them
    159. 159. Link-Walking (traversal) Ask Riak to “walk” a sequence of links filtered by bucket, tag, or a combination Optionally, collect results along the way and return them Can be arbitrarily deep
    160. 160. Link-Walking (traversal) Ask Riak to “walk” a sequence of links filtered by bucket, tag, or a combination Optionally, collect results along the way and return them Can be arbitrarily deep Response is doubly-nested multipart/mixed riak-client handles this for you - Array of Arrays of RObjects
    161. 161. Link-Walking Example
    162. 162. Link-Walking Example GET /riak/demo/test1/_,_,1 Start at demo/test1, follow all links and return the objects obj = client[‘demo’][‘test1’] obj.walk(:keep => true)
    163. 163. Link-Walking Example
    164. 164. Link-Walking Example GET /riak/demo/test1/demo,_,1 Start at demo/test1, follow all links pointing to the demo bucket and return the objects obj.walk(:bucket => “demo”, :keep => true)
    165. 165. Link-Walking Example
    166. 166. Link-Walking Example GET /riak/demo/test1/_,friend,1 Start at demo/test1, follow all links tagged “friend” and return the objects object.walk(:tag => ‘friend’, :keep => true)
    167. 167. Link-Walking Example
    168. 168. Link-Walking Example GET /riak/demo/test1/_,_,_/_,_,1 Start at demo/test1, follow all links, follow all links from those, return everything from the last set obj.walk({},{:keep => true})
    169. 169. LAB
    170. 170. LAB Create a network of mutual friends using Ruby: Justin, Andy, Bryan, Tony
    171. 171. LAB Create a network of mutual friends using Ruby: Justin, Andy, Bryan, Tony Find all of Justin’s friends’ friends via curl
    172. 172. LAB Create a network of mutual friends using Ruby: Justin, Andy, Bryan, Tony Find all of Justin’s friends’ friends via curl Find all of Tony’s first and second-tier friends in Ruby
    173. 173. Riak Map-Reduce I believe I did, Bob.
    174. 174. Riak Map-Reduce
    175. 175. Riak Map-Reduce Based on Google’s Map-Reduce idea
    176. 176. Riak Map-Reduce Based on Google’s Map-Reduce idea Some similarities to Hadoop and CouchDB
    177. 177. Riak Map-Reduce Based on Google’s Map-Reduce idea Some similarities to Hadoop and CouchDB High data-locality
    178. 178. Riak Map-Reduce Based on Google’s Map-Reduce idea Some similarities to Hadoop and CouchDB High data-locality Phases can be Javascript or Erlang
    179. 179. Map-Reduce Terminology
    180. 180. Map-Reduce Terminology Job: a query, composed of inputs and phases
    181. 181. Map-Reduce Terminology Job: a query, composed of inputs and phases Phase: a single map or reduce function application
    182. 182. Map-Reduce Terminology Job: a query, composed of inputs and phases Phase: a single map or reduce function application Map: phase applied to each item - filter, transform
    183. 183. Map-Reduce Terminology Job: a query, composed of inputs and phases Phase: a single map or reduce function application Map: phase applied to each item - filter, transform Reduce: phase applied to the collection - collate, aggregate, compute
    184. 184. Map Phases
    185. 185. Map Phases Inputs are bucket-key pairs (with optional key-specific data)
    186. 186. Map Phases Inputs are bucket-key pairs (with optional key-specific data) Must return a list
    187. 187. Map Phases Inputs are bucket-key pairs (with optional key-specific data) Must return a list Parallel results are aggregated
    188. 188. Map Built-ins
    189. 189. Map Built-ins Riak.mapValues
    190. 190. Map Built-ins Riak.mapValues Riak.mapValuesJson
    191. 191. Reduce Phases
    192. 192. Reduce Phases Performed on a single node
    193. 193. Reduce Phases Performed on a single node Two processes per reduce phase increase parallelism
    194. 194. Reduce Phases Performed on a single node Two processes per reduce phase increase parallelism Must return a list
    195. 195. Reduce Built-ins
    196. 196. Reduce Built-ins Riak.reduceMin
    197. 197. Reduce Built-ins Riak.reduceMin Riak.reduceMax
    198. 198. Reduce Built-ins Riak.reduceMin Riak.reduceMax Riak.reduceSort
    199. 199. Build a M/R Job
    200. 200. Build a M/R Job Specify inputs
    201. 201. Build a M/R Job Specify inputs bucket/key, bucket/key/key-specific-arg, bucket
    202. 202. Build a M/R Job Specify inputs bucket/key, bucket/key/key-specific-arg, bucket Specify phases
    203. 203. Build a M/R Job Specify inputs bucket/key, bucket/key/key-specific-arg, bucket Specify phases Each can receive a static argument
    204. 204. Build a M/R Job Specify inputs bucket/key, bucket/key/key-specific-arg, bucket Specify phases Each can receive a static argument Each can return intermediate results
    205. 205. Map-Reduce on HTTP
    206. 206. Map-Reduce on HTTP Job is a JSON object
    207. 207. Map-Reduce on HTTP Job is a JSON object POST /mapred
    208. 208. A simple M/R job {“inputs”: “goog”, “query”: [{“map”: {“language”:”javascript”, “name”: “Riak.mapValuesJson”, “keep”: true}]}
    209. 209. A simple M/R job {“inputs”: “goog”, “query”: [{“map”: {“language”:”javascript”, “name”: “Riak.mapValuesJson”, “keep”: true}]} Riak::MapReduce.new(c).add(‘goog’). map(‘Riak.mapValuesJson’, :keep => true).run
    210. 210. Another M/R Job
    211. 211. Another M/R Job {“inputs”: “goog”,
    212. 212. Another M/R Job {“inputs”: “goog”, “query”: [{“map”:{“language”:”javascript”,
    213. 213. Another M/R Job {“inputs”: “goog”, “query”: [{“map”:{“language”:”javascript”, “name”: “App.findHighGreater”,
    214. 214. Another M/R Job {“inputs”: “goog”, “query”: [{“map”:{“language”:”javascript”, “name”: “App.findHighGreater”, “arg”: 600.0,
    215. 215. Another M/R Job {“inputs”: “goog”, “query”: [{“map”:{“language”:”javascript”, “name”: “App.findHighGreater”, “arg”: 600.0, “keep”: false},
    216. 216. Another M/R Job {“inputs”: “goog”, “query”: [{“map”:{“language”:”javascript”, “name”: “App.findHighGreater”, “arg”: 600.0, “keep”: false}, {“reduce”:{“language”:”javascript,
    217. 217. Another M/R Job {“inputs”: “goog”, “query”: [{“map”:{“language”:”javascript”, “name”: “App.findHighGreater”, “arg”: 600.0, “keep”: false}, {“reduce”:{“language”:”javascript, “name”: “Riak.reduceMax”,
    218. 218. Another M/R Job {“inputs”: “goog”, “query”: [{“map”:{“language”:”javascript”, “name”: “App.findHighGreater”, “arg”: 600.0, “keep”: false}, {“reduce”:{“language”:”javascript, “name”: “Riak.reduceMax”, “keep”: true}]}
    219. 219. Another M/R Job {“inputs”: “goog”, “query”: [{“map”:{“language”:”javascript”, “name”: “App.findHighGreater”, “arg”: 600.0, “keep”: false}, {“reduce”:{“language”:”javascript, “name”: “Riak.reduceMax”, “keep”: true}]} Riak::MapReduce.new(c).add(‘goog’). map(‘App.findHighGreater’, :arg => 600.0). reduce(“Riak.reduceMax”, :keep => true).run
    220. 220. LAB
    221. 221. LAB Load the Google historical stock data
    222. 222. LAB Load the Google historical stock data Use Map-Reduce to:
    223. 223. LAB Load the Google historical stock data Use Map-Reduce to: Find the highest high price in the first week of March
    224. 224. LAB Load the Google historical stock data Use Map-Reduce to: Find the highest high price in the first week of March Find the day with the widest price range since the beginning of the year
    225. 225. Ripple gem install ripple
    226. 226. Ripple gem install ripple Document-style persistence/modeling library
    227. 227. Ripple gem install ripple Document-style persistence/modeling library ActiveModel niceties
    228. 228. Ripple gem install ripple Document-style persistence/modeling library ActiveModel niceties Callbacks
    229. 229. Ripple gem install ripple Document-style persistence/modeling library ActiveModel niceties Callbacks Validations
    230. 230. Ripple gem install ripple Document-style persistence/modeling library ActiveModel niceties Callbacks Validations ActionPack compatibility
    231. 231. Ripple Roadmap
    232. 232. Ripple Roadmap Associations
    233. 233. Ripple Roadmap Associations Indexes
    234. 234. Ripple Roadmap Associations Indexes Use a property/method as the key
    235. 235. Ripple Roadmap Associations Indexes Use a property/method as the key Dynamic finders
    236. 236. Ripple Roadmap Associations Indexes Use a property/method as the key Dynamic finders Session store
    237. 237. Create a Ripple::Document
    238. 238. Create a Ripple::Document class Person include Ripple::Document property :name, String, :presence => true end
    239. 239. Sample app walkthrough
    240. 240. Sample app walkthrough http://github.com/seancribbs/riak-url-shortener
    241. 241. Create a shortened URL
    242. 242. Create a shortened URL post '/' do
    243. 243. Create a shortened URL post '/' do client = Riak::Client.new
    244. 244. Create a shortened URL post '/' do client = Riak::Client.new key = create_shortcode.call(params[:url])
    245. 245. Create a shortened URL post '/' do client = Riak::Client.new key = create_shortcode.call(params[:url]) bucket = Riak::Bucket.new(client, 'urls')
    246. 246. Create a shortened URL post '/' do client = Riak::Client.new key = create_shortcode.call(params[:url]) bucket = Riak::Bucket.new(client, 'urls') Riak::RObject.new(bucket, key).tap do |obj|
    247. 247. Create a shortened URL post '/' do client = Riak::Client.new key = create_shortcode.call(params[:url]) bucket = Riak::Bucket.new(client, 'urls') Riak::RObject.new(bucket, key).tap do |obj| obj.content_type = "text/plain"
    248. 248. Create a shortened URL post '/' do client = Riak::Client.new key = create_shortcode.call(params[:url]) bucket = Riak::Bucket.new(client, 'urls') Riak::RObject.new(bucket, key).tap do |obj| obj.content_type = "text/plain" obj.data = params[:url]
    249. 249. Create a shortened URL post '/' do client = Riak::Client.new key = create_shortcode.call(params[:url]) bucket = Riak::Bucket.new(client, 'urls') Riak::RObject.new(bucket, key).tap do |obj| obj.content_type = "text/plain" obj.data = params[:url] obj.store
    250. 250. Create a shortened URL post '/' do client = Riak::Client.new key = create_shortcode.call(params[:url]) bucket = Riak::Bucket.new(client, 'urls') Riak::RObject.new(bucket, key).tap do |obj| obj.content_type = "text/plain" obj.data = params[:url] obj.store end
    251. 251. Create a shortened URL post '/' do client = Riak::Client.new key = create_shortcode.call(params[:url]) bucket = Riak::Bucket.new(client, 'urls') Riak::RObject.new(bucket, key).tap do |obj| obj.content_type = "text/plain" obj.data = params[:url] obj.store end status 201 @url = "http://#{request.host_with_port}/#{key}" headers "Location" => @url haml :created end
    252. 252. Embiggen the short URL
    253. 253. Embiggen the short URL get '/:code' do begin client = Riak::Client.new
    254. 254. Embiggen the short URL get '/:code' do begin client = Riak::Client.new obj = Riak::Bucket.new(client, 'urls').get(params[:code])
    255. 255. Embiggen the short URL get '/:code' do begin client = Riak::Client.new obj = Riak::Bucket.new(client, 'urls').get(params[:code]) url = obj.data
    256. 256. Embiggen the short URL get '/:code' do begin client = Riak::Client.new obj = Riak::Bucket.new(client, 'urls').get(params[:code]) url = obj.data halt 301, {"Location" => url}, []
    257. 257. Embiggen the short URL get '/:code' do begin client = Riak::Client.new obj = Riak::Bucket.new(client, 'urls').get(params[:code]) url = obj.data halt 301, {"Location" => url}, [] rescue Riak::FailedRequest => fr case fr.code when 404 not_found(haml(:not_found)) when 500..599 error(503, haml(:error)) end end end
    258. 258. fin
    259. 259. sean@basho.com @seancribbs “seancribbs” on Freenode IRC #riak Questions? http://wiki.basho.com riak-users@lists.basho.com
    1. A particular slide catching your eye?

      Clipping is a handy way to collect important slides you want to go back to later.

    ×