SlideShare ist ein Scribd-Unternehmen logo
1 von 39
Downloaden Sie, um offline zu lesen
Building awesome applications with Apache 
Cassandra 
Christopher Batey 
@chbatey 
©2013 DataStax Confidential. Do not distribute without consent. 
1
Who am I? 
•Technical Evangelist for Apache Cassandra 
• Founder of Stubbed Cassandra 
• Help out Apache Cassandra users 
• Previous: Cassandra backed apps at BSkyB 
@chbatey
@chbatey 
Overview 
• Topics covered 
• Cassandra overview 
• Customer events example 
• DataStax Java Driver 
• Java Mapping API 
• Other features 
• Light weight transactions 
• Load balancing 
• Reconnection policies
@chbatey 
Overview 
• Topics covered 
• Cassandra overview 
• Customer events example 
• DataStax Java Driver 
• Java Mapping API 
• Other features 
• Light weight transactions 
• Load balancing 
• Reconnection policies 
• Not covered 
• Cassandra read and write paths 
• Cassandra failure nodes
Common use cases 
•Ordered data such as time series 
•Event stores 
•Financial transactions 
•Sensor data e.g IoT 
@chbatey
Common use cases 
•Ordered data such as time series 
•Event stores 
•Financial transactions 
•Sensor data e.g IoT 
•Non functional requirements: 
• Linear scalability 
• High throughout durable writes 
•Multi datacenter including active-active 
•Analytics without ETL 
@chbatey
Cassandra overview 
@chbatey
Cassandra 
Cassandra 
• Distributed master less 
database (Dynamo) 
• Column family data model 
(Google BigTable)
Cassandra 
Europe 
• Distributed master less 
database (Dynamo) 
• Column family data model 
(Google BigTable) 
• Multi data centre replication 
built in from the start 
USA
Cassandra 
Online 
• Distributed master less 
database (Dynamo) 
• Column family data model 
(Google BigTable) 
• Multi data centre replication 
built in from the start 
• Analytics with Apache 
Spark 
Analytics
Replication 
WRITE 
CL = 1 We have replication! 
DC1 DC2 
client 
C 
RC 
RF3 RF3
Tunable Consistency 
• Data is replicated N times 
• Every query that you execute you give a consistency 
• ALL 
• QUORUM 
• LOCAL_QUORUM 
• ONE 
• Christos Kalantzis Eventual Consistency != Hopeful Consistency: http://youtu.be/ 
A6qzx_HE3EU?list=PLqcm6qE9lgKJzVvwHprow9h7KMpb5hcUU 
@chbatey
CQL 
•Cassandra Query Language 
•SQL like query language 
•Keyspace – analogous to a schema 
• The keyspace determines the RF (replication factor) 
•Table – looks like a SQL Table CREATE TABLE scores ( 
@chbatey 
name text, 
score int, 
date timestamp, 
PRIMARY KEY (name, score) 
); 
INSERT INTO scores (name, score, date) 
VALUES ('bob', 42, '2012-06-24'); 
INSERT INTO scores (name, score, date) 
VALUES ('bob', 47, '2012-06-25'); 
SELECT date, score FROM scores WHERE name='bob' AND score >= 40;
Example Time: Customer event store 
@chbatey
An example: Customer event store 
• Customer event 
• customer_id - ChrisBatey 
• staff_id - Charlie 
• store_type Website, PhoneApp, Phone, Retail 
• event_type - login, logout, add_to_basket, 
remove_from_basket, buy_item 
• time 
• tags
Requirements 
• Get all events 
• Get all events for a particular customer 
• As above for a time slice
Modelling in Cassandra 
CREATE TABLE customer_events( 
customer_id text, 
staff_id text, 
Partition Key 
time timeuuid, 
store_type text, 
event_type text, 
tags map<text, text>, 
PRIMARY KEY ((customer_id), time)); 
Clustering Column(s)
How it is stored on disk 
customer 
_id 
time event_type store_type tags 
charles 2014-11-18 16:52:04 basket_add online {'item': 'coffee'} 
charles 2014-11-18 16:53:00 basket_add online {'item': ‘wine'} 
charles 2014-11-18 16:53:09 logout online {} 
chbatey 2014-11-18 16:52:21 login online {} 
chbatey 2014-11-18 16:53:21 basket_add online {'item': 'coffee'} 
chbatey 2014-11-18 16:54:00 basket_add online {'item': 'cheese'} 
charles 
event_type 
basket_add 
staff_id 
n/a 
store_type 
online 
tags:item 
coffee 
event_type 
basket_add 
staff_id 
n/a 
store_type 
online 
tags:item 
wine 
event_type 
logout 
staff_id 
n/a 
store_type 
online 
chbatey 
event_type 
login 
staff_id 
n/a 
store_type 
online 
event_type 
basket_add 
staff_id 
n/a 
store_type 
online 
tags:item 
coffee 
event_type 
basket_add 
staff_id 
n/a 
store_type 
online 
tags:item 
cheese
DataStax Java Driver 
• Open source 
@chbatey
@chbatey 
Get all the events 
public List<CustomerEvent> getAllCustomerEvents() { 
return session.execute("select * from customers.customer_events") 
.all().stream() 
.map(mapCustomerEvent()) 
.collect(Collectors.toList()); 
} 
private Function<Row, CustomerEvent> mapCustomerEvent() { 
return row -> new CustomerEvent( 
row.getString("customer_id"), 
row.getUUID("time"), 
row.getString("staff_id"), 
row.getString("store_type"), 
row.getString("event_type"), 
row.getMap("tags", String.class, String.class)); 
}
All events for a particular customer 
private PreparedStatement getEventsForCustomer; 
@PostConstruct 
public void prepareSatements() { 
getEventsForCustomer = 
session.prepare("select * from customers.customer_events where customer_id = ?"); 
} 
public List<CustomerEvent> getCustomerEvents(String customerId) { 
BoundStatement boundStatement = getEventsForCustomer.bind(customerId); 
return session.execute(boundStatement) 
.all().stream() 
.map(mapCustomerEvent()) 
.collect(Collectors.toList()); 
@chbatey 
}
Customer events for a time slice 
public List<CustomerEvent> getCustomerEventsForTime(String customerId, long startTime, 
long endTime) { 
Select.Where getCustomers = QueryBuilder.select() 
.all() 
.from("customers", "customer_events") 
.where(eq("customer_id", customerId)) 
.and(gt("time", UUIDs.startOf(startTime))) 
.and(lt("time", UUIDs.endOf(endTime))); 
return session.execute(getCustomers).all().stream() 
.map(mapCustomerEvent()) 
.collect(Collectors.toList()); 
@chbatey 
}
@chbatey 
Mapping API 
@Table(keyspace = "customers", name = "customer_events") 
public class CustomerEvent { 
@PartitionKey 
@Column(name = "customer_id") 
private String customerId; 
@ClusteringColumn 
private UUID time; 
@Column(name = "staff_id") 
private String staffId; 
@Column(name = "store_type") 
private String storeType; 
@Column(name = "event_type") 
private String eventType; 
private Map<String, String> tags; 
// ctr / getters etc 
}
@chbatey 
Mapping API 
@Accessor 
public interface CustomerEventDao { 
@Query("select * from customers.customer_events where customer_id = :customerId") 
Result<CustomerEvent> getCustomerEvents(String customerId); 
@Query("select * from customers.customer_events") 
Result<CustomerEvent> getAllCustomerEvents(); 
@Query("select * from customers.customer_events where customer_id = :customerId 
and time > minTimeuuid(:startTime) and time < maxTimeuuid(:endTime)") 
Result<CustomerEvent> getCustomerEventsForTime(String customerId, long startTime, 
long endTime); 
} 
@Bean 
public CustomerEventDao customerEventDao() { 
MappingManager mappingManager = new MappingManager(session); 
return mappingManager.createAccessor(CustomerEventDao.class); 
}
Adding some type safety 
public enum StoreType { 
ONLINE, RETAIL, FRANCHISE, MOBILE 
@chbatey 
} 
@Table(keyspace = "customers", name = "customer_events") 
public class CustomerEvent { 
@PartitionKey 
@Column(name = "customer_id") 
private String customerId; 
@ClusteringColumn() 
private UUID time; 
@Column(name = "staff_id") 
private String staffId; 
@Column(name = "store_type") 
@Enumerated(EnumType.STRING) // could be EnumType.ORDINAL 
private StoreType storeType;
@chbatey 
User defined types 
create TYPE store (name text, type text, postcode text) ; 
CREATE TABLE customer_events_type( 
customer_id text, 
staff_id text, 
time timeuuid, 
store frozen<store>, 
event_type text, 
tags map<text, text>, 
PRIMARY KEY ((customer_id), time));
Mapping user defined types 
@chbatey 
@UDT(keyspace = "customers", name = "store") 
public class Store { 
private String name; 
private StoreType type; 
private String postcode; 
// getters etc 
} 
@Table(keyspace = "customers", name = "customer_events_type") 
public class CustomerEventType { 
@PartitionKey 
@Column(name = "customer_id") 
private String customerId; 
@ClusteringColumn() 
private UUID time; 
@Column(name = "staff_id") 
private String staffId; 
@Frozen 
private Store store; 
@Column(name = "event_type") 
private String eventType; 
private Map<String, String> tags;
Mapping user defined types 
@chbatey 
@UDT(keyspace = "customers", name = "store") 
public class Store { 
private String name; 
private StoreType type; 
private String postcode; 
// getters etc 
} 
@Table(keyspace = "customers", name = "customer_events_type") 
public class CustomerEventType { 
@PartitionKey 
@Column(name = "customer_id") 
private String customerId; 
@ClusteringColumn() 
private UUID time; 
@Column(name = "staff_id") 
private String staffId; 
@Frozen 
private Store store; 
@Column(name = "event_type") 
private String eventType; 
private Map<String, String> tags; 
@Query("select * from customers.customer_events_type") 
Result<CustomerEventType> getAllCustomerEventsWithStoreType();
What else can I do? 
@chbatey
Lightweight Transactions (LWT) 
Consequences of Lightweight Transactions 
4 round trips vs. 1 for normal updates (uses Paxos algorithm) 
Operations are done on a per-partition basis 
Will be going across data centres to obtain consensus (unless you use 
LOCAL_SERIAL consistency) 
Cassandra user will need read and write access i.e. you get back the row! 
Great for 1% your app, but eventual consistency is still your friend! 
@chbatey
Company Confidential 
@chbatey 
Batch Statements 
BEGIN BATCH 
INSERT INTO users (userID, password, name) VALUES ('user2', 'ch@ngem3b', 'second user') 
UPDATE users SET password = 'ps22dhds' WHERE userID = 'user2' 
INSERT INTO users (userID, password) VALUES ('user3', 'ch@ngem3c') 
DELETE name FROM users WHERE userID = 'user2’ 
APPLY BATCH; 
BATCH statement combines multiple INSERT, UPDATE, and DELETE statements into a single logical 
operation 
Atomic operation 
If any statement in the batch succeeds, all will 
No batch isolation 
Other “transactions” can read and write data being affected by a partially executed batch 
© 2014 DataStax, All Rights Reserved.
Batch Statements with LWT 
BEGIN BATCH 
UPDATE foo SET z = 1 WHERE x = 'a' AND y = 1; 
UPDATE foo SET z = 2 WHERE x = 'a' AND y = 2 IF t = 4; 
Company Confidential 
@chbatey 
APPLY BATCH; 
Allows you to group multiple conditional updates in a batch as long as all 
those updates apply to the same partition 
© 2014 DataStax, All Rights Reserved.
Load balancing 
• Data centre aware policy 
• Token aware policy 
• Latency aware policy 
• Whitelist policy APP APP 
DC1 DC2 
@chbatey 
Async Replication
Load balancing 
• Data centre aware policy 
• Token aware policy 
• Latency aware policy 
• Whitelist policy APP APP 
DC1 DC2 
@chbatey 
Async Replication
Reconnection Policies 
• Policy that decides how often the reconnection to a dead node is 
attempted. 
Cluster cluster = Cluster.builder() 
.addContactPoints("127.0.0.1", "127.0.0.2") 
.withReconnectionPolicy(new ConstantReconnectionPolicy(1000)) 
.withLoadBalancingPolicy(new TokenAwarePolicy()) 
.build(); 
• ConstantReconnectionPolicy 
• ExponentialReconnectionPolicy (Default) 
@chbatey ©2014 DataStax. Do not distribute without consent.
Reconnection Policies 
• Policy that decides how often the reconnection to a dead node is 
attempted. 
Cluster cluster = Cluster.builder() 
.addContactPoints("127.0.0.1", "127.0.0.2") 
.withReconnectionPolicy(new ConstantReconnectionPolicy(1000)) 
.withLoadBalancingPolicy(new TokenAwarePolicy()) 
.build(); 
• ConstantReconnectionPolicy 
• ExponentialReconnectionPolicy (Default) 
@chbatey ©2014 DataStax. Do not distribute without consent.
@chbatey 
Summary 
• Cassandra overview 
• Customer events example 
• DataStax Java Driver 
• Java Mapping API 
• Other features 
• Light weight transactions 
• Load balancing 
• Reconnection policies
Thanks for listening 
• Badger me on twitter @chbatey 
• https://github.com/chbatey/cassandra-customer-events 
• https://academy.datastax.com/ 
• http://christopher-batey.blogspot.co.uk/ 
@chbatey
© 2014 DataStax, All Rights Reserved. Company Confidential 
Training Day | December 3rd 
Beginner Track 
• Introduction to Cassandra 
• Introduction to Spark, Shark, Scala and Cassandra 
Advanced Track 
• Data Modeling 
• Performance Tuning 
Conference Day | December 4th 
Cassandra Summit Europe 2014 will be the single 
largest gathering of Cassandra users in Europe. Learn 
how the world's most successful companies are 
transforming their businesses and growing faster than 
ever using Apache Cassandra. 
http://bit.ly/cassandrasummit2014 
39

Weitere ähnliche Inhalte

Was ist angesagt?

Real World Mocking In Swift
Real World Mocking In SwiftReal World Mocking In Swift
Real World Mocking In SwiftVeronica Lillie
 
Meetup cassandra sfo_jdbc
Meetup cassandra sfo_jdbcMeetup cassandra sfo_jdbc
Meetup cassandra sfo_jdbczznate
 
Cracking JWT tokens: a tale of magic, Node.js and parallel computing - Code E...
Cracking JWT tokens: a tale of magic, Node.js and parallel computing - Code E...Cracking JWT tokens: a tale of magic, Node.js and parallel computing - Code E...
Cracking JWT tokens: a tale of magic, Node.js and parallel computing - Code E...Luciano Mammino
 
MongoDB: tips, trick and hacks
MongoDB: tips, trick and hacksMongoDB: tips, trick and hacks
MongoDB: tips, trick and hacksScott Hernandez
 
Hector v2: The Second Version of the Popular High-Level Java Client for Apach...
Hector v2: The Second Version of the Popular High-Level Java Client for Apach...Hector v2: The Second Version of the Popular High-Level Java Client for Apach...
Hector v2: The Second Version of the Popular High-Level Java Client for Apach...zznate
 
Beyond Profilers: Tracing Node.js Transactions
Beyond Profilers: Tracing Node.js TransactionsBeyond Profilers: Tracing Node.js Transactions
Beyond Profilers: Tracing Node.js TransactionsTerral R Jordan
 
Azure SQL Database - Connectivity Best Practices
Azure SQL Database - Connectivity Best PracticesAzure SQL Database - Connectivity Best Practices
Azure SQL Database - Connectivity Best PracticesJose Manuel Jurado Diaz
 
High Performance Core Data
High Performance Core DataHigh Performance Core Data
High Performance Core DataMatthew Morey
 
Designing The Right Schema To Power Heap (PGConf Silicon Valley 2016)
Designing The Right Schema To Power Heap (PGConf Silicon Valley 2016)Designing The Right Schema To Power Heap (PGConf Silicon Valley 2016)
Designing The Right Schema To Power Heap (PGConf Silicon Valley 2016)Dan Robinson
 
Adventures in Multithreaded Core Data
Adventures in Multithreaded Core DataAdventures in Multithreaded Core Data
Adventures in Multithreaded Core DataInferis
 
EPAM IT WEEK: AEM & TDD. It's so boring...
EPAM IT WEEK: AEM & TDD. It's so boring...EPAM IT WEEK: AEM & TDD. It's so boring...
EPAM IT WEEK: AEM & TDD. It's so boring...Andrew Manuev
 
Javascript Everywhere
Javascript EverywhereJavascript Everywhere
Javascript EverywherePascal Rettig
 
Matteo Collina | Take your HTTP server to Ludicrous Speed | Codmeotion Madrid...
Matteo Collina | Take your HTTP server to Ludicrous Speed | Codmeotion Madrid...Matteo Collina | Take your HTTP server to Ludicrous Speed | Codmeotion Madrid...
Matteo Collina | Take your HTTP server to Ludicrous Speed | Codmeotion Madrid...Codemotion
 
Drools, jBPM OptaPlanner presentation
Drools, jBPM OptaPlanner presentationDrools, jBPM OptaPlanner presentation
Drools, jBPM OptaPlanner presentationMark Proctor
 
REST to GraphQL migration: Pros, cons and gotchas
REST to GraphQL migration: Pros, cons and gotchasREST to GraphQL migration: Pros, cons and gotchas
REST to GraphQL migration: Pros, cons and gotchasAlexey Ivanov
 
Anton Moldovan "Load testing which you always wanted"
Anton Moldovan "Load testing which you always wanted"Anton Moldovan "Load testing which you always wanted"
Anton Moldovan "Load testing which you always wanted"Fwdays
 
ES6, 잘 쓰고 계시죠?
ES6, 잘 쓰고 계시죠?ES6, 잘 쓰고 계시죠?
ES6, 잘 쓰고 계시죠?장현 한
 
GKAC 2015 Apr. - RxAndroid
GKAC 2015 Apr. - RxAndroidGKAC 2015 Apr. - RxAndroid
GKAC 2015 Apr. - RxAndroidGDG Korea
 

Was ist angesagt? (20)

Real World Mocking In Swift
Real World Mocking In SwiftReal World Mocking In Swift
Real World Mocking In Swift
 
Meetup cassandra sfo_jdbc
Meetup cassandra sfo_jdbcMeetup cassandra sfo_jdbc
Meetup cassandra sfo_jdbc
 
Cracking JWT tokens: a tale of magic, Node.js and parallel computing - Code E...
Cracking JWT tokens: a tale of magic, Node.js and parallel computing - Code E...Cracking JWT tokens: a tale of magic, Node.js and parallel computing - Code E...
Cracking JWT tokens: a tale of magic, Node.js and parallel computing - Code E...
 
MongoDB: tips, trick and hacks
MongoDB: tips, trick and hacksMongoDB: tips, trick and hacks
MongoDB: tips, trick and hacks
 
Hector v2: The Second Version of the Popular High-Level Java Client for Apach...
Hector v2: The Second Version of the Popular High-Level Java Client for Apach...Hector v2: The Second Version of the Popular High-Level Java Client for Apach...
Hector v2: The Second Version of the Popular High-Level Java Client for Apach...
 
Beyond Profilers: Tracing Node.js Transactions
Beyond Profilers: Tracing Node.js TransactionsBeyond Profilers: Tracing Node.js Transactions
Beyond Profilers: Tracing Node.js Transactions
 
servlets
servletsservlets
servlets
 
Azure SQL Database - Connectivity Best Practices
Azure SQL Database - Connectivity Best PracticesAzure SQL Database - Connectivity Best Practices
Azure SQL Database - Connectivity Best Practices
 
High Performance Core Data
High Performance Core DataHigh Performance Core Data
High Performance Core Data
 
Designing The Right Schema To Power Heap (PGConf Silicon Valley 2016)
Designing The Right Schema To Power Heap (PGConf Silicon Valley 2016)Designing The Right Schema To Power Heap (PGConf Silicon Valley 2016)
Designing The Right Schema To Power Heap (PGConf Silicon Valley 2016)
 
Adventures in Multithreaded Core Data
Adventures in Multithreaded Core DataAdventures in Multithreaded Core Data
Adventures in Multithreaded Core Data
 
EPAM IT WEEK: AEM & TDD. It's so boring...
EPAM IT WEEK: AEM & TDD. It's so boring...EPAM IT WEEK: AEM & TDD. It's so boring...
EPAM IT WEEK: AEM & TDD. It's so boring...
 
Javascript Everywhere
Javascript EverywhereJavascript Everywhere
Javascript Everywhere
 
Matteo Collina | Take your HTTP server to Ludicrous Speed | Codmeotion Madrid...
Matteo Collina | Take your HTTP server to Ludicrous Speed | Codmeotion Madrid...Matteo Collina | Take your HTTP server to Ludicrous Speed | Codmeotion Madrid...
Matteo Collina | Take your HTTP server to Ludicrous Speed | Codmeotion Madrid...
 
Reactive server with netty
Reactive server with nettyReactive server with netty
Reactive server with netty
 
Drools, jBPM OptaPlanner presentation
Drools, jBPM OptaPlanner presentationDrools, jBPM OptaPlanner presentation
Drools, jBPM OptaPlanner presentation
 
REST to GraphQL migration: Pros, cons and gotchas
REST to GraphQL migration: Pros, cons and gotchasREST to GraphQL migration: Pros, cons and gotchas
REST to GraphQL migration: Pros, cons and gotchas
 
Anton Moldovan "Load testing which you always wanted"
Anton Moldovan "Load testing which you always wanted"Anton Moldovan "Load testing which you always wanted"
Anton Moldovan "Load testing which you always wanted"
 
ES6, 잘 쓰고 계시죠?
ES6, 잘 쓰고 계시죠?ES6, 잘 쓰고 계시죠?
ES6, 잘 쓰고 계시죠?
 
GKAC 2015 Apr. - RxAndroid
GKAC 2015 Apr. - RxAndroidGKAC 2015 Apr. - RxAndroid
GKAC 2015 Apr. - RxAndroid
 

Ähnlich wie Building Awesome Apps with Apache Cassandra

LA Cassandra Day 2015 - Cassandra for developers
LA Cassandra Day 2015  - Cassandra for developersLA Cassandra Day 2015  - Cassandra for developers
LA Cassandra Day 2015 - Cassandra for developersChristopher Batey
 
GraphQL - when REST API is not enough - lessons learned
GraphQL - when REST API is not enough - lessons learnedGraphQL - when REST API is not enough - lessons learned
GraphQL - when REST API is not enough - lessons learnedMarcinStachniuk
 
Cassandra Day London 2015: Getting Started with Apache Cassandra and Java
Cassandra Day London 2015: Getting Started with Apache Cassandra and JavaCassandra Day London 2015: Getting Started with Apache Cassandra and Java
Cassandra Day London 2015: Getting Started with Apache Cassandra and JavaDataStax Academy
 
Cassandra Day London: Building Java Applications
Cassandra Day London: Building Java ApplicationsCassandra Day London: Building Java Applications
Cassandra Day London: Building Java ApplicationsChristopher Batey
 
[WSO2Con Asia 2018] Patterns for Building Streaming Apps
[WSO2Con Asia 2018] Patterns for Building Streaming Apps[WSO2Con Asia 2018] Patterns for Building Streaming Apps
[WSO2Con Asia 2018] Patterns for Building Streaming AppsWSO2
 
Couchbase@live person meetup july 22nd
Couchbase@live person meetup   july 22ndCouchbase@live person meetup   july 22nd
Couchbase@live person meetup july 22ndIdo Shilon
 
Saving Money by Optimizing Your Cloud Add-On Infrastructure
Saving Money by Optimizing Your Cloud Add-On InfrastructureSaving Money by Optimizing Your Cloud Add-On Infrastructure
Saving Money by Optimizing Your Cloud Add-On InfrastructureAtlassian
 
GraphQL - an elegant weapon... for more civilized age
GraphQL - an elegant weapon... for more civilized ageGraphQL - an elegant weapon... for more civilized age
GraphQL - an elegant weapon... for more civilized ageBartosz Sypytkowski
 
Streams, Tables, and Time in KSQL
Streams, Tables, and Time in KSQLStreams, Tables, and Time in KSQL
Streams, Tables, and Time in KSQLconfluent
 
GraphQL Summit 2019 - Configuration Driven Data as a Service Gateway with Gra...
GraphQL Summit 2019 - Configuration Driven Data as a Service Gateway with Gra...GraphQL Summit 2019 - Configuration Driven Data as a Service Gateway with Gra...
GraphQL Summit 2019 - Configuration Driven Data as a Service Gateway with Gra...Noriaki Tatsumi
 
[WSO2Con EU 2017] Streaming Analytics Patterns for Your Digital Enterprise
[WSO2Con EU 2017] Streaming Analytics Patterns for Your Digital Enterprise[WSO2Con EU 2017] Streaming Analytics Patterns for Your Digital Enterprise
[WSO2Con EU 2017] Streaming Analytics Patterns for Your Digital EnterpriseWSO2
 
Powering Heap With PostgreSQL And CitusDB (PGConf Silicon Valley 2015)
Powering Heap With PostgreSQL And CitusDB (PGConf Silicon Valley 2015)Powering Heap With PostgreSQL And CitusDB (PGConf Silicon Valley 2015)
Powering Heap With PostgreSQL And CitusDB (PGConf Silicon Valley 2015)Dan Robinson
 
Intravert Server side processing for Cassandra
Intravert Server side processing for CassandraIntravert Server side processing for Cassandra
Intravert Server side processing for CassandraEdward Capriolo
 
NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"
NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"
NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"DataStax Academy
 
GraphQL - when REST API is to less - lessons learned
GraphQL - when REST API is to less - lessons learnedGraphQL - when REST API is to less - lessons learned
GraphQL - when REST API is to less - lessons learnedMarcinStachniuk
 
GraphQL - when REST API is to less - lessons learned
GraphQL - when REST API is to less - lessons learnedGraphQL - when REST API is to less - lessons learned
GraphQL - when REST API is to less - lessons learnedMarcinStachniuk
 
[WSO2Con USA 2018] Patterns for Building Streaming Apps
[WSO2Con USA 2018] Patterns for Building Streaming Apps[WSO2Con USA 2018] Patterns for Building Streaming Apps
[WSO2Con USA 2018] Patterns for Building Streaming AppsWSO2
 
VBA API for scriptDB primer
VBA API for scriptDB primerVBA API for scriptDB primer
VBA API for scriptDB primerBruce McPherson
 

Ähnlich wie Building Awesome Apps with Apache Cassandra (20)

LA Cassandra Day 2015 - Cassandra for developers
LA Cassandra Day 2015  - Cassandra for developersLA Cassandra Day 2015  - Cassandra for developers
LA Cassandra Day 2015 - Cassandra for developers
 
GraphQL - when REST API is not enough - lessons learned
GraphQL - when REST API is not enough - lessons learnedGraphQL - when REST API is not enough - lessons learned
GraphQL - when REST API is not enough - lessons learned
 
Cassandra Day London 2015: Getting Started with Apache Cassandra and Java
Cassandra Day London 2015: Getting Started with Apache Cassandra and JavaCassandra Day London 2015: Getting Started with Apache Cassandra and Java
Cassandra Day London 2015: Getting Started with Apache Cassandra and Java
 
Cassandra Day London: Building Java Applications
Cassandra Day London: Building Java ApplicationsCassandra Day London: Building Java Applications
Cassandra Day London: Building Java Applications
 
[WSO2Con Asia 2018] Patterns for Building Streaming Apps
[WSO2Con Asia 2018] Patterns for Building Streaming Apps[WSO2Con Asia 2018] Patterns for Building Streaming Apps
[WSO2Con Asia 2018] Patterns for Building Streaming Apps
 
Couchbase@live person meetup july 22nd
Couchbase@live person meetup   july 22ndCouchbase@live person meetup   july 22nd
Couchbase@live person meetup july 22nd
 
Saving Money by Optimizing Your Cloud Add-On Infrastructure
Saving Money by Optimizing Your Cloud Add-On InfrastructureSaving Money by Optimizing Your Cloud Add-On Infrastructure
Saving Money by Optimizing Your Cloud Add-On Infrastructure
 
Elasticsearch
ElasticsearchElasticsearch
Elasticsearch
 
GraphQL - an elegant weapon... for more civilized age
GraphQL - an elegant weapon... for more civilized ageGraphQL - an elegant weapon... for more civilized age
GraphQL - an elegant weapon... for more civilized age
 
Streams, Tables, and Time in KSQL
Streams, Tables, and Time in KSQLStreams, Tables, and Time in KSQL
Streams, Tables, and Time in KSQL
 
Patterns for Building Streaming Apps
Patterns for Building Streaming AppsPatterns for Building Streaming Apps
Patterns for Building Streaming Apps
 
GraphQL Summit 2019 - Configuration Driven Data as a Service Gateway with Gra...
GraphQL Summit 2019 - Configuration Driven Data as a Service Gateway with Gra...GraphQL Summit 2019 - Configuration Driven Data as a Service Gateway with Gra...
GraphQL Summit 2019 - Configuration Driven Data as a Service Gateway with Gra...
 
[WSO2Con EU 2017] Streaming Analytics Patterns for Your Digital Enterprise
[WSO2Con EU 2017] Streaming Analytics Patterns for Your Digital Enterprise[WSO2Con EU 2017] Streaming Analytics Patterns for Your Digital Enterprise
[WSO2Con EU 2017] Streaming Analytics Patterns for Your Digital Enterprise
 
Powering Heap With PostgreSQL And CitusDB (PGConf Silicon Valley 2015)
Powering Heap With PostgreSQL And CitusDB (PGConf Silicon Valley 2015)Powering Heap With PostgreSQL And CitusDB (PGConf Silicon Valley 2015)
Powering Heap With PostgreSQL And CitusDB (PGConf Silicon Valley 2015)
 
Intravert Server side processing for Cassandra
Intravert Server side processing for CassandraIntravert Server side processing for Cassandra
Intravert Server side processing for Cassandra
 
NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"
NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"
NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"
 
GraphQL - when REST API is to less - lessons learned
GraphQL - when REST API is to less - lessons learnedGraphQL - when REST API is to less - lessons learned
GraphQL - when REST API is to less - lessons learned
 
GraphQL - when REST API is to less - lessons learned
GraphQL - when REST API is to less - lessons learnedGraphQL - when REST API is to less - lessons learned
GraphQL - when REST API is to less - lessons learned
 
[WSO2Con USA 2018] Patterns for Building Streaming Apps
[WSO2Con USA 2018] Patterns for Building Streaming Apps[WSO2Con USA 2018] Patterns for Building Streaming Apps
[WSO2Con USA 2018] Patterns for Building Streaming Apps
 
VBA API for scriptDB primer
VBA API for scriptDB primerVBA API for scriptDB primer
VBA API for scriptDB primer
 

Mehr von Christopher Batey

Docker and jvm. A good idea?
Docker and jvm. A good idea?Docker and jvm. A good idea?
Docker and jvm. A good idea?Christopher Batey
 
LJC: Microservices in the real world
LJC: Microservices in the real worldLJC: Microservices in the real world
LJC: Microservices in the real worldChristopher Batey
 
NYC Cassandra Day - Java Intro
NYC Cassandra Day - Java IntroNYC Cassandra Day - Java Intro
NYC Cassandra Day - Java IntroChristopher Batey
 
Cassandra Day NYC - Cassandra anti patterns
Cassandra Day NYC - Cassandra anti patternsCassandra Day NYC - Cassandra anti patterns
Cassandra Day NYC - Cassandra anti patternsChristopher Batey
 
Think your software is fault-tolerant? Prove it!
Think your software is fault-tolerant? Prove it!Think your software is fault-tolerant? Prove it!
Think your software is fault-tolerant? Prove it!Christopher Batey
 
Manchester Hadoop Meetup: Cassandra Spark internals
Manchester Hadoop Meetup: Cassandra Spark internalsManchester Hadoop Meetup: Cassandra Spark internals
Manchester Hadoop Meetup: Cassandra Spark internalsChristopher Batey
 
Cassandra London - 2.2 and 3.0
Cassandra London - 2.2 and 3.0Cassandra London - 2.2 and 3.0
Cassandra London - 2.2 and 3.0Christopher Batey
 
Cassandra London - C* Spark Connector
Cassandra London - C* Spark ConnectorCassandra London - C* Spark Connector
Cassandra London - C* Spark ConnectorChristopher Batey
 
3 Dundee-Spark Overview for C* developers
3 Dundee-Spark Overview for C* developers3 Dundee-Spark Overview for C* developers
3 Dundee-Spark Overview for C* developersChristopher Batey
 
Paris Day Cassandra: Use case
Paris Day Cassandra: Use caseParis Day Cassandra: Use case
Paris Day Cassandra: Use caseChristopher Batey
 
Dublin Meetup: Cassandra anti patterns
Dublin Meetup: Cassandra anti patternsDublin Meetup: Cassandra anti patterns
Dublin Meetup: Cassandra anti patternsChristopher Batey
 
Data Science Lab Meetup: Cassandra and Spark
Data Science Lab Meetup: Cassandra and SparkData Science Lab Meetup: Cassandra and Spark
Data Science Lab Meetup: Cassandra and SparkChristopher Batey
 
Manchester Hadoop Meetup: Spark Cassandra Integration
Manchester Hadoop Meetup: Spark Cassandra IntegrationManchester Hadoop Meetup: Spark Cassandra Integration
Manchester Hadoop Meetup: Spark Cassandra IntegrationChristopher Batey
 
Manchester Hadoop User Group: Cassandra Intro
Manchester Hadoop User Group: Cassandra IntroManchester Hadoop User Group: Cassandra Intro
Manchester Hadoop User Group: Cassandra IntroChristopher Batey
 
Webinar Cassandra Anti-Patterns
Webinar Cassandra Anti-PatternsWebinar Cassandra Anti-Patterns
Webinar Cassandra Anti-PatternsChristopher Batey
 
Munich March 2015 - Cassandra + Spark Overview
Munich March 2015 -  Cassandra + Spark OverviewMunich March 2015 -  Cassandra + Spark Overview
Munich March 2015 - Cassandra + Spark OverviewChristopher Batey
 

Mehr von Christopher Batey (20)

Cassandra summit LWTs
Cassandra summit  LWTsCassandra summit  LWTs
Cassandra summit LWTs
 
Docker and jvm. A good idea?
Docker and jvm. A good idea?Docker and jvm. A good idea?
Docker and jvm. A good idea?
 
LJC: Microservices in the real world
LJC: Microservices in the real worldLJC: Microservices in the real world
LJC: Microservices in the real world
 
NYC Cassandra Day - Java Intro
NYC Cassandra Day - Java IntroNYC Cassandra Day - Java Intro
NYC Cassandra Day - Java Intro
 
Cassandra Day NYC - Cassandra anti patterns
Cassandra Day NYC - Cassandra anti patternsCassandra Day NYC - Cassandra anti patterns
Cassandra Day NYC - Cassandra anti patterns
 
Think your software is fault-tolerant? Prove it!
Think your software is fault-tolerant? Prove it!Think your software is fault-tolerant? Prove it!
Think your software is fault-tolerant? Prove it!
 
Manchester Hadoop Meetup: Cassandra Spark internals
Manchester Hadoop Meetup: Cassandra Spark internalsManchester Hadoop Meetup: Cassandra Spark internals
Manchester Hadoop Meetup: Cassandra Spark internals
 
Cassandra London - 2.2 and 3.0
Cassandra London - 2.2 and 3.0Cassandra London - 2.2 and 3.0
Cassandra London - 2.2 and 3.0
 
Cassandra London - C* Spark Connector
Cassandra London - C* Spark ConnectorCassandra London - C* Spark Connector
Cassandra London - C* Spark Connector
 
IoT London July 2015
IoT London July 2015IoT London July 2015
IoT London July 2015
 
1 Dundee - Cassandra 101
1 Dundee - Cassandra 1011 Dundee - Cassandra 101
1 Dundee - Cassandra 101
 
2 Dundee - Cassandra-3
2 Dundee - Cassandra-32 Dundee - Cassandra-3
2 Dundee - Cassandra-3
 
3 Dundee-Spark Overview for C* developers
3 Dundee-Spark Overview for C* developers3 Dundee-Spark Overview for C* developers
3 Dundee-Spark Overview for C* developers
 
Paris Day Cassandra: Use case
Paris Day Cassandra: Use caseParis Day Cassandra: Use case
Paris Day Cassandra: Use case
 
Dublin Meetup: Cassandra anti patterns
Dublin Meetup: Cassandra anti patternsDublin Meetup: Cassandra anti patterns
Dublin Meetup: Cassandra anti patterns
 
Data Science Lab Meetup: Cassandra and Spark
Data Science Lab Meetup: Cassandra and SparkData Science Lab Meetup: Cassandra and Spark
Data Science Lab Meetup: Cassandra and Spark
 
Manchester Hadoop Meetup: Spark Cassandra Integration
Manchester Hadoop Meetup: Spark Cassandra IntegrationManchester Hadoop Meetup: Spark Cassandra Integration
Manchester Hadoop Meetup: Spark Cassandra Integration
 
Manchester Hadoop User Group: Cassandra Intro
Manchester Hadoop User Group: Cassandra IntroManchester Hadoop User Group: Cassandra Intro
Manchester Hadoop User Group: Cassandra Intro
 
Webinar Cassandra Anti-Patterns
Webinar Cassandra Anti-PatternsWebinar Cassandra Anti-Patterns
Webinar Cassandra Anti-Patterns
 
Munich March 2015 - Cassandra + Spark Overview
Munich March 2015 -  Cassandra + Spark OverviewMunich March 2015 -  Cassandra + Spark Overview
Munich March 2015 - Cassandra + Spark Overview
 

Building Awesome Apps with Apache Cassandra

  • 1. Building awesome applications with Apache Cassandra Christopher Batey @chbatey ©2013 DataStax Confidential. Do not distribute without consent. 1
  • 2. Who am I? •Technical Evangelist for Apache Cassandra • Founder of Stubbed Cassandra • Help out Apache Cassandra users • Previous: Cassandra backed apps at BSkyB @chbatey
  • 3. @chbatey Overview • Topics covered • Cassandra overview • Customer events example • DataStax Java Driver • Java Mapping API • Other features • Light weight transactions • Load balancing • Reconnection policies
  • 4. @chbatey Overview • Topics covered • Cassandra overview • Customer events example • DataStax Java Driver • Java Mapping API • Other features • Light weight transactions • Load balancing • Reconnection policies • Not covered • Cassandra read and write paths • Cassandra failure nodes
  • 5. Common use cases •Ordered data such as time series •Event stores •Financial transactions •Sensor data e.g IoT @chbatey
  • 6. Common use cases •Ordered data such as time series •Event stores •Financial transactions •Sensor data e.g IoT •Non functional requirements: • Linear scalability • High throughout durable writes •Multi datacenter including active-active •Analytics without ETL @chbatey
  • 8. Cassandra Cassandra • Distributed master less database (Dynamo) • Column family data model (Google BigTable)
  • 9. Cassandra Europe • Distributed master less database (Dynamo) • Column family data model (Google BigTable) • Multi data centre replication built in from the start USA
  • 10. Cassandra Online • Distributed master less database (Dynamo) • Column family data model (Google BigTable) • Multi data centre replication built in from the start • Analytics with Apache Spark Analytics
  • 11. Replication WRITE CL = 1 We have replication! DC1 DC2 client C RC RF3 RF3
  • 12. Tunable Consistency • Data is replicated N times • Every query that you execute you give a consistency • ALL • QUORUM • LOCAL_QUORUM • ONE • Christos Kalantzis Eventual Consistency != Hopeful Consistency: http://youtu.be/ A6qzx_HE3EU?list=PLqcm6qE9lgKJzVvwHprow9h7KMpb5hcUU @chbatey
  • 13. CQL •Cassandra Query Language •SQL like query language •Keyspace – analogous to a schema • The keyspace determines the RF (replication factor) •Table – looks like a SQL Table CREATE TABLE scores ( @chbatey name text, score int, date timestamp, PRIMARY KEY (name, score) ); INSERT INTO scores (name, score, date) VALUES ('bob', 42, '2012-06-24'); INSERT INTO scores (name, score, date) VALUES ('bob', 47, '2012-06-25'); SELECT date, score FROM scores WHERE name='bob' AND score >= 40;
  • 14. Example Time: Customer event store @chbatey
  • 15. An example: Customer event store • Customer event • customer_id - ChrisBatey • staff_id - Charlie • store_type Website, PhoneApp, Phone, Retail • event_type - login, logout, add_to_basket, remove_from_basket, buy_item • time • tags
  • 16. Requirements • Get all events • Get all events for a particular customer • As above for a time slice
  • 17. Modelling in Cassandra CREATE TABLE customer_events( customer_id text, staff_id text, Partition Key time timeuuid, store_type text, event_type text, tags map<text, text>, PRIMARY KEY ((customer_id), time)); Clustering Column(s)
  • 18. How it is stored on disk customer _id time event_type store_type tags charles 2014-11-18 16:52:04 basket_add online {'item': 'coffee'} charles 2014-11-18 16:53:00 basket_add online {'item': ‘wine'} charles 2014-11-18 16:53:09 logout online {} chbatey 2014-11-18 16:52:21 login online {} chbatey 2014-11-18 16:53:21 basket_add online {'item': 'coffee'} chbatey 2014-11-18 16:54:00 basket_add online {'item': 'cheese'} charles event_type basket_add staff_id n/a store_type online tags:item coffee event_type basket_add staff_id n/a store_type online tags:item wine event_type logout staff_id n/a store_type online chbatey event_type login staff_id n/a store_type online event_type basket_add staff_id n/a store_type online tags:item coffee event_type basket_add staff_id n/a store_type online tags:item cheese
  • 19. DataStax Java Driver • Open source @chbatey
  • 20. @chbatey Get all the events public List<CustomerEvent> getAllCustomerEvents() { return session.execute("select * from customers.customer_events") .all().stream() .map(mapCustomerEvent()) .collect(Collectors.toList()); } private Function<Row, CustomerEvent> mapCustomerEvent() { return row -> new CustomerEvent( row.getString("customer_id"), row.getUUID("time"), row.getString("staff_id"), row.getString("store_type"), row.getString("event_type"), row.getMap("tags", String.class, String.class)); }
  • 21. All events for a particular customer private PreparedStatement getEventsForCustomer; @PostConstruct public void prepareSatements() { getEventsForCustomer = session.prepare("select * from customers.customer_events where customer_id = ?"); } public List<CustomerEvent> getCustomerEvents(String customerId) { BoundStatement boundStatement = getEventsForCustomer.bind(customerId); return session.execute(boundStatement) .all().stream() .map(mapCustomerEvent()) .collect(Collectors.toList()); @chbatey }
  • 22. Customer events for a time slice public List<CustomerEvent> getCustomerEventsForTime(String customerId, long startTime, long endTime) { Select.Where getCustomers = QueryBuilder.select() .all() .from("customers", "customer_events") .where(eq("customer_id", customerId)) .and(gt("time", UUIDs.startOf(startTime))) .and(lt("time", UUIDs.endOf(endTime))); return session.execute(getCustomers).all().stream() .map(mapCustomerEvent()) .collect(Collectors.toList()); @chbatey }
  • 23. @chbatey Mapping API @Table(keyspace = "customers", name = "customer_events") public class CustomerEvent { @PartitionKey @Column(name = "customer_id") private String customerId; @ClusteringColumn private UUID time; @Column(name = "staff_id") private String staffId; @Column(name = "store_type") private String storeType; @Column(name = "event_type") private String eventType; private Map<String, String> tags; // ctr / getters etc }
  • 24. @chbatey Mapping API @Accessor public interface CustomerEventDao { @Query("select * from customers.customer_events where customer_id = :customerId") Result<CustomerEvent> getCustomerEvents(String customerId); @Query("select * from customers.customer_events") Result<CustomerEvent> getAllCustomerEvents(); @Query("select * from customers.customer_events where customer_id = :customerId and time > minTimeuuid(:startTime) and time < maxTimeuuid(:endTime)") Result<CustomerEvent> getCustomerEventsForTime(String customerId, long startTime, long endTime); } @Bean public CustomerEventDao customerEventDao() { MappingManager mappingManager = new MappingManager(session); return mappingManager.createAccessor(CustomerEventDao.class); }
  • 25. Adding some type safety public enum StoreType { ONLINE, RETAIL, FRANCHISE, MOBILE @chbatey } @Table(keyspace = "customers", name = "customer_events") public class CustomerEvent { @PartitionKey @Column(name = "customer_id") private String customerId; @ClusteringColumn() private UUID time; @Column(name = "staff_id") private String staffId; @Column(name = "store_type") @Enumerated(EnumType.STRING) // could be EnumType.ORDINAL private StoreType storeType;
  • 26. @chbatey User defined types create TYPE store (name text, type text, postcode text) ; CREATE TABLE customer_events_type( customer_id text, staff_id text, time timeuuid, store frozen<store>, event_type text, tags map<text, text>, PRIMARY KEY ((customer_id), time));
  • 27. Mapping user defined types @chbatey @UDT(keyspace = "customers", name = "store") public class Store { private String name; private StoreType type; private String postcode; // getters etc } @Table(keyspace = "customers", name = "customer_events_type") public class CustomerEventType { @PartitionKey @Column(name = "customer_id") private String customerId; @ClusteringColumn() private UUID time; @Column(name = "staff_id") private String staffId; @Frozen private Store store; @Column(name = "event_type") private String eventType; private Map<String, String> tags;
  • 28. Mapping user defined types @chbatey @UDT(keyspace = "customers", name = "store") public class Store { private String name; private StoreType type; private String postcode; // getters etc } @Table(keyspace = "customers", name = "customer_events_type") public class CustomerEventType { @PartitionKey @Column(name = "customer_id") private String customerId; @ClusteringColumn() private UUID time; @Column(name = "staff_id") private String staffId; @Frozen private Store store; @Column(name = "event_type") private String eventType; private Map<String, String> tags; @Query("select * from customers.customer_events_type") Result<CustomerEventType> getAllCustomerEventsWithStoreType();
  • 29. What else can I do? @chbatey
  • 30. Lightweight Transactions (LWT) Consequences of Lightweight Transactions 4 round trips vs. 1 for normal updates (uses Paxos algorithm) Operations are done on a per-partition basis Will be going across data centres to obtain consensus (unless you use LOCAL_SERIAL consistency) Cassandra user will need read and write access i.e. you get back the row! Great for 1% your app, but eventual consistency is still your friend! @chbatey
  • 31. Company Confidential @chbatey Batch Statements BEGIN BATCH INSERT INTO users (userID, password, name) VALUES ('user2', 'ch@ngem3b', 'second user') UPDATE users SET password = 'ps22dhds' WHERE userID = 'user2' INSERT INTO users (userID, password) VALUES ('user3', 'ch@ngem3c') DELETE name FROM users WHERE userID = 'user2’ APPLY BATCH; BATCH statement combines multiple INSERT, UPDATE, and DELETE statements into a single logical operation Atomic operation If any statement in the batch succeeds, all will No batch isolation Other “transactions” can read and write data being affected by a partially executed batch © 2014 DataStax, All Rights Reserved.
  • 32. Batch Statements with LWT BEGIN BATCH UPDATE foo SET z = 1 WHERE x = 'a' AND y = 1; UPDATE foo SET z = 2 WHERE x = 'a' AND y = 2 IF t = 4; Company Confidential @chbatey APPLY BATCH; Allows you to group multiple conditional updates in a batch as long as all those updates apply to the same partition © 2014 DataStax, All Rights Reserved.
  • 33. Load balancing • Data centre aware policy • Token aware policy • Latency aware policy • Whitelist policy APP APP DC1 DC2 @chbatey Async Replication
  • 34. Load balancing • Data centre aware policy • Token aware policy • Latency aware policy • Whitelist policy APP APP DC1 DC2 @chbatey Async Replication
  • 35. Reconnection Policies • Policy that decides how often the reconnection to a dead node is attempted. Cluster cluster = Cluster.builder() .addContactPoints("127.0.0.1", "127.0.0.2") .withReconnectionPolicy(new ConstantReconnectionPolicy(1000)) .withLoadBalancingPolicy(new TokenAwarePolicy()) .build(); • ConstantReconnectionPolicy • ExponentialReconnectionPolicy (Default) @chbatey ©2014 DataStax. Do not distribute without consent.
  • 36. Reconnection Policies • Policy that decides how often the reconnection to a dead node is attempted. Cluster cluster = Cluster.builder() .addContactPoints("127.0.0.1", "127.0.0.2") .withReconnectionPolicy(new ConstantReconnectionPolicy(1000)) .withLoadBalancingPolicy(new TokenAwarePolicy()) .build(); • ConstantReconnectionPolicy • ExponentialReconnectionPolicy (Default) @chbatey ©2014 DataStax. Do not distribute without consent.
  • 37. @chbatey Summary • Cassandra overview • Customer events example • DataStax Java Driver • Java Mapping API • Other features • Light weight transactions • Load balancing • Reconnection policies
  • 38. Thanks for listening • Badger me on twitter @chbatey • https://github.com/chbatey/cassandra-customer-events • https://academy.datastax.com/ • http://christopher-batey.blogspot.co.uk/ @chbatey
  • 39. © 2014 DataStax, All Rights Reserved. Company Confidential Training Day | December 3rd Beginner Track • Introduction to Cassandra • Introduction to Spark, Shark, Scala and Cassandra Advanced Track • Data Modeling • Performance Tuning Conference Day | December 4th Cassandra Summit Europe 2014 will be the single largest gathering of Cassandra users in Europe. Learn how the world's most successful companies are transforming their businesses and growing faster than ever using Apache Cassandra. http://bit.ly/cassandrasummit2014 39