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

Getting Started with Couchbase App Development

Getting Started with Couchbase App Development

I gave this presentation at CouchConf Berlin 2012. Its purpose was to give the audience a solid introduction on how Couchbase fits in their application architecture and how they can shift their mindset from a relational to a document-oriented database.

Other slides from CouchConf Berlin are available here: http://www.couchbase.com/couchconf-berlin

Michael Nitschinger

October 30, 2012
Tweet

More Decks by Michael Nitschinger

Other Decks in Programming

Transcript

  1. 1   1   Ge%ng  Started  with   Couchbase  App

     Development   Michael  Nitschinger   Developer  Advocate   @daschl    
  2. 2   What  we`ll  talk  about   • Setup  Development  Environment

      • Intro  to  Document  Databases   • Intro  to  Couchbase  OperaFons   • Basic  Document  Modeling   • Modeling  Examples  
  3. 4   Couchbase  is  Faster,  Scales  and  Simplifies   App

     Servers   API  Servers   Couchbase  Server   Cluster  
  4. 5   Download  &  Install  Couchbase   • Downloads  at  couchbase.com/download

      •  Provision  via  wizard  in  Web  Console   –  Or  provision  via  REST  interface:  operaFons  folks  to  automate  provisioning     (i.e  Chef,  puppet,  Rightscale  rightscript)   •  Linux:  Ubuntu  and  Red  Hat/CentOS   –  Packages  for  most  common  distribuFons.   •  dpkg  -­‐i  ,  rpm  -­‐i,  etc.   •  Mac   –  Download  a  .zip,  open,  drag  to  ApplicaFons   •  Windows   –  Download  a  setup.exe,  double  click  
  5. 6   Setup  Smart  Client  SDK   • High  performance,  official

     client  libraries  for  Java,  .NET,  PHP,   Ruby,  C,  Python   –   Community  supported  for  Clojure,  JRuby,  Perl,  Go,  Erlang,    Node.js   • Head  to  couchbase.com/develop  for  SDKs     –   Client  libraries   –   Ge%ng  Started  guides   –   Tutorial  with  a  sample  applicaFon   –   A  complete  API  reference  
  6. 7   Client  Setup:  Ge%ng  Cluster  ConfiguraFon   hep://myserver:8091/  

    { …   "bucketCapabilities": [ "touch", "sync", "couchapi" ], "bucketCapabilitiesVer": "sync-1.0", "bucketType": ”couchbase",   "name": "default", "nodeLocator": "vbucket", "nodes": [   …. Couchbase  Client   Cluster  ConfiguraFon   over  REST  
  7. 8   Client  Setup:  Ge%ng  Cluster  ConfiguraFon   Couchbase  Client

      New  Node  Added  to  Cluster   and  Coming  Online   Couchbase  Topology   Update  
  8. 11   Compared  to  a  Document  Database   •  Easy

     to  distribute  data   •  Makes  sense  to  applicaFon  programmers     o::1001   {   uid:  “ji22jd”,   customer:  “Ann”,   line_items:  [     {  sku:  0321293533,  quan:  3,    unit_price:  48.0  },   {  sku:  0321601912,  quan:  1,  unit_price:  39.0  },   {  sku:  0131495054,  quan:  1,  unit_price:  51.0  }     ],   payment:  {                        type:  “Amex”,                      expiry:  “04/2001”,     last5:  12345   }    
  9. 12   JSON  Documents   •  Maps  more  closely  to

     external  API   •  CRUD  OperaFons,  lightweight  and  implicit  schema   •  Stored  under  a  unique  idenFfier  key   myDocument = {! “fields” : [“with basic types”, 3.14159, true],! “like” : “your favorite language.”,! “status”: {! “apis” : true,! “databases” : “document”}! }! client.set(“mydocumentid”, myDocument);! mySavedDocument = client.get(“mydocumentid”);!
  10. 13   Object  to  JSON  back  to  Object   User

     Object   string   uid   string   firstname   string   lastname   int   age   array   favorite_colors   string   email   u::[email protected]   {   “uid”:  123456,   “firstname”:  “Michael”,   “lastname”:  “Nitschinger”,   “age”:  24,   “favorite_colors”:  [“blue”,  “black”],   “email”:  “michael.nitschinger@cou…”   }   User  Object   string   uid   string   firstname   string   lastname   int   age   array   favorite_colors   string   email   u::[email protected]   {   “uid”:  123456,   “firstname”:  “Michael”,   “lastname”:  “Nitschinger”,   “age”:  24,   “favorite_colors”:  [“blue”,  “black”],   “email”:  “michael.nitschinger@cou…”   }   set()   get()  
  11. 15   The  Most  Common  Mental  Adjustment   •  In

     SQL  we  tend  to  want  to  avoid  hi%ng  the  database  as  much  as   possible:   – Costly,  tying  up  connecFon  pools  and  overloading  db  servers   – Even  with  caching  and  indexing  tricks,  and  massive   improvements  over  the  years,  SQL  sFll  gets  bogged  down  by   complex  joins  and  huge  indexes   •  In  Couchbase,  get`s  and  set`s  are  so  fast  they  are  trivial,  and  not   boelenecks,  this  is  hard  for  many  people  to  accept  at  first  
  12. 16   Couchbase  Basic  OperaFons   •  get  (key)  

    –   Retrieve  a  document   •  set  (key,  value)   –   Store  a  document,  overwrites  if  exists   •  add  (key,  value)   –   Store  a  document,  error/excepFon  if  exists   •  replace  (key,  value)   –   Store  a  document,  error/excepFon  if  doesn`t  exist   •  cas  (key,  value,  cas)   –   Compare  and  swap,  mutate  document  only  if  it  hasn`t  changed   while  execuFng  this  operaFon  
  13. 17   Couchbase  Basic  OperaFons  (cont`d)   Atomic  Counters  are

     a  special  structure  in  Couchbase,  they   are  executed  in  order  and  are  PosiFve  Integer  Values   • set  (key,  value)   –   Use  set  to  iniFalize  the  counter   •  cb.set(lmy_counterz,  1)   • incr  (key)   –   Increase  an  atomic  counter  value,  default  by  1   •  cb.incr(lmy_counterz)  #  now  it`s  2   • decr  (key)   –   Decrease  an  atomic  counter  value,  default  by  1   •  cb.decr(lmy_counterz)  #  now  it`s  1  
  14. 18   INCR  /  DECR   •  Maintain  a  numerical

     counter   •  Good  for  shared  counters  with  tons  of  increments   •  Example:  game  scores   •  Can  INCR  by  any  integer   •  Accessible  as  a  JSON  number  in  views   •  We'll  look  at  maintaining  a  leaderboard  in  the  next   session  
  15. 19   Simple  Example  in  Ruby   #  user.rb  

    require  “rubygems”   require  “couchbase”     class  User   aer_accessor    :name,  :email,  :Ftle,  :twieer     def  iniFalize(aer  =  {})          aer.each  do  |name,  value|                  seeer  =  "#{name}=”                  next  unless  respond_to?(seeer)                  send(seeer,  value)            end   end     def  save          client  =  Couchbase.bucket          client.set(@email.downcase,  self.to_json)   end   end   #  example.rb   require  “./user.rb”     u1  =  User.new({     :email  =>  “michael.nitschinger@c…”,   :name  =>  “Michael  Nitschinger”,   :Ftle  =>  “Developer  Advocate”,   :twieer  =>  “@daschl”   })     u1.save  
  16. 20   Add  Retrieval   #  user.rb   require  “rubygems”

      require  “couchbase”     class  User   aer_accessor    :name,  :email,  :Ftle,  :twieer     def  iniFalize(aer  =  {})  ...  end     def  save          client  =  Couchbase.bucket          client.set(@email.downcase,  self.to_json)   end     def  self.find_by_email(email)          client  =  Couchbase.bucket          doc  =  client.get(email.downcase)          return  doc  ?  User.new(doc)  :  nil   end   end   #  example.rb   require  “./user.rb”     u1  =  User.new({     :email  =>  “michael.nitschinger@c…”,   :name  =>  “Michael  Nitschinger”,   :Ftle  =>  “Developer  Advocate”,   :twieer  =>  “@daschl”   })     u1.save     u1  =  User.find_by_email(“michael.nitschinger@c…”)     if  u1   puts  “User  Found!”   puts  u1.inspect   else   puts  “User  Not  Registered!”   end  
  17. 21   Add  Instance  Variables   #  user.rb   require

     “rubygems”   require  “couchbase”     class  User   aer_accessor    :name,  :email,  :Ftle,  :twieer   aer_accessor  :|_id,  :|_token     def  iniFalize(aer  =  {})  ...  end     def  save  ...  end     def  self.find_by_email(email)          client  =  Couchbase.bucket          doc  =  client.get(email.downcase)          return  doc  ?  User.new(doc)  :  nil   end   end   #  example.rb   require  “./user.rb”     u1  =  User.find_by_email(“michael.nitschinger@c…”)     if  u1   u1.|_id  =  “682829292”   u1.|_token  =  “f02jdjd020d8373730djd02”   u1.save   else   #  create  user   end  
  18. 22   Distributed  System  Design:  Concurrency  Controls   Actor  1

      Actor  2   Couchbase  Server   CAS  mismatch   Success   #  actors.rb     c  =  Couchbase.bucket   c.set(“mydoc”,  {  :myvalue  =>  nil  }     doc1,  flags,  cas  =  c.get(“mydoc”,              :extended  =>  true)     doc2,  flags,  cas  =  c.get(“mydoc”,            :extended  =>  true)     #   c.set  (“mydoc”,  {  “myvalue”:  true  },  :cas  =>  cas)     #  will  fail  because  cas  has  changed   c.set  (“mydoc”,  {  “myvalue”:  true  },  :cas  =>  cas)  
  19. 24   24           When  considering

     how  to  model  data  for  a  given  applicaFon:   •  Think  of  a  logical  container  for  the  data   •  Think  of  how  data  groups  together   Basic  Document  Modeling   Q   •  Are  these  separate  object  in  the  model  layer?     •  Are  these  objects  accessed  together?      
  20. 25   25   Document  Design  OpFons      

          • One  document  that  contains  all  related  data       –   Data  is  de-­‐normalized   –   Beeer  performance  and  scale   –   Eliminate  client-­‐side  joins       • Separate  documents  for  different  object  types  with  cross   references     –   Data  duplicaFon  is  reduced   –   Objects  may  not  be  co-­‐located     –   TransacFons  supported  only  on  a  document  boundary   –   Most  document  databases  do  not  support  joins  
  21. 26   26   Basic  Document  Design:  Document  ID  /

     Key  selecFon   • Similar  to  primary  keys  in  relaFonal  databases   • Documents  are  sharded  based  on  the  document  ID   • ID  based  document  lookup  is  extremely  fast     • ID-­‐Key`s  can  only  appear  once  in  a  bucket,  unique   OpFons   •   UUIDs,  date-­‐based  IDs,  numeric  IDs       •   Hand-­‐cra•ed  (human  readable)     •   Matching  prefixes  (for  mulFple  related  objects)   Q   •         Do  you  have  a  unique  way  of  referencing  objects?   •         Are  related  objects  stored  in  separate  documents?  
  22. 27   27   •  User  profile   •   

      •  Blog  posts   –   Contain  the  posts  themselves     •  Blog  comments   –   Comments  from  other  users   •   OpFon  1  -­‐  Keep  it  with  Blog  Document   •   OpFon  2  -­‐  Separate  it  Out   Example:  EnFFes  for  a  Blog   BLOG  
  23. 28   28   Blog  Document  –  OpFon  1  –

     Single  document     {       “_id”:  “daschl_Hello_World”,   “author”:  “daschl”,     “type”:  “post”   “Ftle”:  “Hello  World”,   “format”:  “markdown”,     “body”:  “Hello  from  [Couchbase](hep://couchbase.com).”,     “html”:  “<p>Hello  from  <a  href=\“hep:    …,       “comments”:  [                            [“format”:  “markdown”,  “body”:”Awesome  post!”],                            [“format”:  “plain”,  “body”:”Like  it.”  ]   ]     }   Blog  Post  Object   string   id   string   author   string   type   string   Ftle   string   format   string   body   string   html   array   comments  
  24. 29   29   Blog  Document  –  OpFon  2  -­‐

     Split  into  MulFple  Docs     {     “_id”:  “daschl_Hello_World”,   “author”:  “daschl”,     “type”:  “post”   “Ftle”:  “Hello  World”,   “format”:  “markdown”,     “body”:  “Hello  from  [Couchbase](hep://couchbase.com).”,     “html”:  “<p>Hello  from  <a  href=\“hep:    …”,   “num_comments”:  2   }   Blog  Post  Object   string   id   string   author   string   type   string   Ftle   string   format   string   body   string   html   int   num_comments   Comment  Object   string   format   string   body   int   id   {   “_id”:  “daschl_Hello_World_1”,   “format”:  “markdown”,   “body”:  “Awesome  post!”   }     {   “_id”:  “daschl_Hello_World_2”,   “format”:  “plain”,   “body”:  “Love  It!”   }  
  25. 30   30   •  You  can  imagine  how  to

     take  this  to  a  threaded  list   Threaded  Comments   Blog   First   comment   Reply  to   comment   More   Comments   List   List   Advantages   •  Only  fetch  the  data  when  you  need  it   •  For  example,  rendering  part  of  a  web  page   • Spread  the  data  and  load  across  the  enFre  cluster