More Related Content Similar to YaJug - Cassandra for Java Developers Similar to YaJug - Cassandra for Java Developers (20) More from Michaël Figuière More from Michaël Figuière (18) YaJug - Cassandra for Java Developers1. Cassandra for Java Developers
DataStax Driver & DevCenter
Michaël Figuière
Drivers & Developer Tools Architect
2. Client / Server Communication
© 2014 DataStax, All Rights Reserved.
2
Client
Client
Client
Client
Node
Node Replica
Replica
Replica
Node
Coordinator node:
Forwards all R/W requests
to corresponding replicas
3. Request Pipelining
© 2014 DataStax, All Rights Reserved.
3
Client
Without
Request Pipelining
Cassandra
Client Cassandra
With
Request Pipelining
4. Notifications
© 2014 DataStax, All Rights Reserved.
4
Client
Without
Notifications
With
Notifications
Node
Node
Node
Client
Node
Node
Node
7. Failover
© 2014 DataStax, All Rights Reserved.
7
Client
Thread
Node
Node
Node
Client
Thread
Client
Thread
Node
7
2
4
3 5 1
Driver
6
8. 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
© 2014 DataStax, All Rights Reserved.
8
9. DataCenter Aware Balancing
© 2014 DataStax, All Rights Reserved.
9
Node
Node
Client Node
Node
Datacenter B
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.
10. Token Aware Balancing
© 2014 DataStax, All Rights Reserved.
Nodes that own a Replica
of the PK being read or
written by the query will
be contacted first.
10
Node
Node
Replica
Node
Client
Replica
Replica
Partition Key will be
inferred from Prepared
Statements metadata
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. 11
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', 'john@doe.com')"
);
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. 12
13. Read
ResultSet resultSet = session.execute(
Session is a thread safe
object. A singleton should
be instantiated at startup
"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>
© 2014 DataStax, All Rights Reserved. 13
14. Write with Prepared Statements
PreparedStatement objects
are also threadsafe, just create
a singleton at startup
PreparedStatement insertUser = session.prepare(
"INSERT INTO user (user_id, name, email)
VALUES (?, ?, ?)"
);
BoundStatement statement = insertUser
.bind(12345, "johndoe", "john@doe.com")
.setConsistencyLevel(ConsistencyLevel.QUORUM);
session.execute(statement);
Parameters can
be named as well
BoundStatement
is a stateful, NON
threadsafe object
Consistency Level can be
set for each statement
© 2014 DataStax, All Rights Reserved. 14
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. 15
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. 16
17. Query Builder
import static of
QueryBuilder is required in
order to use the DSL
import static
com.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", "john@doe.com");
session.execute(insert);
© 2014 DataStax, All Rights Reserved. 17
18. 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
© 2014 DataStax, All Rights Reserved.
18
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. 19
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. 20
21. Basic Object Mapping
MappingManager
manager
=
new
MappingManager(session);
Mapper
mapper
=
manager.mapper(User.class);
UserProfile
myProfile
=
mapper.get("xyz@example.com");
ListenableFuture
saveFuture
=
mapper.saveAsync(anotherProfile);
mapper.delete("xyz@example.com");
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. 21
22. Accessors
@Accessor
interface
UserAccessor
{
@Query("SELECT
*
FROM
user_profiles
LIMIT
:max")
Result<User>
firstN(@Param("max")
int
limit);
}
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
© 2014 DataStax, All Rights Reserved. 22
24. We’re Hiring!
github.com/datastax
blog.datastax.com
@mfiguiere
…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…