28
DataStax Java Driver Unleashed!

C* Summit 2013: Java and .NET Client Drivers - Cassandra Developments on Fire by Michael Figuiere and Patrick McFadin

Embed Size (px)

DESCRIPTION

Speakers: Michael Figuiere and Patrick McFadin, Principal Solutions Architect at DataStax Cassandra 1.2 finalizes CQL3 and introduces a new binary protocol for client/server communication. These two components are the foundation of the new line of drivers developed by DataStax. Based on years of experience with Cassandra, these new drivers for Java, .Net and Python come with an asynchronous and lightweight architecture, a clean and simple API, a standardized way to discover nodes and to manage load balancing and fail over. This presentation will give an in depth look at these new drivers which will make your Cassandra-based applications even more robust, efficient and simple to write.

Citation preview

Page 1: C* Summit 2013: Java and .NET Client Drivers - Cassandra Developments on Fire by Michael Figuiere and Patrick McFadin

DataStax Java Driver Unleashed!

Page 2: C* Summit 2013: Java and .NET Client Drivers - Cassandra Developments on Fire by Michael Figuiere and Patrick McFadin

CQL The new face of Cassandra* CQL3

* Simpler Data Model using Denormalized Tables

* SQL-like Query Language

* Schema Definition

* CQL Native Protocol

* Introduced in Cassandra 1.2

* Designed for CQL3

* Thrift will keep being supported by Cassandra

Page 3: C* Summit 2013: Java and .NET Client Drivers - Cassandra Developments on Fire by Michael Figuiere and Patrick McFadin

* Cassandra lives closer to users and application

* Data model expresses your application intent

* Not made for generalizable queries

* Key to a successful project

CQL Data Model Overview

Page 4: C* Summit 2013: Java and .NET Client Drivers - Cassandra Developments on Fire by Michael Figuiere and Patrick McFadin

CQL3 Data Model

Data duplicated over several tables

CQL3 Query Language comes with a new Data

Model abstraction made of denormalized, statically defined tables

Page 5: C* Summit 2013: Java and .NET Client Drivers - Cassandra Developments on Fire by Michael Figuiere and Patrick McFadin

CQL3 Data Model

gmason

user_id

1735

tweet_id

phenry

author

Give me liberty or give me death

body

PartitionKey

gmason 1742 gwashington I chopped down the cherry tree

ahamilton 1767 jadams A government of laws, not men

ahamilton 1794 gwashington I chopped down the cherry tree

ClusteringKey

Timeline Table

Page 6: C* Summit 2013: Java and .NET Client Drivers - Cassandra Developments on Fire by Michael Figuiere and Patrick McFadin

CQL3 Data Model

gmason

user_id

1735

tweet_id

phenry

author

Give me liberty or give me death

body

PartitionKey

gmason 1742 gwashington I chopped down the cherry tree

ahamilton 1767 jadams A government of laws, not men

ahamilton 1794 gwashington I chopped down the cherry tree

ClusteringKey

Timeline Table

CREATE TABLE timeline ( user_id varchar, tweet_id timeuuid, author varchar, body varchar, PRIMARY KEY (user_id, tweet_id));

CQL

Page 7: C* Summit 2013: Java and .NET Client Drivers - Cassandra Developments on Fire by Michael Figuiere and Patrick McFadin

DB API

CQL Native Protocol

CQL API OO API

Next Generation Driver

New Driver Architecture

Page 8: C* Summit 2013: Java and .NET Client Drivers - Cassandra Developments on Fire by Michael Figuiere and Patrick McFadin

* Reference Implementation

* Asynchronous architecture based on Netty

* Prepared Statements Support

* Automatic Fail-over

* Node Discovery

* Cassandra Tracing Support

* Tunable Policies

Java Driver Overview

Page 9: C* Summit 2013: Java and .NET Client Drivers - Cassandra Developments on Fire by Michael Figuiere and Patrick McFadin

Client

WithoutRequest Pipelining

Cassandra

Client CassandraWith

Request Pipelining

Request Pipelining

Page 10: C* Summit 2013: Java and .NET Client Drivers - Cassandra Developments on Fire by Michael Figuiere and Patrick McFadin

Client

WithoutNotifications

WithNotifications

NodeNode

Node

Client

NodeNode

Node

Notifications

Page 11: C* Summit 2013: Java and .NET Client Drivers - Cassandra Developments on Fire by Michael Figuiere and Patrick McFadin

