91
Webinar NoSQL For Java Developers Simon Baslé SDK Engineer 1

NoSQL for Java Developers

Embed Size (px)

Citation preview

Page 1: NoSQL for Java Developers

Webinar  NoSQL  For  Java  Developers

Simon  Baslé  -­‐  SDK  Engineer

1

Page 2: NoSQL for Java Developers

Agenda

▪Motivation  ▪ The  new  API,  what  does  it  look  like?  ▪ Example  ▪ RxJava  and  the  asynchronous  API  ▪ Error  handling  and  batching  ▪ Live  Demo  (N1QL  DSL)  ▪ Plans  for  the  future

2

Page 3: NoSQL for Java Developers

Let's Dive In !

3

Page 4: NoSQL for Java Developers

Motivationfor  the  2.0  SDK  generation

4

Page 5: NoSQL for Java Developers

Benefits  of  a  SDK?  

• Work  with  the  database  using  familiar  language  and  

patterns  associated  with  it  

• It  does  the  heavy  lifting  for  you  (cluster  topology  

awareness,  op  routing,  dealing  with  protocol(s),  ...)  

• Mutualize  work  on  performance  and  offer  good  

abstractions5

Page 6: NoSQL for Java Developers

Previous  generation  (1.4.x)  based  on  Spymemcached

• a  lot  of  legacy,  Spymemcached  is  maybe  too  

memcached-­‐focused  

• async,  but  with  java.util.concurrent.Future  (limited)  

• asynchronous  interdependent  dataflows  are  hard  to  build

6

Page 7: NoSQL for Java Developers

Time  to  freshen  up  the  API!  

• Find  a  better,  more  expressive  way  of  doing  async  

• Offer  coherent  well-­‐thought  abstractions  

• Plan  for  the  future,  evolvability  

• Don't  forget  about  performance!

7

Page 8: NoSQL for Java Developers

2.0  is  a  complete  rewrite  with  asynchronicity  at  its  core...  

RxJava Netty

8

Page 9: NoSQL for Java Developers

2.0  is  a  complete  rewrite  ...but  a  synchronous  API  built  on  top  of  it  is  offered  too  

9

Page 10: NoSQL for Java Developers

Architectural  Overview

10

Page 11: NoSQL for Java Developers

Architectural  Overview

Core▪ Core  abstracts  low-­‐level  

▪ Fully  async  &  message-­‐oriented  

▪ Low  overhead,  high  performance  

▪ Java  6+11

Page 12: NoSQL for Java Developers

Architectural  Overview

Core

Java

▪ Java  Client  is  a  higher  level  abstraction  

▪ Exposes  RxJava  Observables  in  the  Asynchronous  API  

▪ Adds  a  Synchronous  API  on  top  of  it  

▪ Java  6+  (especially  great  for  clients  in  Java  8!) 12

Page 13: NoSQL for Java Developers

Architectural  Overview

Core

Java Hadoop

Spring

▪ All  that  can  be  leveraged  to  build  connectors  

▪ Spring  Data,  Hadoop  in  the  works

13

Page 14: NoSQL for Java Developers

Architectural  Overview

Core

Java Scala JRuby,  ... Hadoop

Spring Play!2

▪ Other  SDKs  /  connectors  could  be  built  

▪ even  by  you,  the  community

14

Page 15: NoSQL for Java Developers

The  New  API  -­‐  What  does  it  look  like?(for  now  the  Synchronous  API)

15

Page 16: NoSQL for Java Developers

Cluster  and  BucketEntry  points  Class  naming  refers  to  Couchbase  concepts

16

Page 17: NoSQL for Java Developers

Cluster  and  BucketEntry  points  Class  naming  refers  to  Couchbase  concepts

▪ To  bootstrap,  connect  and  also  manage  nodes,  use  Cluster  – just  needs  one  or  more  IPs  or  hostnames  to  connect  

▪ To  operate  on  data,  use  Bucket  

▪ A  Bucket  is  thread  safe,  should  be  reused  instead  of  re-­‐created

17

Page 18: NoSQL for Java Developers

The  Document<T>where  the  data  goes

