SlideShare a Scribd company logo
1 of 50
Cassandra 101
Scala by the Lagoon
Treviso, 28 April 2016
THE SPEAKER
• Software engineer at Radicalbit
• Blogger at codingjam.it
• (Re)twitter guy with @supergiampaolo
Giampaolo
AGENDA
1.What’s Cassandra
2.The CAP Theorem
3.“Internals”
4.CQL
5.Scala/Phantom
Cassandra 101
(2.x)
What’s Cassandra
What’s Cassandra
• NoSQL
• High availability
• Linear Scalability
• Predictable Performance
• No Single Point of Failure (peer to peer)
• Multi DataCenter (DC)
• A hybrid between a key-value and a column oriented
• Clients see data in tables
• Data manipulation through CQL (similar to SQL)
• Not a replacement for a RDBMS
“Apache Cassandra is an open
source distributed database
management system designed
to handle large amounts of data
across many servers, providing
high availability with no single
point of failure.”
What’s Cassandra
Who uses
Cassandra?
What’s Cassandra
• Internet of Things: time series from users,
device and sensors
• Personalization: ingest and analyze to
personalize user experience
• Messaging: storing, managing, and
analyzing messages
• Fraud detection: to analyze quickly patterns
• Playlist: storing collections of user selected
items
Use cases
What’s Cassandra
• Developed at Facebook for messaging
system
• From Google Big Table: the storage model
• From Amazon Dynamo: the distribution
backbone
• Open source since 2008
• Apache top level since 2010
• Most stable release: 2.2 (2015)
• Latest release 3.4 (March 2016)
• Tick-tock releases in 2016
Quick history so far
• No master/slave, no Zookeeper, no config server
• All nodes can reply to writes and reads
• Data is partitioned around the ring
• Location of data on ring is determined a function
• Data is replicated with a specific factor
What’s Cassandra
1
4 2
3
-128
-64
0
64
C* is a big hash ring
The CAP Theorem
Three properties
of shared data
system operating
over a network
The CAP Theorem
Consistency
every read would get you the most recent write
Availability
every node (if not failed) always executes queries within
unbounded time (but finite)
Partition Tolerance
the system continues to operate despite arbitrary
partitioning due to network failures
The CAP Theorem (rough)
1.AP: the system is Partitioned and
Available to clients but not
Consistent
2.CP: the system is Consistent and
working during a Partition, but
there is no Availability
3.AC: the system is Consistent and
Available there is no Partition.
Does this system really exist?
“pick two”
“this is often considered to be a misleading
presentation, since you cannot build - or
choose - 'partition tolerance': your system
either might experience partitions or it won't”.
The CAP Theorem (finer)
1. Do you respond to the reads with
potentially stale information
2. Do you wait (potentially forever) to
hear from the other side of the
partition and compromise availability?
“pick one”
or what you give up?
If a client writes to one side of a partition, any
reads that go to the other side of that partition
can't possibly know about the most recent
write. We are in a critical condition
Consistency & Availability Tradeoff
Spectrum
Both C and A are strong
guarantees in a critical condition
But out of critical conditions, a
system can be happily consistent
and available
AP to CP is a spectrum and
the whole space is useful
Eventual consistency and high
availability are good enough
AVAILABILITY CONSISTENCY
AP CP
Beyond CAP: PACELC
P(A/C)E(L/C)
AVAILABILITY CONSISTENCY
AP CP
(LESS) LATENCY
CONSISTENCY
If there is a partition (P)
how does the system trade off
availability and consistency (A and C)
else (E)
when the system is running normally
in the absence of partitions, how does
the system trade off latency (L) and
consistency (C)?
Cassandra & PACELC
C* has a tunable
consistency
Can move from PC/EC to PA/EL
Consistency can be tuned at query
level from max availability to
immediate consistency
AVAILABILITY CONSISTENCY
AP CP
(LESS) LATENCY
CONSISTENCY
PA/EL
PC/EC
Internals
Internals
A cluster is a peer to peer set of servers
Organized in
• Data centers
• Racks
• Nodes
Cluster
Internals
A node needs
• Cluster name
• Seeds addresses
• Its listen address
Every node is aware of status of
cluster through gossip
Joining a
cluster
Internals
Replication Tables are grouped by keyspace
Every keyspace has its own replication properties
CREATE KEYSPACE books
WITH REPLICATION =
{'class': 'SimpleStrategy',
'replication_factor' : 3};
CREATE KEYSPACE books
WITH REPLICATION =
{'class': 'NetworkTopologyStrategy',
'dc-newyork': 3,
'dc-london': 4};
Internals
Request coordinator
SELECT * FROM authors
Where name = ‘Poe’
• The node that handles communication with client
• Every node can do the coordinator
• The driver decides which is the coordinator
Internals
Consistent
hashing
CREATE TABLE authors(
name text,
bio text ,
PRIMARY KEY (name));
INSERT INTO authors
(name, bio)
VALUES
('Poe', ’Poe was a writer');
• -263..263 tokens (3.4*1038) distributed in cluster
• Every node knows its tokens
• Partitioner is a function from a partition key to a token
• Nodes and drivers use the same partitioner
Internals
Replication
Poe, Poe was a writer
Poe, Poe was a
writer
CREATE TABLE authors(
name text,
bio text ,
PRIMARY KEY (name));
INSERT INTO authors
(name, bio)
VALUES
('Poe', ’Poe was a writer');
Internals
Hinted
handoff
Poe, Poe was an
American writer
Poe, Poe was an
American writer
• What if node 1 is down? Do we give up writing?
• Hinted handoff allows to replay writes to a momentary
unavailable node
• It’s optional
• There are some limitations
• Coordinator keeps the data
• What about consistency?
UPDATE authors
SET bio = ‘Poe was an
American writer’
WHERE name = ‘Poe’
Internals
Consistency
level
CONSISTENCY = TWO;
SELECT * FROM authors
WHERE name= 'Poe’;
Real read will happen for one node only, the other two will send a digest
Poe was an
American
writer
Poe was
an
American
writer
Poe was a
writer
• How many nodes must acknowledge a request to return a
positive response to the client (Read/Write)
• Set at query level
• What if replicas do not agree?
Internals
Consistency
levels
there are more
• ANY (writes only)
• ONE
• TWO
• THREE
• QUORUM
• LOCAL_ONE
• LOCAL_QUORUM
ALL for immediate consistency (high latency)
ONE/ANY for eventual consistency (lowest latency)
Internals
Immediate
consistency
• Combine read and write to get consistency as this
rule:
If (nodes_written + nodes_read) > RF
then immediate consistency
• Examples with RF = 3
• Write: ALL, Read: ONE
• Write: QUORUM, Read: QUORUM
• Write: ONE, Read: ALL
• Is stale data really a problem?
CQL
CQL
• CQL is declarative like SQL and the
very basic structure of the query
component of the language
(SELECTs, INSERTs, …) is the same.
• But there are enough differences that
one should not approach using it in the
same way as conventional SQL
(because Cassandra is not relational!)
Cassandra
Query
Language
CQL
Cassandra
Query
Language
CREATE TABLE authors(
name text,
gender text,
born int,
died int,
bio text,
genre set<text>,
PRIMARY KEY (name));
ALTER TABLE authors ADD picture blob;
ALTER TABLE authors DROP gender;
DROP TABLE authors;
CQL
Cassandra
Query
Language
Cassandra has upserts, what
happens if I want to update the
name of an author?
SELECT * FROM authors LIMIT 10;
SELECT * FROM authors
where NAME = 'Herman Melville';
INSERT INTO authors(name)
VALUES ('Edgar Alan Poe');
UPDATE authors SET born = 1797
WHERE name = 'Mary Shelley';
UPDATE authors SET genre = genre + {'Gothic
literature'} where name = 'Mary Shelley';
DELETE from authors
WHERE name = 'Charles Dickens';
CQL
Invalid queries
• SELECT * FROM authors WHERE born = 1797;
• SELECT * FROM authors WHERE name like
'Mar%';
• SELECT * FROM authors WHERE NOT name = 'Mary
Shelley';
• SELECT * FROM authors WHERE name = 'Mary
Shelley' or name = 'Edgar Alan Poe';
• SELECT max(born) FROM authors group by
genre;
• SELECT * FROM authors ORDER by name;
• SELECT * FROM authors JOIN books ON
author.name = books.author;
CQL
How to solve
the problem?
Create tables that responds to
specific queries
Logged batch to the rescue
Actually won’t work for two
authors of 1819, try to insert
(George Eliot, 1819)
CREATE TABLE authors_by_year (
born int,
name text,
PRIMARY KEY (born));
INSERT INTO authors_by_year (born, name)
VALUES (1797, 'Mary Shelley')
INSERT INTO authors_by_year (born, name)
VALUES (1819, 'Herman Melville')
SELECT * FROM authors_by_year
WHERE born = 1797;
CQL
Partition key
Primary key
Partition
Row
• Partition is a list of rows and has a Partition
key, simple or compound
• Every row has its primary key composed by
partition key and (eventual) other columns
(said clustering) and it’s ordered inside
partition
• Partition key and primary key, something like
a two level key
• Partition key is related to token so a partition
cannot be split between nodes
CQL
Partition
example
CREATE TABLE books(
author text,
born int static,
title text,
published int,
PRIMARY KEY ((author), title);
INSERT INTO books(author, title) VALUES
('Melville', 'White-Jacket');
UPDATE books SET born = 1819 WHERE author =
'Melville’;
INSERT INTO books(author, title, published)
VALUES ('Melville', 'Moby Dick' , 1851);
CQL
Partition
example
SELECT * FROM books WHERE author = 'Melville'
author | title | born | published
----------+--------------+------+-----------
Melville | Moby Dick | 1819 | 1851
Melville | White-Jacket | 1819 | null
CQL
Filtering and
ordering is
possible on
clustered
columns
SELECT * FROM books WHERE author = 'Melville'
ORDER BY title DESC;
author | title | born | published
----------+--------------+------+-----------
Melville | White-Jacket | 1819 | null
Melville | Moby Dick | 1819 | 1851
SELECT * FROM books WHERE author = 'Melville'
AND title >= 'O';
author | title | born | published
----------+--------------+------+-----------
Melville | White-Jacket | 1819 | null
CQL
Filtering and
ordering is
possible on
clustered
columns
SELECT * FROM books WHERE title >= 'O';
InvalidRequest: code=2200 [Invalid query]
message="Cannot execute this query as it might
involve data filtering and thus may have
unpredictable performance. If you want to
execute this query despite the performance
unpredictability, use ALLOW FILTERING”
SELECT * FROM books WHERE title >= 'O’ ALLOW
FILTERING;
author | title | born | published
----------+--------------+------+-----------
Melville | White-Jacket | 1819 | null
Scala/Phantom
PHANTOM
Phantom
• Type-safe Scala DSL for Cassandra
• Built atop Datastax Java Driver
• Adds type safety to CQL statements
• Add reactivity (Futures!)
• Performances comparable to direct Java implementation
• Freeware/Commercial versions
• https://github.com/outworkers/phantom
• Sample code at
https://github.com/giampaolotrapasso/cassandra-101-scala-
examples
PHANTOM
Books
case class Book(
author: String,
born: Int,
title: String,
published: Option[Int] = None
)
PHANTOM
Books
class BooksTable extends CassandraTable[BooksDAO, Book] {
override val tableName = "books"
object author extends StringColumn(this) with PartitionKey[String]
object born extends IntColumn(this) with StaticColumn[Int]
object title extends StringColumn(this) with ClusteringOrder[String]
object published extends OptionalIntColumn(this)
override def fromRow(row: Row): Book = {
Book(
author = author(row),
born = born(row),
title = title(row),
published = published(row)
)
}
}
PHANTOM
Books
abstract class BooksDAO extends BooksTable with RootConnector {
def insertNewStatement(book: Book) = {
insert
.value(_.author, book.author)
.value(_.born, book.born)
.value(_.title, book.title)
.value(_.published, book.published)
}
def insertNew(book: Book): Future[dsl.ResultSet] =
insertNewStatement(book).future()
def selectByAuthor(author: String): Future[List[Book]] = {
select.where(_.author eqs author).fetch()
}
def updateBookStatement(author: String, book: String, published: Option[Int]) = {
update
.where(_.author eqs author).and(_.title eqs book)
.modify(_.published setTo published)
}
}
PHANTOM
Books by
year
case class BookByYear(year: Int, book: String)
class BooksByYearTable extends CassandraTable[BooksByYearTable, BookByYear] {
override val tableName = "books_by_year”
object year extends IntColumn(this) with PartitionKey[Int]
object book extends StringColumn(this) with ClusteringOrder[String] with Ascending
override def fromRow(row: Row): BookByYear = {
BookByYear(
year = year(row),
book = book(row))
}
}
abstract class BooksByYearDAO extends BooksByYearTable with RootConnector {
def insertNewStatement(bookByYear: BookByYear) = {
insert
.value(_.year, bookByYear.year)
.value(_.book, bookByYear.book)
}
def insertNew(postByAuthor: BookByYear) = insertNewStatement(postByAuthor).future
def selectByYear(year: Int): Future[List[BookByYear]] = {
select.where(_.year eqs year).fetch()
}
}
PHANTOM
Configuration object Config {
val keySpace = KeySpace("books")
val contactPoint: KeySpaceBuilder = ContactPoint(
host = "localhost",
port = ContactPoint.DefaultPorts.live)
val keySpaceConnector: KeySpaceDef =
contactPoint.keySpace(keySpace.name)
}
PHANTOM
Database class Database(val keySpaceConnector: KeySpaceDef)
extends DatabaseImpl(keySpaceConnector) {
object books extends BooksDAO with keySpaceConnector.Connector
object booksByYear extends BooksByYearDAO
with keySpaceConnector.Connector
def insertBook(book: Book) = {
var batch = Batch.logged
.add(books.insertNewStatement(book))
book.published.map { year =>
val byYear = BookByYear(year, book.title)
batch = batch.add(booksByYear.insertNewStatement(byYear))
}
batch.future()
}
}
object BookDatabase extends Database(Config.keySpaceConnector)
PHANTOM
Run! implicit val space: KeySpace = BookDatabase.space
implicit val session: Session = BookDatabase.session
Await.result(BookDatabase.autocreate().future, 10 seconds)
val book1 = Book("Melville”, 1819, "White-Jacket”, Some(1850))
val book2 = book1.copy(title = "Moby Dick", published = Some(1851))
val book3 = Book("Hemingway”, 1899, "For Whom the Bell tolls”)
val book4 = Book("Dino Buzzati”, 1906, "Il deserto dei tartari”, Some(1940))
val books: List[Future[ResultSet]] =
List(book1, book2, book3, book4).map(p => BookDatabase.insertBook(p))
val operations: Future[List[ResultSet]] = Future.sequence(books)
Await.result(operations, 10.seconds)
PHANTOM
Run! val listOfMelville: Future[List[Book]] =
BookDatabase.books.selectByAuthor("Melville")
listOfMelville.onComplete {
case Success(list) => println(s"${list.size} books by Melville ")
case Failure(x) => println(x)
}
Await.result(listOfMelville, 3.seconds)
val booksOf1940 = BookDatabase.booksByYear.selectByYear(1940)
booksOf1940.onComplete {
case Success(list) => println(s"${list.size} books in 1940")
case Failure(x) => println(x)
}
Await.ready(booksOf1940, 3.seconds)
Q & Option[A]
Thanks!
Giampaolo Trapasso
Software engineer
giampaolo.trapasso@radicalbit.io

More Related Content

Similar to Cassandra 101

Deep Dive into Cassandra
Deep Dive into CassandraDeep Dive into Cassandra
Deep Dive into CassandraBrent Theisen
 
Introduction to Cassandra - Denver
Introduction to Cassandra - DenverIntroduction to Cassandra - Denver
Introduction to Cassandra - DenverJon Haddad
 
Cassandra Day Denver 2014: Introduction to Apache Cassandra
Cassandra Day Denver 2014: Introduction to Apache CassandraCassandra Day Denver 2014: Introduction to Apache Cassandra
Cassandra Day Denver 2014: Introduction to Apache CassandraDataStax Academy
 
Cassandra Day London 2015: Introduction to Apache Cassandra and DataStax Ente...
Cassandra Day London 2015: Introduction to Apache Cassandra and DataStax Ente...Cassandra Day London 2015: Introduction to Apache Cassandra and DataStax Ente...
Cassandra Day London 2015: Introduction to Apache Cassandra and DataStax Ente...DataStax Academy
 
Cassandra Day Atlanta 2015: Introduction to Apache Cassandra & DataStax Enter...
Cassandra Day Atlanta 2015: Introduction to Apache Cassandra & DataStax Enter...Cassandra Day Atlanta 2015: Introduction to Apache Cassandra & DataStax Enter...
Cassandra Day Atlanta 2015: Introduction to Apache Cassandra & DataStax Enter...DataStax Academy
 
Cassandra Day Chicago 2015: Introduction to Apache Cassandra & DataStax Enter...
Cassandra Day Chicago 2015: Introduction to Apache Cassandra & DataStax Enter...Cassandra Day Chicago 2015: Introduction to Apache Cassandra & DataStax Enter...
Cassandra Day Chicago 2015: Introduction to Apache Cassandra & DataStax Enter...DataStax Academy
 
Cassandra & Python - Springfield MO User Group
Cassandra & Python - Springfield MO User GroupCassandra & Python - Springfield MO User Group
Cassandra & Python - Springfield MO User GroupAdam Hutson
 
Cassandra Tutorial
Cassandra Tutorial Cassandra Tutorial
Cassandra Tutorial Na Zhu
 
Introduction to cassandra
Introduction to cassandraIntroduction to cassandra
Introduction to cassandraTarun Garg
 
NoSQL - Cassandra & MongoDB.pptx
NoSQL -  Cassandra & MongoDB.pptxNoSQL -  Cassandra & MongoDB.pptx
NoSQL - Cassandra & MongoDB.pptxNaveen Kumar
 
cassandra_presentation_final
cassandra_presentation_finalcassandra_presentation_final
cassandra_presentation_finalSergioBruno21
 
MongoDB SoCal 2020: From Pharmacist to Analyst: Leveraging MongoDB for Real-T...
MongoDB SoCal 2020: From Pharmacist to Analyst: Leveraging MongoDB for Real-T...MongoDB SoCal 2020: From Pharmacist to Analyst: Leveraging MongoDB for Real-T...
MongoDB SoCal 2020: From Pharmacist to Analyst: Leveraging MongoDB for Real-T...MongoDB
 
Introduction to NoSQL CassandraDB
Introduction to NoSQL CassandraDBIntroduction to NoSQL CassandraDB
Introduction to NoSQL CassandraDBJanos Geronimo
 
Design Patterns For Distributed NO-reational databases
Design Patterns For Distributed NO-reational databasesDesign Patterns For Distributed NO-reational databases
Design Patterns For Distributed NO-reational databaseslovingprince58
 
NOSQL and Cassandra
NOSQL and CassandraNOSQL and Cassandra
NOSQL and Cassandrarantav
 
Design Patterns for Distributed Non-Relational Databases
Design Patterns for Distributed Non-Relational DatabasesDesign Patterns for Distributed Non-Relational Databases
Design Patterns for Distributed Non-Relational Databasesguestdfd1ec
 
Apache Cassandra, part 1 – principles, data model
Apache Cassandra, part 1 – principles, data modelApache Cassandra, part 1 – principles, data model
Apache Cassandra, part 1 – principles, data modelAndrey Lomakin
 

Similar to Cassandra 101 (20)

Deep Dive into Cassandra
Deep Dive into CassandraDeep Dive into Cassandra
Deep Dive into Cassandra
 
Introduction to Cassandra - Denver
Introduction to Cassandra - DenverIntroduction to Cassandra - Denver
Introduction to Cassandra - Denver
 
Cassandra Day Denver 2014: Introduction to Apache Cassandra
Cassandra Day Denver 2014: Introduction to Apache CassandraCassandra Day Denver 2014: Introduction to Apache Cassandra
Cassandra Day Denver 2014: Introduction to Apache Cassandra
 
Cassandra Day London 2015: Introduction to Apache Cassandra and DataStax Ente...
Cassandra Day London 2015: Introduction to Apache Cassandra and DataStax Ente...Cassandra Day London 2015: Introduction to Apache Cassandra and DataStax Ente...
Cassandra Day London 2015: Introduction to Apache Cassandra and DataStax Ente...
 
Cassandra Day Atlanta 2015: Introduction to Apache Cassandra & DataStax Enter...
Cassandra Day Atlanta 2015: Introduction to Apache Cassandra & DataStax Enter...Cassandra Day Atlanta 2015: Introduction to Apache Cassandra & DataStax Enter...
Cassandra Day Atlanta 2015: Introduction to Apache Cassandra & DataStax Enter...
 
Cassandra Day Chicago 2015: Introduction to Apache Cassandra & DataStax Enter...
Cassandra Day Chicago 2015: Introduction to Apache Cassandra & DataStax Enter...Cassandra Day Chicago 2015: Introduction to Apache Cassandra & DataStax Enter...
Cassandra Day Chicago 2015: Introduction to Apache Cassandra & DataStax Enter...
 
Cassandra & Python - Springfield MO User Group
Cassandra & Python - Springfield MO User GroupCassandra & Python - Springfield MO User Group
Cassandra & Python - Springfield MO User Group
 
Cassandra Tutorial
Cassandra Tutorial Cassandra Tutorial
Cassandra Tutorial
 
Cassandra training
Cassandra trainingCassandra training
Cassandra training
 
Introduction to cassandra
Introduction to cassandraIntroduction to cassandra
Introduction to cassandra
 
L6.sp17.pptx
L6.sp17.pptxL6.sp17.pptx
L6.sp17.pptx
 
NoSQL - Cassandra & MongoDB.pptx
NoSQL -  Cassandra & MongoDB.pptxNoSQL -  Cassandra & MongoDB.pptx
NoSQL - Cassandra & MongoDB.pptx
 
cassandra_presentation_final
cassandra_presentation_finalcassandra_presentation_final
cassandra_presentation_final
 
MongoDB SoCal 2020: From Pharmacist to Analyst: Leveraging MongoDB for Real-T...
MongoDB SoCal 2020: From Pharmacist to Analyst: Leveraging MongoDB for Real-T...MongoDB SoCal 2020: From Pharmacist to Analyst: Leveraging MongoDB for Real-T...
MongoDB SoCal 2020: From Pharmacist to Analyst: Leveraging MongoDB for Real-T...
 
Introduction to NoSQL CassandraDB
Introduction to NoSQL CassandraDBIntroduction to NoSQL CassandraDB
Introduction to NoSQL CassandraDB
 
Design Patterns For Distributed NO-reational databases
Design Patterns For Distributed NO-reational databasesDesign Patterns For Distributed NO-reational databases
Design Patterns For Distributed NO-reational databases
 
NOSQL and Cassandra
NOSQL and CassandraNOSQL and Cassandra
NOSQL and Cassandra
 
Design Patterns for Distributed Non-Relational Databases
Design Patterns for Distributed Non-Relational DatabasesDesign Patterns for Distributed Non-Relational Databases
Design Patterns for Distributed Non-Relational Databases
 
NoSql Database
NoSql DatabaseNoSql Database
NoSql Database
 
Apache Cassandra, part 1 – principles, data model
Apache Cassandra, part 1 – principles, data modelApache Cassandra, part 1 – principles, data model
Apache Cassandra, part 1 – principles, data model
 

Recently uploaded

Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideChristina Lin
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...gurkirankumar98700
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software DevelopersVinodh Ram
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based projectAnoyGreter
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityNeo4j
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...MyIntelliSource, Inc.
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureDinusha Kumarasiri
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Andreas Granig
 
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...Christina Lin
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样umasea
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...MyIntelliSource, Inc.
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEOrtus Solutions, Corp
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...soniya singh
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxTier1 app
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsAhmed Mohamed
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmSujith Sukumaran
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio, Inc.
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfAlina Yurenko
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...stazi3110
 

Recently uploaded (20)

Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software Developers
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based project
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered Sustainability
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with Azure
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024
 
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
 
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML Diagrams
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalm
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
 

Cassandra 101

  • 1. Cassandra 101 Scala by the Lagoon Treviso, 28 April 2016
  • 2. THE SPEAKER • Software engineer at Radicalbit • Blogger at codingjam.it • (Re)twitter guy with @supergiampaolo Giampaolo
  • 3. AGENDA 1.What’s Cassandra 2.The CAP Theorem 3.“Internals” 4.CQL 5.Scala/Phantom Cassandra 101 (2.x)
  • 5. What’s Cassandra • NoSQL • High availability • Linear Scalability • Predictable Performance • No Single Point of Failure (peer to peer) • Multi DataCenter (DC) • A hybrid between a key-value and a column oriented • Clients see data in tables • Data manipulation through CQL (similar to SQL) • Not a replacement for a RDBMS “Apache Cassandra is an open source distributed database management system designed to handle large amounts of data across many servers, providing high availability with no single point of failure.”
  • 7. What’s Cassandra • Internet of Things: time series from users, device and sensors • Personalization: ingest and analyze to personalize user experience • Messaging: storing, managing, and analyzing messages • Fraud detection: to analyze quickly patterns • Playlist: storing collections of user selected items Use cases
  • 8. What’s Cassandra • Developed at Facebook for messaging system • From Google Big Table: the storage model • From Amazon Dynamo: the distribution backbone • Open source since 2008 • Apache top level since 2010 • Most stable release: 2.2 (2015) • Latest release 3.4 (March 2016) • Tick-tock releases in 2016 Quick history so far
  • 9. • No master/slave, no Zookeeper, no config server • All nodes can reply to writes and reads • Data is partitioned around the ring • Location of data on ring is determined a function • Data is replicated with a specific factor What’s Cassandra 1 4 2 3 -128 -64 0 64 C* is a big hash ring
  • 11. Three properties of shared data system operating over a network The CAP Theorem Consistency every read would get you the most recent write Availability every node (if not failed) always executes queries within unbounded time (but finite) Partition Tolerance the system continues to operate despite arbitrary partitioning due to network failures
  • 12. The CAP Theorem (rough) 1.AP: the system is Partitioned and Available to clients but not Consistent 2.CP: the system is Consistent and working during a Partition, but there is no Availability 3.AC: the system is Consistent and Available there is no Partition. Does this system really exist? “pick two” “this is often considered to be a misleading presentation, since you cannot build - or choose - 'partition tolerance': your system either might experience partitions or it won't”.
  • 13. The CAP Theorem (finer) 1. Do you respond to the reads with potentially stale information 2. Do you wait (potentially forever) to hear from the other side of the partition and compromise availability? “pick one” or what you give up? If a client writes to one side of a partition, any reads that go to the other side of that partition can't possibly know about the most recent write. We are in a critical condition
  • 14. Consistency & Availability Tradeoff Spectrum Both C and A are strong guarantees in a critical condition But out of critical conditions, a system can be happily consistent and available AP to CP is a spectrum and the whole space is useful Eventual consistency and high availability are good enough AVAILABILITY CONSISTENCY AP CP
  • 15. Beyond CAP: PACELC P(A/C)E(L/C) AVAILABILITY CONSISTENCY AP CP (LESS) LATENCY CONSISTENCY If there is a partition (P) how does the system trade off availability and consistency (A and C) else (E) when the system is running normally in the absence of partitions, how does the system trade off latency (L) and consistency (C)?
  • 16. Cassandra & PACELC C* has a tunable consistency Can move from PC/EC to PA/EL Consistency can be tuned at query level from max availability to immediate consistency AVAILABILITY CONSISTENCY AP CP (LESS) LATENCY CONSISTENCY PA/EL PC/EC
  • 18. Internals A cluster is a peer to peer set of servers Organized in • Data centers • Racks • Nodes Cluster
  • 19. Internals A node needs • Cluster name • Seeds addresses • Its listen address Every node is aware of status of cluster through gossip Joining a cluster
  • 20. Internals Replication Tables are grouped by keyspace Every keyspace has its own replication properties CREATE KEYSPACE books WITH REPLICATION = {'class': 'SimpleStrategy', 'replication_factor' : 3}; CREATE KEYSPACE books WITH REPLICATION = {'class': 'NetworkTopologyStrategy', 'dc-newyork': 3, 'dc-london': 4};
  • 21. Internals Request coordinator SELECT * FROM authors Where name = ‘Poe’ • The node that handles communication with client • Every node can do the coordinator • The driver decides which is the coordinator
  • 22. Internals Consistent hashing CREATE TABLE authors( name text, bio text , PRIMARY KEY (name)); INSERT INTO authors (name, bio) VALUES ('Poe', ’Poe was a writer'); • -263..263 tokens (3.4*1038) distributed in cluster • Every node knows its tokens • Partitioner is a function from a partition key to a token • Nodes and drivers use the same partitioner
  • 23. Internals Replication Poe, Poe was a writer Poe, Poe was a writer CREATE TABLE authors( name text, bio text , PRIMARY KEY (name)); INSERT INTO authors (name, bio) VALUES ('Poe', ’Poe was a writer');
  • 24. Internals Hinted handoff Poe, Poe was an American writer Poe, Poe was an American writer • What if node 1 is down? Do we give up writing? • Hinted handoff allows to replay writes to a momentary unavailable node • It’s optional • There are some limitations • Coordinator keeps the data • What about consistency? UPDATE authors SET bio = ‘Poe was an American writer’ WHERE name = ‘Poe’
  • 25. Internals Consistency level CONSISTENCY = TWO; SELECT * FROM authors WHERE name= 'Poe’; Real read will happen for one node only, the other two will send a digest Poe was an American writer Poe was an American writer Poe was a writer • How many nodes must acknowledge a request to return a positive response to the client (Read/Write) • Set at query level • What if replicas do not agree?
  • 26. Internals Consistency levels there are more • ANY (writes only) • ONE • TWO • THREE • QUORUM • LOCAL_ONE • LOCAL_QUORUM ALL for immediate consistency (high latency) ONE/ANY for eventual consistency (lowest latency)
  • 27. Internals Immediate consistency • Combine read and write to get consistency as this rule: If (nodes_written + nodes_read) > RF then immediate consistency • Examples with RF = 3 • Write: ALL, Read: ONE • Write: QUORUM, Read: QUORUM • Write: ONE, Read: ALL • Is stale data really a problem?
  • 28. CQL
  • 29. CQL • CQL is declarative like SQL and the very basic structure of the query component of the language (SELECTs, INSERTs, …) is the same. • But there are enough differences that one should not approach using it in the same way as conventional SQL (because Cassandra is not relational!) Cassandra Query Language
  • 30. CQL Cassandra Query Language CREATE TABLE authors( name text, gender text, born int, died int, bio text, genre set<text>, PRIMARY KEY (name)); ALTER TABLE authors ADD picture blob; ALTER TABLE authors DROP gender; DROP TABLE authors;
  • 31. CQL Cassandra Query Language Cassandra has upserts, what happens if I want to update the name of an author? SELECT * FROM authors LIMIT 10; SELECT * FROM authors where NAME = 'Herman Melville'; INSERT INTO authors(name) VALUES ('Edgar Alan Poe'); UPDATE authors SET born = 1797 WHERE name = 'Mary Shelley'; UPDATE authors SET genre = genre + {'Gothic literature'} where name = 'Mary Shelley'; DELETE from authors WHERE name = 'Charles Dickens';
  • 32. CQL Invalid queries • SELECT * FROM authors WHERE born = 1797; • SELECT * FROM authors WHERE name like 'Mar%'; • SELECT * FROM authors WHERE NOT name = 'Mary Shelley'; • SELECT * FROM authors WHERE name = 'Mary Shelley' or name = 'Edgar Alan Poe'; • SELECT max(born) FROM authors group by genre; • SELECT * FROM authors ORDER by name; • SELECT * FROM authors JOIN books ON author.name = books.author;
  • 33. CQL How to solve the problem? Create tables that responds to specific queries Logged batch to the rescue Actually won’t work for two authors of 1819, try to insert (George Eliot, 1819) CREATE TABLE authors_by_year ( born int, name text, PRIMARY KEY (born)); INSERT INTO authors_by_year (born, name) VALUES (1797, 'Mary Shelley') INSERT INTO authors_by_year (born, name) VALUES (1819, 'Herman Melville') SELECT * FROM authors_by_year WHERE born = 1797;
  • 34. CQL Partition key Primary key Partition Row • Partition is a list of rows and has a Partition key, simple or compound • Every row has its primary key composed by partition key and (eventual) other columns (said clustering) and it’s ordered inside partition • Partition key and primary key, something like a two level key • Partition key is related to token so a partition cannot be split between nodes
  • 35. CQL Partition example CREATE TABLE books( author text, born int static, title text, published int, PRIMARY KEY ((author), title); INSERT INTO books(author, title) VALUES ('Melville', 'White-Jacket'); UPDATE books SET born = 1819 WHERE author = 'Melville’; INSERT INTO books(author, title, published) VALUES ('Melville', 'Moby Dick' , 1851);
  • 36. CQL Partition example SELECT * FROM books WHERE author = 'Melville' author | title | born | published ----------+--------------+------+----------- Melville | Moby Dick | 1819 | 1851 Melville | White-Jacket | 1819 | null
  • 37. CQL Filtering and ordering is possible on clustered columns SELECT * FROM books WHERE author = 'Melville' ORDER BY title DESC; author | title | born | published ----------+--------------+------+----------- Melville | White-Jacket | 1819 | null Melville | Moby Dick | 1819 | 1851 SELECT * FROM books WHERE author = 'Melville' AND title >= 'O'; author | title | born | published ----------+--------------+------+----------- Melville | White-Jacket | 1819 | null
  • 38. CQL Filtering and ordering is possible on clustered columns SELECT * FROM books WHERE title >= 'O'; InvalidRequest: code=2200 [Invalid query] message="Cannot execute this query as it might involve data filtering and thus may have unpredictable performance. If you want to execute this query despite the performance unpredictability, use ALLOW FILTERING” SELECT * FROM books WHERE title >= 'O’ ALLOW FILTERING; author | title | born | published ----------+--------------+------+----------- Melville | White-Jacket | 1819 | null
  • 40. PHANTOM Phantom • Type-safe Scala DSL for Cassandra • Built atop Datastax Java Driver • Adds type safety to CQL statements • Add reactivity (Futures!) • Performances comparable to direct Java implementation • Freeware/Commercial versions • https://github.com/outworkers/phantom • Sample code at https://github.com/giampaolotrapasso/cassandra-101-scala- examples
  • 41. PHANTOM Books case class Book( author: String, born: Int, title: String, published: Option[Int] = None )
  • 42. PHANTOM Books class BooksTable extends CassandraTable[BooksDAO, Book] { override val tableName = "books" object author extends StringColumn(this) with PartitionKey[String] object born extends IntColumn(this) with StaticColumn[Int] object title extends StringColumn(this) with ClusteringOrder[String] object published extends OptionalIntColumn(this) override def fromRow(row: Row): Book = { Book( author = author(row), born = born(row), title = title(row), published = published(row) ) } }
  • 43. PHANTOM Books abstract class BooksDAO extends BooksTable with RootConnector { def insertNewStatement(book: Book) = { insert .value(_.author, book.author) .value(_.born, book.born) .value(_.title, book.title) .value(_.published, book.published) } def insertNew(book: Book): Future[dsl.ResultSet] = insertNewStatement(book).future() def selectByAuthor(author: String): Future[List[Book]] = { select.where(_.author eqs author).fetch() } def updateBookStatement(author: String, book: String, published: Option[Int]) = { update .where(_.author eqs author).and(_.title eqs book) .modify(_.published setTo published) } }
  • 44. PHANTOM Books by year case class BookByYear(year: Int, book: String) class BooksByYearTable extends CassandraTable[BooksByYearTable, BookByYear] { override val tableName = "books_by_year” object year extends IntColumn(this) with PartitionKey[Int] object book extends StringColumn(this) with ClusteringOrder[String] with Ascending override def fromRow(row: Row): BookByYear = { BookByYear( year = year(row), book = book(row)) } } abstract class BooksByYearDAO extends BooksByYearTable with RootConnector { def insertNewStatement(bookByYear: BookByYear) = { insert .value(_.year, bookByYear.year) .value(_.book, bookByYear.book) } def insertNew(postByAuthor: BookByYear) = insertNewStatement(postByAuthor).future def selectByYear(year: Int): Future[List[BookByYear]] = { select.where(_.year eqs year).fetch() } }
  • 45. PHANTOM Configuration object Config { val keySpace = KeySpace("books") val contactPoint: KeySpaceBuilder = ContactPoint( host = "localhost", port = ContactPoint.DefaultPorts.live) val keySpaceConnector: KeySpaceDef = contactPoint.keySpace(keySpace.name) }
  • 46. PHANTOM Database class Database(val keySpaceConnector: KeySpaceDef) extends DatabaseImpl(keySpaceConnector) { object books extends BooksDAO with keySpaceConnector.Connector object booksByYear extends BooksByYearDAO with keySpaceConnector.Connector def insertBook(book: Book) = { var batch = Batch.logged .add(books.insertNewStatement(book)) book.published.map { year => val byYear = BookByYear(year, book.title) batch = batch.add(booksByYear.insertNewStatement(byYear)) } batch.future() } } object BookDatabase extends Database(Config.keySpaceConnector)
  • 47. PHANTOM Run! implicit val space: KeySpace = BookDatabase.space implicit val session: Session = BookDatabase.session Await.result(BookDatabase.autocreate().future, 10 seconds) val book1 = Book("Melville”, 1819, "White-Jacket”, Some(1850)) val book2 = book1.copy(title = "Moby Dick", published = Some(1851)) val book3 = Book("Hemingway”, 1899, "For Whom the Bell tolls”) val book4 = Book("Dino Buzzati”, 1906, "Il deserto dei tartari”, Some(1940)) val books: List[Future[ResultSet]] = List(book1, book2, book3, book4).map(p => BookDatabase.insertBook(p)) val operations: Future[List[ResultSet]] = Future.sequence(books) Await.result(operations, 10.seconds)
  • 48. PHANTOM Run! val listOfMelville: Future[List[Book]] = BookDatabase.books.selectByAuthor("Melville") listOfMelville.onComplete { case Success(list) => println(s"${list.size} books by Melville ") case Failure(x) => println(x) } Await.result(listOfMelville, 3.seconds) val booksOf1940 = BookDatabase.booksByYear.selectByYear(1940) booksOf1940.onComplete { case Success(list) => println(s"${list.size} books in 1940") case Failure(x) => println(x) } Await.ready(booksOf1940, 3.seconds)