ClientThread

Node

Node

Node

ClientThread

ClientThread

Node

Driver

Asynchronous Architecture

Page 12: C* Summit 2013: Java and .NET Client Drivers - Cassandra Developments on Fire by Michael Figuiere and Patrick McFadin

1

23

45

6ClientThread

Node

Node

Node

ClientThread

ClientThread

Node

Driver

Asynchronous Architecture

Page 13: C* Summit 2013: Java and .NET Client Drivers - Cassandra Developments on Fire by Michael Figuiere and Patrick McFadin

contactPoints = {“10.0.0.1”,”10.0.0.2”}

keyspace = “videodb”

public VideoDbBasicImpl(List<String> contactPoints, String keyspace) {

cluster = Cluster .builder() .addContactPoints(! contactPoints.toArray(new String[contactPoints.size()])) .build();

session = cluster.connect(keyspace); }

Creating a Basic Connection

Page 14: C* Summit 2013: Java and .NET Client Drivers - Cassandra Developments on Fire by Michael Figuiere and Patrick McFadin

public void setUserByUsingString(User user) {

StringBuffer userInsert = new StringBuffer( "INSERT INTO users (username, firstname, lastname, email, password, created_date) VALUES (");

userInsert.append("'" + user.getUsername() + "'"); userInsert.append("'" + user.getFirstname() + "'"); userInsert.append("'" + user.getLastname() + "'"); userInsert.append("'" + user.getEmail() + "'"); userInsert.append("'" + user.getPassword() + "'"); userInsert.append("'" + user.getCreated_date().toString() + "'"); userInsert.append(")");

session.execute(userInsert.toString());}

Basic write using insert

Page 15: C* Summit 2013: Java and .NET Client Drivers - Cassandra Developments on Fire by Michael Figuiere and Patrick McFadin

! public User getUserByUsernameUsingString(String username) {

! ! User user = new User();

! ! ResultSet rs = session.execute("SELECT * FROM users WHERE username = '"! ! ! ! + username + "'");

! ! // A result set has Rows which can be iterated over! ! for (Row row : rs) {! ! ! user.setUsername(username);! ! ! user.setFirstname(row.getString("firstname"));! ! ! user.setLastname(row.getString("lastname"));! ! ! user.setEmail(row.getString("email"));! ! ! user.setPassword(row.getString("Password"));! ! ! user.setCreated_date(row.getDate("created_date"));! ! }

! ! return user;

! }

Basic Read using Select

Page 16: C* Summit 2013: Java and .NET Client Drivers - Cassandra Developments on Fire by Michael Figuiere and Patrick McFadin

public void setUserByPreparedStatement(User user) {

BoundStatement bs = setUser.bind();

bs.setString("username", user.getUsername()); bs.setString("firstname", user.getFirstname()); bs.setString("lastname", user.getLastname()); bs.setString("email", user.getEmail()); bs.setString("password", user.getPassword()); bs.setDate("created_date", user.getCreated_date());! ! session.execute(bs);

}

Writing with Prepared Statements

Page 17: C* Summit 2013: Java and .NET Client Drivers - Cassandra Developments on Fire by Michael Figuiere and Patrick McFadin

public List<Video> getVideosByUsernameUsingAsyncRead(String username) {

BoundStatement bs = getVideosByUsernamePreparedStatement.bind();

List<ResultSetFuture> futures = new ArrayList<ResultSetFuture>(); List<Video> videos = new ArrayList<Video>();

bs.setString("username", username);

for (Row row : session.execute(bs)) {

futures.add(session.executeAsync(getVideoByIDPreparedStatement .bind(row.getUUID("videoid")))); }

for (ResultSetFuture future : futures) {

for (Row row : future.getUninterruptibly()) { Video video = new Video(); video.setVideoid(row.getUUID("videoid")); videos.add(video); } } return videos;}

Asynchronous Read

Page 18: C* Summit 2013: Java and .NET Client Drivers - Cassandra Developments on Fire by Michael Figuiere and Patrick McFadin

for (String tag : tags) { BoundStatement bs = getVideosByTagPreparedStatement.bind(tag); final ResultSetFuture future = session.executeAsync(bs);

future.addListener(new Runnable() {

public void run() { for (Row row : future.getUninterruptibly()) { UUID videoId = row.getUUID("videoid");

if (videoIds.putIfAbsent(videoId, PRESENT) == null) {

videoFutures.add(session .executeAsync(getVideoByIDPreparedStatement .bind(videoId))); } } } }, executor);}