18

Page 19: NoSQL for Java Developers

The  Document<T>where  the  data  goes

▪ Represents  the  data  in  Couchbase  

▪ Both  content()  and  metadata  :  id(),  cas(),  expiry()  

▪ CAS:  Compare-­‐and-­‐Swap.  Sequence  number  that  allows  to  prevent  mutation  clashes

19

Page 20: NoSQL for Java Developers

The  Document<T>where  the  data  goes

▪ JsonDocument  ▪ BinaryDocument  ▪ SerializableDocument  ▪ ...  

▪ The  JsonDocument's  content  is  a  JsonObject  ▪ simple  Map-­‐like  API  to  deal  with  JSON  ▪ there's  also  a  RawJsonDocument  to  deal  with  JSON  as  String

20

Page 21: NoSQL for Java Developers

Key-­‐Value  Operationsthe  gist  of  the  API

21

Page 22: NoSQL for Java Developers

Key-­‐Value  Operationsthe  gist  of  the  API

▪ Get  (but  also  getFromReplica,  getAndLock,  touch)  

▪ Upsert  (but  also  insert,  replace)  

▪ Remove  

▪ Append,  Prepend  

▪ Unlock...22

Page 23: NoSQL for Java Developers

Key-­‐Value  Operationsthe  gist  of  the  API

▪ Each  operation  returns  a  Document,  by  default  JsonDocument,  with  the  updated  CAS  

▪ Overrides  to  choose  a  target  Document  type  

▪ Overrides  to  customize  the  timeout  for  each  operation  

▪ Mutating  operations  have  overrides  to  choose  replication  factor  and  persistence  constraints  to  wait  for  before  returning 23

Page 24: NoSQL for Java Developers

Management  APIs"ops  stuff"

24

Page 25: NoSQL for Java Developers

Management  APIs"ops  stuff"

▪ cluster.createManager("admin",  "pass")  ▪ info  ▪ hasBucket  ▪ getBucket  ▪ insert/remove/updateBucket  

▪ bucket.bucketManager()  ▪ info  ▪ flush  ▪ get/insert/upsert/removeDesignDocument  ▪ publishDesignDocument 25

Page 26: NoSQL for Java Developers

Example

26

Page 27: NoSQL for Java Developers

connect  to  cluster  

prepare  JSON  

insert  a  document  vs.  upsert  a  document  

clean  up

27

Page 28: NoSQL for Java Developers

Cluster cluster = CouchbaseCluster.create("127.0.0.1"); Bucket testBucket = cluster.openBucket("testBucket");

//create some JSON content for a new DocumentJsonObject content = JsonObject.create() .put("type", "test") .put("value", "this is a test"); JsonDocument testDoc = JsonDocument.create("test", content);

//insert the fresh DocumenttestBucket.insert(testDoc);

28

Page 29: NoSQL for Java Developers

//try again with same key? try { testBucket.insert(testDoc); } catch (DocumentAlreadyExistsException e) { //expected //upsert works whenever document exists or not testBucket.upsert(testDoc); }

//cleans up ALL shared resources // (also calls close() on each Bucket)cluster.disconnect();

29

Page 30: NoSQL for Java Developers

Q&A  Intermission  1any  questions  at  this  point?

30

Page 31: NoSQL for Java Developers

RxJava  &  the  Asynchronous  APIModern  Async  Dataflows

31

Page 32: NoSQL for Java Developers

RxJava  101aka  "Async  Goodness"

32

Page 33: NoSQL for Java Developers

RxJava  101aka  "Async  Goodness"

▪ Observable<T>    and    Observer<T>  

▪ Observable  =  a  Stream  of  Data  

▪ Use  Rx  operators  to  manipulate  the  stream

33

Page 34: NoSQL for Java Developers

RxJava  101compare  with  Iterator

Single Multiple

Sync  ("pull") T Iterable<T>

Async  ("push") Future<T> Observable<T>

34

Page 35: NoSQL for Java Developers

RxJava  101Observer<T>  interface

Event Iterator<T> Observer<T>

data  retrieval T  next() onNext(T)

