SlideShare a Scribd company logo
1 of 117
Embracing NoSQL
  Your First Cassandra Project


      #embracingnosql
       @mwynholds
         @rudy
          @rk
Goal
Goal

By the time you leave
  here, you will be
 comfortable using
 Cassandra in Rails
GENERALIZATION WARNING:
  PRESENTATION CAN CAUSE
   BROAD SIMPLIFICATIONS,
OPINIONS, NIT-PICKING, AND MAY
   COMPLICATE PROGRESS.
Schedule
• 3:30 - 5:00 Hands On Workshop
  • Introduction
  • Setup
  • Reading and Writing
  • Timeline
  • ORM
  • Denormalization
• After 5ish - Panel Q&A
Why NoSQL?

Scalability for the
   social web
CAP
CAP
Consistency
CAP
Consistency




              Availability
CAP
            Consistency




Partition
                          Availability
Tolerance
CAP
            Consistency




Partition
                          Availability
Tolerance

  You can only have two at a time!
CAP
     C




P         A
CAP
           C

MongoDB
 HBase
 Redis

   P            A
CAP
           C

MongoDB
                MySQL
 HBase
                Postgres
 Redis

   P               A
CAP
            C

MongoDB
                    MySQL
 HBase
                    Postgres
 Redis

   P                   A
          CouchDB
            Riak
CAP
              C

MongoDB
                       MySQL
 HBase
                       Postgres
 Redis

   P                      A
          CouchDB
             Riak
          Cassandra!
Cassandra
Cassandra


http://cassandra.apache.org
Column Oriented
123
        date:
       1/23/11
                    title:
                   My Title
                                  url:
                                http://...
                                               user:
                                               rudy
                                                        ...
546
         body:
       Lipsum...
                    date:
                   3/13/11
                                 status:
                                pending
                                               title:
                                               Foo
                                                          user:
                                                          jared
                                                                  ...
680     date:
       1/23/11
                     url:
                   http://...
                                 user:
                                  rob
                                             ...
791      body:
       Lipsum...
                    date:
                   3/13/11
                                  title:
                                   Bar
                                               user:
                                               mike
                                                        ...
Decentralized &
 Distributed
Decentralized &
 Distributed
      Node
Decentralized &
 Distributed
        Node




 Node          Node




        Node
Decentralized &
 Distributed
Sync    Node
               Sync


 Node           Node




        Node
Sync           Sync
Decentralized &
         Distributed
        Sync    Node
                       Sync
Write
         Node           Node




                Node
        Sync           Sync
Decentralized &
         Distributed
        Sync    Node
                       Sync
Write
         Node           Node


                               Read
                Node
        Sync           Sync
Tunably Consistent

Write

               ONE
                         Read
Tunably Consistent
          where n = replication factor


Write
                  QUORUM
                   (2n +1)
                                         Read
Tunably Consistent

Write

                ALL
                         Read
So How Much Faster Is
     Cassandra?
So How Much Faster Is
     Cassandra?



   
So How Much Faster Is
     Cassandra?



   
No Really, how fast?
No Really, how fast?
w/ 50GB   MySql   Cassandra


 Write    300ms    0.12ms


 Read     350ms     15ms
First NoSQL Rule
First NoSQL Rule


Don’t Use NoSQL
  Right Away!
Build Your
 Application First,
THEN Use NoSQL
   As Needed!
What We’re Building
      Today
What We’re Building
      Today
          Reddit
What We’re Building
      Today
          Reddit
   +       Digg
What We’re Building
      Today
           Reddit
   +          Digg
   -   Quite a Lot
What We’re Building
      Today
         Reddit
   +        Digg
   - Quite a Lot
   DUGGIT!
Login
Submit Links
Vote on Links
LAB: Installation

• Install Cassandra
• Start it up
• Command line interface
• Shut it down
Lexicon
Database       Keyspace




  Tables
                Column Families
Rows and Columns
         date:       title:        url:
  123
        1/23/11     My Title     http://...



          body:      date:        status:     title:
  546
        Lipsum...   3/13/11      pending      Foo



  680    date:        url:
        1/23/11     http://...



          body:      date:         title:
  791
        Lipsum...   3/13/11         Bar
Rows and Columns
         date:       title:        url:
  123
        1/23/11     My Title     http://...    Row

          body:      date:        status:     title:
  546
        Lipsum...   3/13/11      pending      Foo



  680    date:        url:
        1/23/11     http://...



          body:      date:         title:
  791
        Lipsum...   3/13/11         Bar
Rows and Columns
               date:       title:        url:
        123
              1/23/11     My Title     http://...    Row

                body:      date:        status:     title:
        546
              Lipsum...   3/13/11      pending      Foo


Row     680    date:        url:
Key           1/23/11     http://...



                body:      date:         title:
        791
              Lipsum...   3/13/11         Bar
Rows and Columns
               date:       title:        url:
        123
              1/23/11     My Title     http://...    Row

                body:      date:        status:     title:
        546
              Lipsum...   3/13/11      pending      Foo


Row     680    date:        url:
                                             Column