Performing a Read with a Listener

Page 19: C* Summit 2013: Java and .NET Client Drivers - Cassandra Developments on Fire by Michael Figuiere and Patrick McFadin

public Video getVideoByIdUsingQueryBuilder(String videoId) {

Video video = new Video();

Query query = select().all().from("videodb", "videos") .where(eq("videoId", videoId)).limit(10);

query.setConsistencyLevel(ConsistencyLevel.ONE);

ResultSet rs = session.execute(query); for (Row row : rs) {

video.setVideoid(row.getUUID("videoid")); video.setVideoname(row.getString("videoName")); video.setUsername(row.getString("username")); video.setDescription(row.getString("description")); } return video;}

Using the Query Builder

Page 20: C* Summit 2013: Java and .NET Client Drivers - Cassandra Developments on Fire by Michael Figuiere and Patrick McFadin

Load Balancing

Policy

Node

Node

Node

Health Monitor

Load Balancing and Failover

ReconnectionNotifications

Client

RetryPolicy

ResponseDispatcher

1 3

2

4

5

6

Page 21: C* Summit 2013: Java and .NET Client Drivers - Cassandra Developments on Fire by Michael Figuiere and Patrick McFadin

Node

Node

NodeClient

Datacenter B

Node

Node

Node

Client

Client

Client

Client

Client

Datacenter ALocal nodes are queried first, if non are available, the request will be sent to a remote node.

Multi Datacenter Load Balancing

Page 22: C* Summit 2013: Java and .NET Client Drivers - Cassandra Developments on Fire by Michael Figuiere and Patrick McFadin

Multi Datacenter Load Balancing

Node

Node

ReplicaNode

Client Node

NodeReplica

Replica

Nodes that own a Replica of the data being read or written by the query will be contacted first.

Page 23: C* Summit 2013: Java and .NET Client Drivers - Cassandra Developments on Fire by Michael Figuiere and Patrick McFadin

contactPoints = {“10.0.0.1”,”10.0.0.2”}

keyspace = “videodb”

public VideoDbBasicImpl(List<String> contactPoints, String keyspace) {

cluster = Cluster .builder() .addContactPoints(! contactPoints.toArray(new String[contactPoints.size()])) .withLoadBalancingPolicy(Policies.defaultLoadBalancingPolicy()) .build();

session = cluster.connect(keyspace); }

Create your own policy!

Add a Load Balancing Policy

Page 24: C* Summit 2013: Java and .NET Client Drivers - Cassandra Developments on Fire by Michael Figuiere and Patrick McFadin

Client

If the requested Consistency Level cannot be reached (QUORUM here), a second request with a lower CL is sent automatically.

Node

Node Replica

Replica

NodeReplica

Downgrading Retry Policy

Page 25: C* Summit 2013: Java and .NET Client Drivers - Cassandra Developments on Fire by Michael Figuiere and Patrick McFadin

contactPoints = {“10.0.0.1”,”10.0.0.2”}

keyspace = “videodb”

public VideoDbBasicImpl(List<String> contactPoints, String keyspace) {

cluster = Cluster .builder() .addContactPoints(! contactPoints.toArray(new String[contactPoints.size()])) .withLoadBalancingPolicy(Policies.defaultLoadBalancingPolicy()) .withRetryPolicy(Policies.defaultRetryPolicy()) .build();

session = cluster.connect(keyspace); }

Create your own policy!

Specify a Retry Policy

Page 26: C* Summit 2013: Java and .NET Client Drivers - Cassandra Developments on Fire by Michael Figuiere and Patrick McFadin

public enum Gender {

@EnumValue("m") MALE, @EnumValue("f") FEMALE;}

@Table(name = "user")public class User { @PartitionKey @Column(name = "user_id") private String userId; private String name; private String email; private Gender gender;}

Object Mapping

Page 27: C* Summit 2013: Java and .NET Client Drivers - Cassandra Developments on Fire by Michael Figuiere and Patrick McFadin

DevCenter an IDE for Developers

Page 28: C* Summit 2013: Java and .NET Client Drivers - Cassandra Developments on Fire by Michael Figuiere and Patrick McFadin

Questions ?