discover  error throw  Exception onError(Throwable)

complete returns onCompleted()35

Page 36: NoSQL for Java Developers

Observableexposes  operators

▪ Transformation  

▪ Filtering  

▪ Combination  

▪ Managing  Errors

36

Page 37: NoSQL for Java Developers

Transform!"map  is  the  first  step"

37

Page 38: NoSQL for Java Developers

Transform!"map  is  the  first  step"

▪ Observable<T>  source  

▪ Observable<R>  transformed  =  source.map(mapFunction)  

▪ mapFunction  transforms  each  T  into  an  R  ▪ eg.  T  =  String  and  R  =  Integer,  mapFunction  returns  string.length()

38

Page 39: NoSQL for Java Developers

Transform!"map  is  the  first  step"

39

Page 40: NoSQL for Java Developers

Filterwhen  you  only  need  part  of  the  data

40

Page 41: NoSQL for Java Developers

Filterwhen  you  only  need  part  of  the  data

▪ first()  

▪ take(int  n)  

▪ skip(int  n)  

▪ distinct()  

▪ ...

41

Page 42: NoSQL for Java Developers

FilterThe  Heavy  Artillery

▪ Observable<T>  filter(  filterPredicate  )  

▪ Only  emit  the  Ts  that  match  the  filterPredicate

42

Page 43: NoSQL for Java Developers

FilterThe  Heavy  Artillery

43

Page 44: NoSQL for Java Developers

Combineseveral  streams

44

Page 45: NoSQL for Java Developers

Combineseveral  streams

▪ merge(otherObservableOfT)  

▪ concat(otherObservableOfT)  

▪ mergeDelayErrors,  zipWith,  join,  ...

45

Page 46: NoSQL for Java Developers

Combinemerge

46

Page 47: NoSQL for Java Developers

Combineconcat

47

Page 48: NoSQL for Java Developers

Back  to  Transformations"improve  your  Rx-­‐Fu  with  flatMap"

48

Page 49: NoSQL for Java Developers

Back  to  Transformations"improve  your  Rx-­‐Fu  with  flatMap"

▪ Like  a  map...  ▪ ...for  when  your  transformation  must  also  be  asynchronous

49

Page 50: NoSQL for Java Developers

Back  to  Transformations"improve  your  Rx-­‐Fu  with  flatMap"

▪ Like  a  map...  ▪ ...for  when  your  transformation  must  also  be  asynchronous  

▪ transforms  each  item  to  an  Observable<R>  (not  just  an  R)  

▪ flattens  them  all  in  the  output  stream  to  give  a  flat  stream  of  Rs

50

Page 51: NoSQL for Java Developers

Back  to  Transformations"improve  your  Rx-­‐Fu  with  flatMap"

51

Page 52: NoSQL for Java Developers

The  Very  Last  Stepsubscription

52

Page 53: NoSQL for Java Developers

The  Very  Last  Stepsubscription

▪ You  have  your  final  Observable  representing  your  async  data  flow  

▪ Now  is  time  to  start  emission  and  describe  what  to  do  with  data  in  the  end  

▪ Always  subscribe  !

53

Page 54: NoSQL for Java Developers

The  Very  Last  Stepsubscription

▪ either  a  full  implementation  of  Observer  

▪ or  use  Observable<R>.subscribe  "shortcuts"  :  just  pass  in  an  Action  for  the  part  of  the  API  that  are  relevant  (eg.  just  onNext)

54

Page 55: NoSQL for Java Developers

©2014  Couchbase  Inc. 55

I  Know  Rx-­‐Fu!

Page 56: NoSQL for Java Developers

Q&A  Intermission  2any  questions  at  this  point?

56

Page 57: NoSQL for Java Developers

Putting  That  Into  Actionhow  does  it  weave  into  the                  SDK?

57

Page 58: NoSQL for Java Developers

Putting  That  Into  Action

▪ to  access  the  Async  API,  use  async()  on  both  Cluster  and  Bucket  

▪ now  every  operation  returns  an  Observable<something>  

▪ apply  the  power  of  Rx  to  work  with  your  data  as  a  stream