Key           1/23/11     http://...



                body:      date:         title:
        791
              Lipsum...   3/13/11         Bar
In SQL Columns Exist
   for Every Row ...
id     title      body        url      date      user

123   My Title              http://... 1/23/11   rudy

456     Foo      Lipsum..            3/13/11     jared

680                         http://... 1/23/11   rob

791     Bar      Lipsum..            3/13/11     mike
... But NOT in Column
        Families!
       date:       title:        url:       user:
123
      1/23/11     My Title     http://...   rudy



        body:      date:         title:     user:
546
      Lipsum...   3/13/11        Foo        jared



680    date:        url:        user:
      1/23/11     http://...     rob



        body:      date:         title:     user:
791
      Lipsum...   3/13/11         Bar       mike
In SQL New Columns
Require ALTER TABLE...
 id   title      body         url        date      user status

123   My Title              http://...   1/23/11   rudy


456     Foo      Lipsum..                3/13/11   jared   pending


680                         http://...   1/23/11   rob


791     Bar      Lipsum..                3/13/11   mike
... But Are Simple
Writes in Cassandra!
       date:       title:        url:       user:
123
      1/23/11     My Title     http://...   rudy



        body:      date:        status:     title:   user:
546
      Lipsum...   3/13/11      pending      Foo      jared



680    date:        url:        user:
      1/23/11     http://...     rob



        body:      date:         title:     user:
791
      Lipsum...   3/13/11         Bar       mike
What’s a Column?

 user:     Column Name

 rudy         Value
What’s a Column?

 user:     Column Name

 rudy         Value

 1234       Timestamp
Columns are Ordered

        body:      date:    title:   user:
546
      Lipsum...   3/13/11   Foo      jared
Columns are Ordered

        body:      date:     status:   title:   user:
546
      Lipsum...   3/13/11   pending    Foo      jared
Name can be Anything!
           body:      date:       status:     title:     user:
 546
         Lipsum...   3/13/11     pending      Foo        jared




         11/11/03:   11/12/03:   11/13/03:   11/14/03:
 rudy      Party     Recover       Panel      Return




           123:        456:        680:        791:
c4af67
            7           0           2           5
PATTERN: Simple Index
          f(x, y) = z
        y1:   y2:   y3:
   x1
        z11   z12   z13



   x2         y2:         y4:
              z22         z24



        y1:         y3:   y4:
   x3
        z31         z33   z34
Duggit:Votes
f(link_id, user_id) = vote
        jared:           rob:   rudy:
 123
           1              -1     -1



 680             mike:   rob:
                  1       1



        jared:   mike:          rudy:
 791
          -1      1               1
LAB: Setup

• Create duggit keyspaces
• Create votes column family
• Create some sample data
Cassandra API




     Node
Cassandra API


     Thrift


      Node
Cassandra API
JAVA    Ruby       Python   WhatEvs


               Thrift


                Node
Use High Level Client
           cassandra

             Ruby

             Thrift


              Node



   github.com/fauna/cassandra
Connecting


con = Cassandra.new(keyspace, address)
Connecting


con = Cassandra.new('duggit', '127.0.0.1:9160')
Reading a Row


row = con.get(column_family, key)
Reading a Row

link_id = ‘123’
row = con.get(:votes, link_id)

url = row['url']
Reading Many Rows


results = con.multi_get(column_family, keys)
Reading Many Rows

link_ids = [‘123’, ‘456’]
results = con.multi_get :votes, keys

results.each do |key, row|
    row_key = key
    url = row['url']
end
Writing


con.insert(column_family, key, column_values)
Writing


link_id = ‘123’
vote = {user.id => vote_val}

con.insert :votes, link_id, vote
LAB: Simple Column
        Family
• Connect to Cassandra
• Rewrite Vote
• Rewrite Link#value
• Configure testing frameworks
Querying?


