Upload
couchbase
View
813
Download
0
Tags:
Embed Size (px)
Citation preview
11
Getting Started withCouchbase App Development
Michael NitschingerDeveloper Advocate@daschl
2
What we’ll talk about
• Setup Development Environment• Intro to Document Databases• Intro to Couchbase Operations• Basic Document Modeling• Modeling Examples
3 3
Basics & Getting started
4
Couchbase is Faster, Scales and Simplifies
App Servers
API Servers
Couchbase ServerCluster
5
Download & Install Couchbase
• Downloads at couchbase.com/download
• Provision via wizard in Web Console– Or provision via REST interface: operations folks to automate provisioning
(i.e Chef, puppet, Rightscale rightscript)
• Linux: Ubuntu and Red Hat/CentOS– Packages for most common distributions.
• dpkg -i , rpm -i, etc.
• Mac– Download a .zip, open, drag to Applications
• Windows– Download a setup.exe, double click
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– Getting Started guides– Tutorial with a sample application– A complete API reference
7
Client Setup: Getting Cluster Configuration
http://myserver:8091/
{… "bucketCapabilities": [ "touch", "sync", "couchapi" ], "bucketCapabilitiesVer": "sync-1.0", "bucketType": ”couchbase", "name": "default", "nodeLocator": "vbucket", "nodes": [….
Couchbase ClientCouchbase ClientCluster Configuration
over REST
8
Client Setup: Getting Cluster Configuration
Couchbase ClientCouchbase Client
New Node Added to Cluster and Coming
OnlineCouchbase TopologyCouchbase Topology
UpdateUpdateCouchbase TopologyCouchbase Topology
UpdateUpdate
9 9
Document Database Basics
10
The relational approach to model data
http://martinfowler.com/bliki/AggregateOrientedDatabase.html
11
Compared to a Document Database
• Easy to distribute data• Makes sense to application 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}
12
JSON Documents
• Maps more closely to external API• CRUD Operations, lightweight and implicit schema
• Stored under a unique identifier 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”);
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()
1414
Couchbase Operations
15
The Most Common Mental Adjustment
• In SQL we tend to want to avoid hitting the database as much as possible:–Costly, tying up connection pools and overloading db servers–Even with caching and indexing tricks, and massive
improvements over the years, SQL still gets bogged down by complex joins and huge indexes
• In Couchbase, get’s and set’s are so fast they are trivial, and not bottlenecks, this is hard for many people to accept at first
16
Couchbase Basic Operations
• get (key)– Retrieve a document
• set (key, value)– Store a document, overwrites if exists
• add (key, value)– Store a document, error/exception if exists
• replace (key, value)– Store a document, error/exception if doesn’t exist
• cas (key, value, cas)– Compare and swap, mutate document only if it hasn’t changed
while executing this operation
17
Couchbase Basic Operations (cont’d)
Atomic Counters are a special structure in Couchbase, they are executed in order and are Positive Integer Values•set (key, value)– Use set to initialize the counter• cb.set(“my_counter”, 1)
•incr (key)– Increase an atomic counter value, default by 1• cb.incr(“my_counter”) # now it’s 2
•decr (key)– Decrease an atomic counter value, default by 1• cb.decr(“my_counter”) # now it’s 1
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
19
Simple Example in Ruby
# user.rbrequire “rubygems”require “couchbase”
class Userattr_accessor :name, :email, :title, :twitter
def initialize(attr = {}) attr.each do |name, value| setter = "#{name}=” next unless respond_to?(setter) send(setter, value) endend
def save client = Couchbase.bucket client.set(@email.downcase, self.to_json)endend
# example.rbrequire “./user.rb”
u1 = User.new({ :email => “michael.nitschinger@c…”,:name => “Michael Nitschinger”,:title => “Developer Advocate”,:twitter => “@daschl”
})
u1.save
20
Add Retrieval
# user.rbrequire “rubygems”require “couchbase”
class Userattr_accessor :name, :email, :title, :twitter
def initialize(attr = {}) ... 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) : nilendend
# example.rbrequire “./user.rb”
u1 = User.new({ :email => “michael.nitschinger@c…”,:name => “Michael Nitschinger”,:title => “Developer Advocate”,:twitter => “@daschl”
})
u1.save
u1 = User.find_by_email(“michael.nitschinger@c…”)
if u1puts “User Found!”puts u1.inspectelseputs “User Not Registered!”end
21
Add Instance Variables
# user.rbrequire “rubygems”require “couchbase”
class Userattr_accessor :name, :email, :title, :twitterattr_accessor :fb_id, :fb_token
def initialize(attr = {}) ... end
def save ... end
def self.find_by_email(email) client = Couchbase.bucket doc = client.get(email.downcase) return doc ? User.new(doc) : nilendend
# example.rbrequire “./user.rb”
u1 = User.find_by_email(“michael.nitschinger@c…”)
if u1u1.fb_id = “682829292”u1.fb_token = “f02jdjd020d8373730djd02”u1.saveelse# create userend
22
Distributed System Design: Concurrency Controls
Actor 1 Actor 2
Couchbase Server
CAS mismatchSuccess
# actors.rb
c = Couchbase.bucketc.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 changedc.set (“mydoc”, { “myvalue”: true }, :cas => cas)
2323
Document Modeling
2424
When considering how to model data for a given application:• 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?
2525
Document Design Options
• One document that contains all related data – Data is de-normalized– Better performance and scale– Eliminate client-side joins
• Separate documents for different object types with cross references – Data duplication is reduced– Objects may not be co-located – Transactions supported only on a document boundary– Most document databases do not support joins
2626
Basic Document Design: Document ID / Key selection
• Similar to primary keys in relational 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
Options• UUIDs, date-based IDs, numeric IDs • Hand-crafted (human readable) • Matching prefixes (for multiple related objects)
Q • Do you have a unique way of referencing objects?• Are related objects stored in separate documents?
2727
• User profile•
• Blog posts– Contain the posts themselves
• Blog comments– Comments from other users• Option 1 - Keep it with Blog Document• Option 2 - Separate it Out
Example: Entities for a Blog
BLOG
2828
Blog Document – Option 1 – Single document
{
“_id”: “daschl_Hello_World”,“author”: “daschl”, “type”: “post”“title”: “Hello World”,“format”: “markdown”, “body”: “Hello from [Couchbase](http://couchbase.com).”, “html”: “<p>Hello from <a href=\“http: …,
“comments”: [ [“format”: “markdown”, “body”:”Awesome post!”], [“format”: “plain”, “body”:”Like it.” ]]
}
Blog Post Object
string id
string author
string type
string title
string format
string body
string html
array comments
2929
Blog Document – Option 2 - Split into Multiple Docs
{ “_id”: “daschl_Hello_World”,“author”: “daschl”, “type”: “post”“title”: “Hello World”,“format”: “markdown”, “body”: “Hello from [Couchbase](http://couchbase.com).”, “html”: “<p>Hello from <a href=\“http: …”,“num_comments”: 2}
Blog Post Object
string id
string author
string type
string title
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!”}
3030
• You can imagine how to take this to a threaded list
Threaded Comments
Blog
First comment
Reply to comment
More Comments
ListList ListList
Advantages
• Only fetch the data when you need it• For example, rendering part of a web page
• Spread the data and load across the entire cluster
3131
Demo Time/Questions?