how  does  it  weave  into  the                  SDK?

58

Page 59: NoSQL for Java Developers

Async  Example"the  2014  club"

59

Page 60: NoSQL for Java Developers

Async  Example

I  have  a  list  of  user  IDs  

get  their  detailed  profile  

and,  for  those  who  registered  last  year  (2014),  

give  them  a  badge  

(make  sure  to  persist  it)  

then  finally  display  the  2014  Club

60

Page 61: NoSQL for Java Developers

Async  Example"the  2014  club"

Observable.from  list  of  IDs  

flatMap  to  get  every  profile  

filter  on  registration  year  

mutate  to  add  the  badge  via  a  map  

flatMap  to  upsert  the  profiles  

map  to  the  stream  of  updated  IDs  

subscribe  in  order  to  print  out   61

Page 62: NoSQL for Java Developers

Async  Example"the  2014  club"

Observable<String> oneYearClub =Observable.from(Arrays.asList("1", "18")) .map(userId -> "user::" + userId) .flatMap(docId -> bucket.async().get(docId)) .filter(userDoc -> userDoc.content().getInt("yearRegistered") == Calendar.getInstance().get(Calendar.YEAR) - 1) .map(userDoc -> { userDoc.content().getArray("badges").add("oneYearClub"); return userDoc; }) .flatMap(userDoc -> bucket.async().upsert(userDoc)) .map(userDoc -> userDoc.id().replace("user::", "")); oneYearClub.subscribe(id -> System.out.println("Welcome user #" + id + " to the One Year Club!"));

62

Page 63: NoSQL for Java Developers

Async  Example"the  2014  club"

Observable<String> oneYearClub =Observable.from(Arrays.asList("1", "18")) .map(userId -> "user::" + userId) .flatMap(docId -> bucket.async().get(docId)) .filter(userDoc -> userDoc.content().getInt("yearRegistered")== Calendar.getInstance().get(Calendar.YEAR) - 1) .map(userDoc -> { userDoc.content().getArray("badges").add("oneYearClub"); return userDoc; }) .flatMap(userDoc -> bucket.async().upsert(userDoc)) .map(userDoc -> userDoc.id().replace("user::", ""));oneYearClub.subscribe(id -> System.out.println("Welcome user #" + id + " to the One Year Club!"));

Observable.from(Arrays.asList("1", "18")) .map(userId -> "user::" + userId)

63

Page 64: NoSQL for Java Developers

Async  Example"the  2014  club"

Observable<String> oneYearClub =Observable.from(Arrays.asList("1", "18")) .map(userId -> "user::" + userId) .flatMap(docId -> bucket.async().get(docId)) .filter(userDoc -> userDoc.content().getInt("yearRegistered")== Calendar.getInstance().get(Calendar.YEAR) - 1) .map(userDoc -> { userDoc.content().getArray("badges").add("oneYearClub"); return userDoc; }) .flatMap(userDoc -> bucket.async().upsert(userDoc)) .map(userDoc -> userDoc.id().replace("user::", ""));oneYearClub.subscribe(id -> System.out.println("Welcome user #" + id + " to the One Year Club!"));

.flatMap(docId -> bucket.async().get(docId))

64

Page 65: NoSQL for Java Developers

Async  Example"the  2014  club"

Observable<String> oneYearClub =Observable.from(Arrays.asList("1", "18")) .map(userId -> "user::" + userId) .flatMap(docId -> bucket.async().get(docId)) .filter(userDoc -> userDoc.content().getInt("yearRegistered") == Calendar.getInstance().get(Calendar.YEAR) - 1) .map(userDoc -> { userDoc.content().getArray("badges").add("oneYearClub"); return userDoc; }) .flatMap(userDoc -> bucket.async().upsert(userDoc)) .map(userDoc -> userDoc.id().replace("user::", ""));oneYearClub.subscribe(id -> System.out.println("Welcome user #" + id + " to the One Year Club!"));

.filter(userDoc -> userDoc.content().getInt("yearRegistered") == Calendar.getInstance().get(Calendar.YEAR) - 1)

65