Not Really ...
Slice
con.get_columns(column_family,
               key,
               :columns => column_names


con.get_columns(:links,
               '546',
               :columns => ['date', 'user']

          body:      date:     status:   title:   user:
 546
        Lipsum...   3/13/11   pending    Foo      jared
Range
con.get(column_family,
        row_key,
        :start => start,
        :finish => finish)


con.get(:link, '546', :start => 'd', :finish => 'u')


          body:      date:     status:   title:   user:
 546
        Lipsum...   3/13/11   pending    Foo      jared
REMEMBER: Column
Names can Be Anything
           body:      date:       status:     title:     user:
 546
         Lipsum...   3/13/11     pending      Foo        jared




         11/11/03:   11/12/03:   11/13/03:   11/14/03:
 rudy      Party     Recover       Panel      Return




           123:        456:        680:        791:
c4af67
            7           0           2           5
PATTERN: Timeline
   Columns are timestamps
         rudy



         mike



         jared
PATTERN: Timeline
             Columns are timestamps
rudy: OHAI                 0330:
                   rudy
                           OHAI


                   mike



                   jared
PATTERN: Timeline
             Columns are timestamps
rudy: OHAI                 0330:
                   rudy
                           OHAI
mike: Hi

                   mike    0335:
                            Hi


                   jared
PATTERN: Timeline
             Columns are timestamps
rudy: OHAI                 0330:
                   rudy
                           OHAI
mike: Hi
jared:YO                   0335:
                   mike
                            Hi


                           0345:
                   jared
                            YO
PATTERN: Timeline
             Columns are timestamps
rudy: OHAI                 0330:   0346:
                   rudy
                           OHAI    HALP
mike: Hi
jared:YO                   0335:
                   mike
rudy:HALP                   Hi


                           0345:
                   jared
                            YO
PATTERN: Timeline
             Columns are timestamps
rudy: OHAI                 0330:   0346:   0415:
                   rudy
                           OHAI    HALP     PLZ
mike: Hi
jared:YO                   0335:
                   mike
rudy:HALP                   Hi

rudy: PLZ
                           0345:
                   jared
                            YO
PATTERN: Timeline
              Columns are timestamps
rudy: OHAI                  0330:   0346:   0415:
                    rudy
                            OHAI    HALP     PLZ
mike: Hi
jared:YO                    0335:
                    mike
rudy:HALP                    Hi

rudy: PLZ
                            0345:   0420:
                    jared
jared: RTFM                  YO     RTFM
PATTERN: Timeline
              Columns are timestamps
rudy: OHAI                  0330:   0346:   0415:
                    rudy
                            OHAI    HALP     PLZ
mike: Hi
jared:YO                    0335:
                    mike
rudy:HALP                    Hi

rudy: PLZ
                            0345:   0420:   0445:
                    jared
jared: RTFM                  YO     RTFM    NEWB

jared: NEWB
PATTERN: Timeline
              Columns are timestamps
rudy: OHAI                  0330:   0346:   0415:
                    rudy
                            OHAI    HALP     PLZ
mike: Hi
jared:YO                    0335:   0515:
                    mike
rudy:HALP                    Hi     LOL

rudy: PLZ
                            0345:   0420:   0445:
                    jared
jared: RTFM                  YO     RTFM    NEWB

jared: NEWB
mike: LOL
PATTERN: Timeline
              Columns are timestamps
rudy: OHAI                  0330:   0346:   0415:     0645:
                    rudy                            KTHXBAI
                            OHAI    HALP     PLZ
mike: Hi
jared:YO                    0335:   0515:
                    mike
rudy:HALP                    Hi     LOL

rudy: PLZ
                            0345:   0420:   0445:
                    jared
jared: RTFM                  YO     RTFM    NEWB

jared: NEWB
mike: LOL
rudy: KTHXBAI
Duggit: Users Links
        20110101:   20110214:   20110311:   20110313:
rudy      123         311         777         987



        20101211:   20110113:   20110225:   20110301    20110314:
jared
           4          202         456         531        1066



        20101231:   20110228:   20110304:
rob
           99         432         680



        20101211:   20101225:   20110307:   20110312:
mike                                          791
          500          53         696
“Pagination”
con.get ‘jared’, :count => 3, :reverse => true


         20101211:   20110113:   20110225:   20110301   20110314:
 jared                                         531
            4          202         456                   1066




con.get ‘jared’, :count => 3,
       :reverse => true, :start => 20110224


         20101211:   20110113:   20110225:   20110301   20110314:
 jared                                         531
            4          202         456                   1066
But What about Across
       Rows?
            20110101:   20110214:      20110311:    20110313:
 rudy                     311
              123                        777          987



            20101211:   2011013:       20110225:    20110301    20110314:
 jared                                                531
               4          202            456                     1066


                                    shuffle



20110214:   20110225:   20110301        20110311:   20110313:   20110314:
  311         456         531                777      987         1066
“All” Timeline
 All
        20101211:
           4
                    20101231:
                       99
                                20110101:
                                  123
                                            20110113:
                                              202
                                                        20110214:
                                                          311
                                                                    ...
        20110101:   20110214:   20110311:   20110313:
rudy                  311
          123                     777         987



        20101211:   20110113:   20110225:   20110301    20110314:
jared                                         531
           4          202         456                    1066


        20101231:   20110228:   20110304:
rob        99         432         680
The Balance
      rudy
       rob



All           mike




      jared
The Balance
      rudy
       rob



All           mike




      jared
Batch Writing

con.batch do

  con.insert :user_links, user.id, value

  con.insert :user_links, 'All', value

end
LAB: Timelines

• Create a user_links column family
• Write links to appropriate timelines
• Return the recent items
Still Hitting SQL
App   Cassandra   SQL
Pattern: ORM
            Row = Object
       Column = Object property

       date:       title:        url:       user:
123
      1/23/11     My Title     http://...   rudy



        body:      date:        status:     title:   user:
546
      Lipsum...   3/13/11      pending      Foo      jared



680    date:        url:        user:
      1/23/11     http://...     rob
Secondary Index
      Create an index on date column

        date:       title:        url:       user:
123
       1/23/11     My Title     http://...   rudy



         body:      date:        status:     title:   user:
546
       Lipsum...   3/13/11      pending      Foo      jared



680     date:        url:        user:
       1/23/11     http://...     rob
Secondary Index
       Query: where date = 1/23/11

        date:      title:        url:       user:
123
       1/23/11    My Title     http://...   rudy



        body:      date:        status:     title:   user:
546
      Lipsum...   3/13/11      pending      Foo      jared



680     date:       url:        user:
       1/23/11    http://...     rob
LAB: ORM


• Rewrite Link to save to Cassandra
• Update supporting models and controllers
Still Two Reads
App   Cassandra   Cassandra
What if it isn’t there?
What if it isn’t there?

Write
What if it isn’t there?

Write
What if it isn’t there?
                   Link.recent_ids

Write
What if it isn’t there?
                   Link.recent_ids

Write




                   Link.by_ids
PATTERN:
Denormalization
    Just like SQL:
Store it multiple times,
  multiple locations
Seen it before ...
 All
         20101211:
            4
                     20101231:
                        99
                                 20110101:
                                   123
                                             20110113:
                                               202
                                                         20110214:
                                                           311
                                                                     ...
         20110101:   20110214:   20110311:   20110313:
rudy                   311
           123                     777         987



         20101211:   20110113:   20110225:   20110301    20110314:
jared                                          531
            4          202         456                    1066


         20101231:   20110228:   20110304:
rob         99         432         680
But Different Column
 Family Structures?
 links
          date:       title:       url:        user:
   123
         1/23/11     My Title    http://...    rudy



 users_to_links
         20110101:   20110214:   20110311:    20110313:
  rudy                 311
           123                     777          987
Super-Column Families
 All    20101211:   20101231:   20110101:   20110113:   20110214:
                                                                    ...
rudy    20110313:   20110311:   20110214:   20110101:




jared   20110314:   20110301:   20110225:   20110113:   20101211:




 rob
        20110304:   20110228:   20101231:
Super-Column


                             date:     title:      url:       user:
20110314:   =   20110314:
                            1/23/11   My Title   http://...   rudy
Write Object to Each
uuid = SimpleUUID::UUID.new
@id = uuid.to_guid
value = { 'id' => @id, 'title' => @title, ... }
pointer = { uuid => value }

con.batch do
  con.insert :links, @id, value
  con.insert :user_links, @user_id.to_s, pointer
  con.insert :user_links, 'all', pointer
end
LAB: Denormalize Links


• Rewrite Link#save
Resources
• Wiki: http://wiki.apache.org/cassandra/
• Mailing List: user@cassandra.apache.org
• “Cassandra: The Definitive Guide” by Eban
  Hewitt (@ebenhewitt)
• Presentations of Mike Malone
  (@mjmalone)
Advanced Topics

• Deployment
• Cassandra in the Cloud
• Row Partitioning
• Compound Keys
• Other Strategies

More Related Content

Similar to Embracing NoSQL - Your First Cassandra Project

zmq.rs - A brief history of concurrency in Rust
zmq.rs - A brief history of concurrency in Rustzmq.rs - A brief history of concurrency in Rust
zmq.rs - A brief history of concurrency in RustFantix King 王川
 
Craig Brown speaks on ElasticSearch
Craig Brown speaks on ElasticSearchCraig Brown speaks on ElasticSearch
Craig Brown speaks on ElasticSearchimarcticblue
 
Ruby semweb 2011-12-06
Ruby semweb 2011-12-06Ruby semweb 2011-12-06
Ruby semweb 2011-12-06Gregg Kellogg
 
Can we run the Whole Web on Apache Sling?
Can we run the Whole Web on Apache Sling?Can we run the Whole Web on Apache Sling?
Can we run the Whole Web on Apache Sling?Bertrand Delacretaz
 
Redis深入浅出
Redis深入浅出Redis深入浅出
Redis深入浅出ruoyi ruan
 
Strangers In The Night: Ruby, Rack y Sinatra - Herramientas potentes para con...
Strangers In The Night: Ruby, Rack y Sinatra - Herramientas potentes para con...Strangers In The Night: Ruby, Rack y Sinatra - Herramientas potentes para con...
Strangers In The Night: Ruby, Rack y Sinatra - Herramientas potentes para con...Alberto Perdomo
 
Node.js Explained
Node.js ExplainedNode.js Explained
Node.js ExplainedJeff Kunkle
 
MongoDB @ SourceForge
MongoDB @ SourceForgeMongoDB @ SourceForge
MongoDB @ SourceForgeiammutex
 
Spark Summit EU talk by Ross Lawley
Spark Summit EU talk by Ross LawleySpark Summit EU talk by Ross Lawley
Spark Summit EU talk by Ross LawleySpark Summit
 
How To Connect Spark To Your Own Datasource
How To Connect Spark To Your Own DatasourceHow To Connect Spark To Your Own Datasource
How To Connect Spark To Your Own DatasourceMongoDB
 
You got ur Erlang in my Ruby
You got ur Erlang in my RubyYou got ur Erlang in my Ruby
You got ur Erlang in my Rubyelliando dias
 
Zing Database – Distributed Key-Value Database
Zing Database – Distributed Key-Value DatabaseZing Database – Distributed Key-Value Database
Zing Database – Distributed Key-Value Databasezingopen
 
Zing Database
Zing Database Zing Database
Zing Database Long Dao
 
An introduction to Semantic Web and Linked Data
An introduction to Semantic Web and Linked DataAn introduction to Semantic Web and Linked Data
An introduction to Semantic Web and Linked DataFabien Gandon
 
Seastore: Next Generation Backing Store for Ceph
Seastore: Next Generation Backing Store for CephSeastore: Next Generation Backing Store for Ceph
Seastore: Next Generation Backing Store for CephScyllaDB
 

Similar to Embracing NoSQL - Your First Cassandra Project (20)

zmq.rs - A brief history of concurrency in Rust
zmq.rs - A brief history of concurrency in Rustzmq.rs - A brief history of concurrency in Rust
zmq.rs - A brief history of concurrency in Rust
 
Craig Brown speaks on ElasticSearch
Craig Brown speaks on ElasticSearchCraig Brown speaks on ElasticSearch
Craig Brown speaks on ElasticSearch
 
Ruby semweb 2011-12-06
Ruby semweb 2011-12-06Ruby semweb 2011-12-06
Ruby semweb 2011-12-06
 
Can we run the Whole Web on Apache Sling?
Can we run the Whole Web on Apache Sling?Can we run the Whole Web on Apache Sling?
Can we run the Whole Web on Apache Sling?
 
Git studynotes
Git studynotesGit studynotes
Git studynotes
 
skipfish
skipfishskipfish
skipfish
 
Linked Data on Rails
Linked Data on RailsLinked Data on Rails
Linked Data on Rails
 
Redis深入浅出
Redis深入浅出Redis深入浅出
Redis深入浅出
 
Strangers In The Night: Ruby, Rack y Sinatra - Herramientas potentes para con...
Strangers In The Night: Ruby, Rack y Sinatra - Herramientas potentes para con...Strangers In The Night: Ruby, Rack y Sinatra - Herramientas potentes para con...
Strangers In The Night: Ruby, Rack y Sinatra - Herramientas potentes para con...
 
Node.js Explained
Node.js ExplainedNode.js Explained
Node.js Explained
 
How MongoDB works
How MongoDB worksHow MongoDB works
How MongoDB works
 
MongoDB @ SourceForge
MongoDB @ SourceForgeMongoDB @ SourceForge
MongoDB @ SourceForge
 
linux-namespaces.pdf
linux-namespaces.pdflinux-namespaces.pdf
linux-namespaces.pdf
 
Spark Summit EU talk by Ross Lawley
Spark Summit EU talk by Ross LawleySpark Summit EU talk by Ross Lawley
Spark Summit EU talk by Ross Lawley
 
How To Connect Spark To Your Own Datasource
How To Connect Spark To Your Own DatasourceHow To Connect Spark To Your Own Datasource
How To Connect Spark To Your Own Datasource
 
You got ur Erlang in my Ruby
You got ur Erlang in my RubyYou got ur Erlang in my Ruby
You got ur Erlang in my Ruby
 
Zing Database – Distributed Key-Value Database
Zing Database – Distributed Key-Value DatabaseZing Database – Distributed Key-Value Database
Zing Database – Distributed Key-Value Database
 
Zing Database
Zing Database Zing Database
Zing Database
 
An introduction to Semantic Web and Linked Data
An introduction to Semantic Web and Linked DataAn introduction to Semantic Web and Linked Data
An introduction to Semantic Web and Linked Data
 
Seastore: Next Generation Backing Store for Ceph
Seastore: Next Generation Backing Store for CephSeastore: Next Generation Backing Store for Ceph
Seastore: Next Generation Backing Store for Ceph
 

Recently uploaded

IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Evaluating the top large language models.pdf
Evaluating the top large language models.pdfEvaluating the top large language models.pdf
Evaluating the top large language models.pdfChristopherTHyatt
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)wesley chun
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024The Digital Insurer
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProduct Anonymous
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?Antenna Manufacturer Coco
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoffsammart93
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfsudhanshuwaghmare1
 

Recently uploaded (20)

IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Evaluating the top large language models.pdf
Evaluating the top large language models.pdfEvaluating the top large language models.pdf
Evaluating the top large language models.pdf
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 

Embracing NoSQL - Your First Cassandra Project

  • 1. Embracing NoSQL Your First Cassandra Project #embracingnosql @mwynholds @rudy @rk
  • 3. Goal By the time you leave here, you will be comfortable using Cassandra in Rails
  • 4. GENERALIZATION WARNING: PRESENTATION CAN CAUSE BROAD SIMPLIFICATIONS, OPINIONS, NIT-PICKING, AND MAY COMPLICATE PROGRESS.
  • 5. Schedule • 3:30 - 5:00 Hands On Workshop • Introduction • Setup • Reading and Writing • Timeline • ORM • Denormalization • After 5ish - Panel Q&A
  • 6. Why NoSQL? Scalability for the social web
  • 7. CAP
  • 9. CAP Consistency Availability
  • 10. CAP Consistency Partition Availability Tolerance
  • 11. CAP Consistency Partition Availability Tolerance You can only have two at a time!
  • 12. CAP C P A
  • 13. CAP C MongoDB HBase Redis P A
  • 14. CAP C MongoDB MySQL HBase Postgres Redis P A
  • 15. CAP C MongoDB MySQL HBase Postgres Redis P A CouchDB Riak
  • 16. CAP C MongoDB MySQL HBase Postgres Redis P A CouchDB Riak Cassandra!
  • 19. Column Oriented 123 date: 1/23/11 title: My Title url: http://... user: rudy ... 546 body: Lipsum... date: 3/13/11 status: pending title: Foo user: jared ... 680 date: 1/23/11 url: http://... user: rob ... 791 body: Lipsum... date: 3/13/11 title: Bar user: mike ...
  • 22. Decentralized & Distributed Node Node Node Node
  • 23. Decentralized & Distributed Sync Node Sync Node Node Node Sync Sync
  • 24. Decentralized & Distributed Sync Node Sync Write Node Node Node Sync Sync
  • 25. Decentralized & Distributed Sync Node Sync Write Node Node Read Node Sync Sync
  • 27. Tunably Consistent where n = replication factor Write QUORUM (2n +1) Read
  • 29. So How Much Faster Is Cassandra?
  • 30. So How Much Faster Is Cassandra? 
  • 31. So How Much Faster Is Cassandra? 
  • 32. No Really, how fast?
  • 33. No Really, how fast? w/ 50GB MySql Cassandra Write 300ms 0.12ms Read 350ms 15ms
  • 35. First NoSQL Rule Don’t Use NoSQL Right Away!
  • 36. Build Your Application First, THEN Use NoSQL As Needed!
  • 38. What We’re Building Today Reddit
  • 39. What We’re Building Today Reddit + Digg
  • 40. What We’re Building Today Reddit + Digg - Quite a Lot
  • 41. What We’re Building Today Reddit + Digg - Quite a Lot DUGGIT!
  • 42. Login
  • 45. LAB: Installation • Install Cassandra • Start it up • Command line interface • Shut it down
  • 46. Lexicon Database Keyspace Tables Column Families
  • 47. Rows and Columns date: title: url: 123 1/23/11 My Title http://... body: date: status: title: 546 Lipsum... 3/13/11 pending Foo 680 date: url: 1/23/11 http://... body: date: title: 791 Lipsum... 3/13/11 Bar
  • 48. Rows and Columns date: title: url: 123 1/23/11 My Title http://... Row body: date: status: title: 546 Lipsum... 3/13/11 pending Foo 680 date: url: 1/23/11 http://... body: date: title: 791 Lipsum... 3/13/11 Bar
  • 49. Rows and Columns date: title: url: 123 1/23/11 My Title http://... Row body: date: status: title: 546 Lipsum... 3/13/11 pending Foo Row 680 date: url: Key 1/23/11 http://... body: date: title: 791 Lipsum... 3/13/11 Bar
  • 50. Rows and Columns date: title: url: 123 1/23/11 My Title http://... Row body: date: status: title: 546 Lipsum... 3/13/11 pending Foo Row 680 date: url: Column Key 1/23/11 http://... body: date: title: 791 Lipsum... 3/13/11 Bar
  • 51. In SQL Columns Exist for Every Row ... id title body url date user 123 My Title http://... 1/23/11 rudy 456 Foo Lipsum.. 3/13/11 jared 680 http://... 1/23/11 rob 791 Bar Lipsum.. 3/13/11 mike
  • 52. ... But NOT in Column Families! date: title: url: user: 123 1/23/11 My Title http://... rudy body: date: title: user: 546 Lipsum... 3/13/11 Foo jared 680 date: url: user: 1/23/11 http://... rob body: date: title: user: 791 Lipsum... 3/13/11 Bar mike
  • 53. In SQL New Columns Require ALTER TABLE... id title body url date user status 123 My Title http://... 1/23/11 rudy 456 Foo Lipsum.. 3/13/11 jared pending 680 http://... 1/23/11 rob 791 Bar Lipsum.. 3/13/11 mike
  • 54. ... But Are Simple Writes in Cassandra! date: title: url: user: 123 1/23/11 My Title http://... rudy body: date: status: title: user: 546 Lipsum... 3/13/11 pending Foo jared 680 date: url: user: 1/23/11 http://... rob body: date: title: user: 791 Lipsum... 3/13/11 Bar mike
  • 55. What’s a Column? user: Column Name rudy Value
  • 56. What’s a Column? user: Column Name rudy Value 1234 Timestamp
  • 57. Columns are Ordered body: date: title: user: 546 Lipsum... 3/13/11 Foo jared
  • 58. Columns are Ordered body: date: status: title: user: 546 Lipsum... 3/13/11 pending Foo jared
  • 59. Name can be Anything! body: date: status: title: user: 546 Lipsum... 3/13/11 pending Foo jared 11/11/03: 11/12/03: 11/13/03: 11/14/03: rudy Party Recover Panel Return 123: 456: 680: 791: c4af67 7 0 2 5
  • 60. PATTERN: Simple Index f(x, y) = z y1: y2: y3: x1 z11 z12 z13 x2 y2: y4: z22 z24 y1: y3: y4: x3 z31 z33 z34
  • 61. Duggit:Votes f(link_id, user_id) = vote jared: rob: rudy: 123 1 -1 -1 680 mike: rob: 1 1 jared: mike: rudy: 791 -1 1 1
  • 62. LAB: Setup • Create duggit keyspaces • Create votes column family • Create some sample data
  • 64. Cassandra API Thrift Node
  • 65. Cassandra API JAVA Ruby Python WhatEvs Thrift Node
  • 66. Use High Level Client cassandra Ruby Thrift Node github.com/fauna/cassandra
  • 69. Reading a Row row = con.get(column_family, key)
  • 70. Reading a Row link_id = ‘123’ row = con.get(:votes, link_id) url = row['url']
  • 71. Reading Many Rows results = con.multi_get(column_family, keys)
  • 72. Reading Many Rows link_ids = [‘123’, ‘456’] results = con.multi_get :votes, keys results.each do |key, row| row_key = key url = row['url'] end
  • 74. Writing link_id = ‘123’ vote = {user.id => vote_val} con.insert :votes, link_id, vote
  • 75. LAB: Simple Column Family • Connect to Cassandra • Rewrite Vote • Rewrite Link#value • Configure testing frameworks
  • 77. Slice con.get_columns(column_family, key, :columns => column_names con.get_columns(:links, '546', :columns => ['date', 'user'] body: date: status: title: user: 546 Lipsum... 3/13/11 pending Foo jared
  • 78. Range con.get(column_family, row_key, :start => start, :finish => finish) con.get(:link, '546', :start => 'd', :finish => 'u') body: date: status: title: user: 546 Lipsum... 3/13/11 pending Foo jared
  • 79. REMEMBER: Column Names can Be Anything body: date: status: title: user: 546 Lipsum... 3/13/11 pending Foo jared 11/11/03: 11/12/03: 11/13/03: 11/14/03: rudy Party Recover Panel Return 123: 456: 680: 791: c4af67 7 0 2 5
  • 80. PATTERN: Timeline Columns are timestamps rudy mike jared
  • 81. PATTERN: Timeline Columns are timestamps rudy: OHAI 0330: rudy OHAI mike jared
  • 82. PATTERN: Timeline Columns are timestamps rudy: OHAI 0330: rudy OHAI mike: Hi mike 0335: Hi jared
  • 83. PATTERN: Timeline Columns are timestamps rudy: OHAI 0330: rudy OHAI mike: Hi jared:YO 0335: mike Hi 0345: jared YO
  • 84. PATTERN: Timeline Columns are timestamps rudy: OHAI 0330: 0346: rudy OHAI HALP mike: Hi jared:YO 0335: mike rudy:HALP Hi 0345: jared YO
  • 85. PATTERN: Timeline Columns are timestamps rudy: OHAI 0330: 0346: 0415: rudy OHAI HALP PLZ mike: Hi jared:YO 0335: mike rudy:HALP Hi rudy: PLZ 0345: jared YO
  • 86. PATTERN: Timeline Columns are timestamps rudy: OHAI 0330: 0346: 0415: rudy OHAI HALP PLZ mike: Hi jared:YO 0335: mike rudy:HALP Hi rudy: PLZ 0345: 0420: jared jared: RTFM YO RTFM
  • 87. PATTERN: Timeline Columns are timestamps rudy: OHAI 0330: 0346: 0415: rudy OHAI HALP PLZ mike: Hi jared:YO 0335: mike rudy:HALP Hi rudy: PLZ 0345: 0420: 0445: jared jared: RTFM YO RTFM NEWB jared: NEWB
  • 88. PATTERN: Timeline Columns are timestamps rudy: OHAI 0330: 0346: 0415: rudy OHAI HALP PLZ mike: Hi jared:YO 0335: 0515: mike rudy:HALP Hi LOL rudy: PLZ 0345: 0420: 0445: jared jared: RTFM YO RTFM NEWB jared: NEWB mike: LOL
  • 89. PATTERN: Timeline Columns are timestamps rudy: OHAI 0330: 0346: 0415: 0645: rudy KTHXBAI OHAI HALP PLZ mike: Hi jared:YO 0335: 0515: mike rudy:HALP Hi LOL rudy: PLZ 0345: 0420: 0445: jared jared: RTFM YO RTFM NEWB jared: NEWB mike: LOL rudy: KTHXBAI
  • 90. Duggit: Users Links 20110101: 20110214: 20110311: 20110313: rudy 123 311 777 987 20101211: 20110113: 20110225: 20110301 20110314: jared 4 202 456 531 1066 20101231: 20110228: 20110304: rob 99 432 680 20101211: 20101225: 20110307: 20110312: mike 791 500 53 696
  • 91. “Pagination” con.get ‘jared’, :count => 3, :reverse => true 20101211: 20110113: 20110225: 20110301 20110314: jared 531 4 202 456 1066 con.get ‘jared’, :count => 3, :reverse => true, :start => 20110224 20101211: 20110113: 20110225: 20110301 20110314: jared 531 4 202 456 1066
  • 92. But What about Across Rows? 20110101: 20110214: 20110311: 20110313: rudy 311 123 777 987 20101211: 2011013: 20110225: 20110301 20110314: jared 531 4 202 456 1066 shuffle 20110214: 20110225: 20110301 20110311: 20110313: 20110314: 311 456 531 777 987 1066
  • 93. “All” Timeline All 20101211: 4 20101231: 99 20110101: 123 20110113: 202 20110214: 311 ... 20110101: 20110214: 20110311: 20110313: rudy 311 123 777 987 20101211: 20110113: 20110225: 20110301 20110314: jared 531 4 202 456 1066 20101231: 20110228: 20110304: rob 99 432 680
  • 94. The Balance rudy rob All mike jared
  • 95. The Balance rudy rob All mike jared
  • 96. Batch Writing con.batch do con.insert :user_links, user.id, value con.insert :user_links, 'All', value end
  • 97. LAB: Timelines • Create a user_links column family • Write links to appropriate timelines • Return the recent items
  • 98. Still Hitting SQL App Cassandra SQL
  • 99. Pattern: ORM Row = Object Column = Object property date: title: url: user: 123 1/23/11 My Title http://... rudy body: date: status: title: user: 546 Lipsum... 3/13/11 pending Foo jared 680 date: url: user: 1/23/11 http://... rob
  • 100. Secondary Index Create an index on date column date: title: url: user: 123 1/23/11 My Title http://... rudy body: date: status: title: user: 546 Lipsum... 3/13/11 pending Foo jared 680 date: url: user: 1/23/11 http://... rob
  • 101. Secondary Index Query: where date = 1/23/11 date: title: url: user: 123 1/23/11 My Title http://... rudy body: date: status: title: user: 546 Lipsum... 3/13/11 pending Foo jared 680 date: url: user: 1/23/11 http://... rob
  • 102. LAB: ORM • Rewrite Link to save to Cassandra • Update supporting models and controllers
  • 103. Still Two Reads App Cassandra Cassandra
  • 104. What if it isn’t there?
  • 105. What if it isn’t there? Write
  • 106. What if it isn’t there? Write
  • 107. What if it isn’t there? Link.recent_ids Write
  • 108. What if it isn’t there? Link.recent_ids Write Link.by_ids
  • 109. PATTERN: Denormalization Just like SQL: Store it multiple times, multiple locations
  • 110. Seen it before ... All 20101211: 4 20101231: 99 20110101: 123 20110113: 202 20110214: 311 ... 20110101: 20110214: 20110311: 20110313: rudy 311 123 777 987 20101211: 20110113: 20110225: 20110301 20110314: jared 531 4 202 456 1066 20101231: 20110228: 20110304: rob 99 432 680
  • 111. But Different Column Family Structures? links date: title: url: user: 123 1/23/11 My Title http://... rudy users_to_links 20110101: 20110214: 20110311: 20110313: rudy 311 123 777 987
  • 112. Super-Column Families All 20101211: 20101231: 20110101: 20110113: 20110214: ... rudy 20110313: 20110311: 20110214: 20110101: jared 20110314: 20110301: 20110225: 20110113: 20101211: rob 20110304: 20110228: 20101231:
  • 113. Super-Column date: title: url: user: 20110314: = 20110314: 1/23/11 My Title http://... rudy
  • 114. Write Object to Each uuid = SimpleUUID::UUID.new @id = uuid.to_guid value = { 'id' => @id, 'title' => @title, ... } pointer = { uuid => value } con.batch do con.insert :links, @id, value con.insert :user_links, @user_id.to_s, pointer con.insert :user_links, 'all', pointer end
  • 115. LAB: Denormalize Links • Rewrite Link#save
  • 116. Resources • Wiki: http://wiki.apache.org/cassandra/ • Mailing List: user@cassandra.apache.org • “Cassandra: The Definitive Guide” by Eban Hewitt (@ebenhewitt) • Presentations of Mike Malone (@mjmalone)
  • 117. Advanced Topics • Deployment • Cassandra in the Cloud • Row Partitioning • Compound Keys • Other Strategies

Editor's Notes

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n
  51. \n
  52. \n
  53. \n
  54. \n
  55. \n
  56. \n
  57. \n
  58. \n
  59. \n
  60. \n
  61. \n
  62. \n
  63. \n
  64. \n
  65. \n
  66. \n
  67. \n
  68. \n
  69. \n
  70. \n
  71. \n
  72. \n
  73. \n
  74. \n
  75. \n
  76. \n
  77. \n
  78. \n
  79. \n
  80. \n
  81. \n
  82. \n
  83. \n
  84. \n
  85. \n
  86. \n
  87. \n
  88. \n
  89. \n
  90. \n
  91. \n
  92. \n
  93. \n
  94. \n
  95. \n
  96. \n
  97. \n
  98. \n
  99. \n
  100. \n
  101. \n
  102. \n
  103. \n