Upload
michael-figuiere
View
330
Download
2
Embed Size (px)
DESCRIPTION
Citation preview
Cassandra for Java DevelopersDataStax Driver & DevCenter
Michaël FiguièreDrivers & Developer Tools Architect
© 2014 DataStax, All Rights Reserved.
Client / Server Communication
2
Client
Client
Client
Client
Node
Node Replica
Replica
ReplicaNode
Coordinator node:Forwards all R/W requeststo corresponding replicas
© 2014 DataStax, All Rights Reserved.
Request Pipelining
3
Client
WithoutRequest Pipelining
Cassandra
Client CassandraWith
Request Pipelining
© 2014 DataStax, All Rights Reserved.
Notifications
4
Client
WithoutNotifications
WithNotifications
NodeNode
Node
Client
NodeNode
Node
© 2014 DataStax, All Rights Reserved.
Asynchronous Driver Architecture
5
ClientThread
Node
Node
Node
ClientThread
ClientThread
Node
Driver
© 2014 DataStax, All Rights Reserved.
Asynchronous Driver Architecture
6
ClientThread
Node
Node
Node
ClientThread
ClientThread
Node
6
23
45
1
Driver
© 2014 DataStax, All Rights Reserved.
Failover
7
ClientThread
Node
Node
Node
ClientThread
ClientThread
Node
7
2
4
531
Driver
6
© 2014 DataStax, All Rights Reserved.
Java Driver Highlights
• Reference implementation• Asynchronous architecture based on Netty• Prepared Statements Support• Automatic Failover• Node Discovery• Tunable Load Balancing
• Round Robin, Latency Awareness, Multi Data Centers, Replica Awareness
• Cassandra Tracing Support• Compression & SSL
8
© 2014 DataStax, All Rights Reserved.
DataCenter Aware Balancing
9
Node
Node
NodeClient
Datacenter B
Node
Node
Node
Client
Client
Client
Client
Client
Datacenter A
Local nodes are queried first, if non are available, the request could be sent to a remote node.
© 2014 DataStax, All Rights Reserved.
Token Aware Balancing
10
Nodes that own a Replica of the PK being read or written by the query will be contacted first.
Node
Node
ReplicaNode
Client
Replica
Replica
Partition Key will be inferred from Prepared Statements metadata
© 2014 DataStax, All Rights Reserved. 11
DataStax Driver in Practice
<dependency> <groupId>com.datastax.cassandra</groupId> <artifactId>cassandra-‐driver-‐core</artifactId> <version>2.1.0</version>
</dependency>
Available in Maven Central. Depends on Netty, Guava, Metrics
Supports Apache Cassandra 1.2 to 2.1
© 2014 DataStax, All Rights Reserved. 12
Connect and Write
Cluster cluster = Cluster.builder() .addContactPoints("10.1.2.5", "cassandra_node3") .build();
Session session = cluster.connect(“my_keyspace");
session.execute( "INSERT INTO user (user_id, name, email) VALUES (12345, 'johndoe', '[email protected]')");
The rest of the nodes will be discovered by the driver
A keyspace is just like a schema in the SQL world
© 2014 DataStax, All Rights Reserved. 13
Read
ResultSet resultSet = session.execute( "SELECT * FROM user WHERE user_id IN (1,8,13)");
List<Row> rows = resultSet.all(); for (Row row : rows) {
String userId = row.getString("user_id"); String name = row.getString("name"); String email = row.getString("email");}
Actually ResultSet also implements Iterable<Row>
Session is a thread safe object. A singleton should be instantiated at startup
© 2014 DataStax, All Rights Reserved. 14
Write with Prepared Statements
PreparedStatement insertUser = session.prepare( "INSERT INTO user (user_id, name, email) VALUES (?, ?, ?)");
BoundStatement statement = insertUser .bind(12345, "johndoe", "[email protected]") .setConsistencyLevel(ConsistencyLevel.QUORUM);
session.execute(statement);
Parameters can be named as well
PreparedStatement objects are also threadsafe, just create a singleton at startup
BoundStatement is a stateful, NON threadsafe object
Consistency Level can be set for each statement
© 2014 DataStax, All Rights Reserved. 15
Asynchronous Read
ResultSetFuture future = session.executeAsync( "SELECT * FROM user WHERE user_id IN (1,2,3)");
ResultSet resultSet = future.get();
List<Row> rows = resultSet.all(); for (Row row : rows) {
String userId = row.getString("user_id"); String name = row.getString("name"); String email = row.getString("email");}
Will not block. Returns immediately
Will block until less all the connections are busy
© 2014 DataStax, All Rights Reserved. 16
Asynchronous Read with Callbacks
ResultSetFuture future = session.executeAsync( "SELECT * FROM user WHERE user_id IN (1,2,3)");
future.addListener(new Runnable() { public void run() { // Process the results here }}, executor);
ResultSetFuture implements Guava’s ListenableFuture
executor = Executors .newCachedThreadPool();
executor = MoreExecutors .sameThreadExecutor();
Only if your listener code is trivial and non blocking as it’ll be executed in the IO Thread
…Or any thread pool that you prefer
© 2014 DataStax, All Rights Reserved. 17
Query Builder
import staticcom.datastax.driver.core.querybuilder.QueryBuilder.*;
Statement selectAll = select().all().from("user").where(eq("user_id", userId));
session.execute(selectAll);
Statement insert = insertInto("user") .value("user_id", 2) .value("name", "johndoe") .value("email", "[email protected]");
session.execute(insert);
import static of QueryBuilder is required in order to use the DSL
© 2014 DataStax, All Rights Reserved.
Object Mapper
• Avoid boilerplate for common use cases
• Map Objects to Statements and ResultSets to Objects
• Do NOT hide Cassandra from the developer
• No “clever tricks” à la Hibernate
• Not JPA compatible, but JPA-ish API
18
© 2014 DataStax, All Rights Reserved. 19
Object Mapper in Practice
<dependency> <groupId>com.datastax.cassandra</groupId> <artifactId>cassandra-‐driver-‐mapping</artifactId> <version>2.1.0</version>
</dependency>
Additional artifact for object mapping
Available from Driver 2.1.0
© 2014 DataStax, All Rights Reserved. 20
Basic Object Mapping
CREATE TYPE address ( street text, city text, zip int ); CREATE TABLE users ( email text PRIMARY KEY, address address );
@UDT(keyspace = "ks", name = "address") public class Address { private String street; private String city; private int zip; // getters and setters omitted... } @Table(keyspace = "ks", name = "users") public class User { @PartitionKey private String email; private Address address; // getters and setters omitted... }
© 2014 DataStax, All Rights Reserved. 21
Basic Object Mapping
MappingManager manager = new MappingManager(session);
Mapper mapper = manager.mapper(User.class); UserProfile myProfile = mapper.get("[email protected]");
ListenableFuture saveFuture = mapper.saveAsync(anotherProfile);
mapper.delete("[email protected]");
Mapper, just like Session, is a thread-safe object. Create a singleton at startup.
get() returns a mapped row for the given Primary Key
ListenableFuture from Guava. Completed when the write is acknowledged.
© 2014 DataStax, All Rights Reserved. 22
Accessors
UserAccessor accessor = manager.createAccessor(UserAccessor.class); Result<User> users = accessor.firstN(10);
for (User user : users) { System.out.println( profile.getAddress().getZip() ); }
Result is like ResultSet but specialized for a mapped class…
…so we iterate over it just like we would with a ResultSet
@Accessor interface UserAccessor { @Query("SELECT * FROM user_profiles LIMIT :max") Result<User> firstN(@Param("max") int limit); }
DataStax DevCenterDemo
We’re Hiring!
@mfiguiere
blog.datastax.com
github.com/datastax
…seriously I really mean it, so if you’re passionated about beautiful technology feel free to talk to me!
Work remotely from anywhere in Europe, even Luxembourg…