Page 66: NoSQL for Java Developers

Async  Example"the  2014  club"

Observable<String> oneYearClub =Observable.from(Arrays.asList("1", "18")) .map(userId -> "user::" + userId) .flatMap(docId -> bucket.async().get(docId)) .filter(userDoc -> userDoc.content().getInt("yearRegistered") == Calendar.getInstance().get(Calendar.YEAR) - 1) .map(userDoc -> { userDoc.content().getArray("badges").add("oneYearClub"); return userDoc; }) .flatMap(userDoc -> bucket.async().upsert(userDoc)) .map(userDoc -> userDoc.id().replace("user::", ""));oneYearClub.subscribe(id -> System.out.println("Welcome user #" + id + " to the One Year Club!"));

.map(userDoc -> { userDoc.content().getArray("badges") .add("oneYearClub"); return userDoc; })

66

Page 67: NoSQL for Java Developers

Async  Example"the  2014  club"

Observable<String> oneYearClub =Observable.from(Arrays.asList("1", "18")) .map(userId -> "user::" + userId) .flatMap(docId -> bucket.async().get(docId)) .filter(userDoc -> userDoc.content().getInt("yearRegistered")== Calendar.getInstance().get(Calendar.YEAR) - 1) .map(userDoc -> { userDoc.content().getArray("badges").add("oneYearClub"); return userDoc; }) .flatMap(userDoc -> bucket.async().upsert(userDoc)) .map(userDoc -> userDoc.id().replace("user::", ""));oneYearClub.subscribe(id -> System.out.println("Welcome user #" + id + " to the One Year Club!"));

.flatMap(userDoc -> bucket.async().upsert(userDoc))

67

Page 68: NoSQL for Java Developers

Async  Example"the  2014  club"

Observable<String> oneYearClub =Observable.from(Arrays.asList("1", "18")) .map(userId -> "user::" + userId) .flatMap(docId -> bucket.async().get(docId)) .filter(userDoc -> userDoc.content().getInt("yearRegistered")== Calendar.getInstance().get(Calendar.YEAR) - 1) .map(userDoc -> { userDoc.content().getArray("badges").add("oneYearClub"); return userDoc; }) .flatMap(userDoc -> bucket.async().upsert(userDoc)) .map(userDoc -> userDoc.id().replace("user::", ""));oneYearClub.subscribe(id -> System.out.println("Welcome user #" + id + " to the One Year Club!"));

.map(userDoc -> userDoc.id().replace("user::", ""));

68

Page 69: NoSQL for Java Developers

Async  Example"the  2014  club"

Observable<String> oneYearClub =Observable.from(Arrays.asList("1", "18")) .map(userId -> "user::" + userId) .flatMap(docId -> bucket.async().get(docId)) .filter(userDoc -> userDoc.content().getInt("yearRegistered")== Calendar.getInstance().get(Calendar.YEAR) - 1) .map(userDoc -> { userDoc.content().getArray("badges").add("oneYearClub"); return userDoc; }) .flatMap(userDoc -> bucket.async().upsert(userDoc)) .map(userDoc -> userDoc.id().replace("user::", ""));oneYearClub.subscribe(id -> System.out.println("Welcome user #" + id + " to the One Year Club!"));

oneYearClub.subscribe(id -> System.out.println( "Welcome user #" + id + " to the One Year Club!"));

Observable<String> oneYearClub = ...;

69

Page 70: NoSQL for Java Developers

What  If  there  are  Errors?

70

Page 71: NoSQL for Java Developers

Error-­‐handling  &  Batching

71

Page 72: NoSQL for Java Developers

Error  Handlingthe  basics

▪ Basic  Error  Handling  is  using  Observer.onError(Throwable  t)  

▪ One  can  also  use  the  default  value  pattern  ▪  Observable<T>.onErrorReturn(T  default)

72

Page 73: NoSQL for Java Developers

Error  Handlingmore  advanced

▪ Defer  to  a  backup  stream  on  error  :  ▪ Observable<T>.onErrorResumeNext(Observable<T>  backup)

73

Page 74: NoSQL for Java Developers

Error  Handlingmore  advanced

▪ Defer  to  a  backup  stream  on  error  :  ▪ Observable<T>.onErrorResumeNext(Observable<T>  backup)

74

Page 75: NoSQL for Java Developers

Error  Handlingmore  advanced

▪ Retry  on  error  :  ▪ Observable<T>.retry(retryPredicate)  

▪ retryPredicate  takes  the  number  of  retries  and  the  last  error  to  determine  if  another  retry  should  happen  

▪ if  that's  the  case,  there's  a  re-­‐subscription

75

Page 76: NoSQL for Java Developers

Error  Handlingmore  advanced

▪ Retry  on  error  :  ▪ Observable<T>.retry(retryPredicate)

76

Page 77: NoSQL for Java Developers

Error  Handlingbuild  on  this  for  production-­‐ready  strategies

▪ Exponential  backoff  ▪ using  retry  overrides  to  retry  with  a  delay  that  grows  

▪ Throttling  ▪ when  rate  of  data  creation  >  rate  of  data  consumption  ▪ divide  timeline  into  windows,  only  emit  first/last  item  of  each  window  

▪ Concept  of  backpressure  ▪ when  rate  of  data  creation  >  rate  of  data  consumption  ▪ a  way  to  let  the  Observer  signal  source  at  what  pace  data  production  is  manageable

77

Page 78: NoSQL for Java Developers

Batching"where  is  bulk  get  gone?"

78

Page 79: NoSQL for Java Developers

Batching"where  is  bulk  get  gone?"

▪ Now  relying  on  RxJava  primitives  for  bulk  

▪ Underlying  RingBuffer  +  Netty  is  pretty  capable  for  rapid-­‐burst  requests  

▪ In  a  word,  use  Observable.from(collection  of  keys)  and  flatMap  to  a  get

79

Page 80: NoSQL for Java Developers

Batching"where  is  bulk  get  gone?"

Observable<JsonDocument>  allDocs  =  Observable.from(allKeys)          .flatMap(new  Func1<String,  JsonDocument>()  {                  public  Observable<JsonDocument>  call(String  id)  {                          return  bucket.async().get(id);                  }          });

80

Page 81: NoSQL for Java Developers

Batching"where  is  bulk  get  gone?"

Observable<JsonDocument>  allDocs  =  Observable.from(allKeys)          .flatMap(new  Func1<String,  JsonDocument>()  {                  public  Observable<JsonDocument>  call(String  id)  {                          return  bucket.async().get(id);                  }          });  

The  best  thing  is,  it  is  now  possible  on  every  operations,  not  just  get!81

Page 82: NoSQL for Java Developers

Querying  JSON  with  N1QLdeveloper  preview

82

Page 83: NoSQL for Java Developers

Let's do a Live Demo!

83

Page 84: NoSQL for Java Developers

*  Totally  made  with  Special  Effects

*

Let's do a Live Demo!

84

Page 85: NoSQL for Java Developers

Plans  for  the  futurea  glimpse  at  things  to  come

85

Page 86: NoSQL for Java Developers

2.1"Overall,  More  Goodness"  

Geo,  N1QL,  ...  +  lots  of  bug  fixes

86

Page 87: NoSQL for Java Developers

Finalizing  N1QL  Supportgive  your  feedback  on  developer  preview

87

Page 88: NoSQL for Java Developers

Spring  Data  Connector,  2.0porting  the  adapter  to  the  new  client

88

Page 89: NoSQL for Java Developers

Thank You!the End

89

Page 90: NoSQL for Java Developers

Final  Q&A?

90

Page 91: NoSQL for Java Developers

via  Wikipedia  via  Wikimedia  via  Flickr  via  Wikimedia  ,  still  from  the  motion  picture  

CC  BY-­‐SA  David  Shankbone  CC  BY-­‐SA  Donovan  Govan  

CC  BY-­‐ND  NCinDC  CC  BY  Evan  Lovely  

all  rights  reserved  Warner  Bros

Diver  Kitchen  Funnel    

Then&Now    Computer-­‐Using  Cat  

"The  Matrix",  

End  Credits

91