5. 5
The
“C”
is
for
Consistency
“..
any
transacQon
will
bring
the
database
from
one
valid
state
to
another.”
“…all
clients
have
the
same
view
of
the
data.”
CAP
Theorem
“C”
ACID
“C”
Eventually..
6. 6
Tunable
Consistency
• Manage
consistency
in
your
applicaQon
• Decide
consistency
per
transacQon
CONSISTENCY ONE;
UPDATE users SET name='IAN' WHERE name='ian';
CONSISTENCY ALL;
SELECT * FROM users WHERE name='ian';
7. 7
Strong
Consistency
*
QUORUM
=
(replicaQon
factor
/
2)
+
1
nodes
wri_en
nodes
read
replicaQon
factor
R
+
W
>
N
Write
ONE
Read
ONE
=
WEAK
Write
ONE
Read
ALL
=
STRONG
Write
ALL
Read
ONE
=
STRONG
Write
QUORUM
Read
QUORUM
=
STRONG
8. 8
“A”
is
for
Atomicity
START TRANSACTION;
INSERT INTO users (name, country)
VALUES(‘ian’, ‘Australia’);
INSERT INTO users (name, country)
VALUES(‘meg’, ‘Japan’);
COMMIT; // or ROLLBACK
aka
transacQon
consistency,
linearizable
consistency,
serial
isolaQon
level
All
succeed
or
none
succeed
SQL:
9. 9
Cassandra
BATCH
BEGIN BATCH
INSERT INTO users (name, country)
VALUES(‘ian’, ‘Australia’);
INSERT INTO users (name, country)
VALUES(‘meg’, ‘Japan’);
APPLY BATCH;
Guarantees
ALL
will
succeed
or
ALL
will
fail
CQL:
10. 10
“I”
Is
For
Isola8on
START TRANSACTION;
SELECT current_caps FROM bottlecaps
WHERE name='ian' FOR UPDATE;
UPDATE bottlecaps
SET current_caps = current_caps + 1;
COMMIT;
Is
anyone
else
changing
this
data?
SQL:
11. 11
Cassandra
Lightweight
Transac8ons
INSERT INTO users (name, country)
VALUES(‘ian’, ‘Australia’) IF NOT EXISTS;
UPDATE users SET country=‘Japan’
WHERE name=‘ian’ IF country=‘Australia’;
Allows
you
to
set
condiQons
of
an
update
CQL:
12. 12
Op8mis8c
vs
Pessimis8c
Locking
PessimisQc
(SQL)
OpQmisQc
(CQL)
SELECT
FOR
UPDATE
SELECT
FOR
UPDATE
COMMIT
COMMIT
lock
SELECT
SELECT
UPDATE
..
IF
…
UPDATE
..
IF
…
Thread
1
Thread
2
lock
Thread
1
Thread
2
13. 13
PuTng
It
Together
1. Record a transaction
2. Keep track of the total
3. Ensure they are updated atomically
Example
14. 14
name
current_caps tx_id amount balance
ian
0
tx001
null
null
Example: Bottlecaps
CREATE TABLE bottlecaps (
name text,
current_caps int STATIC,
tx_id int,
amount int,
balance int,
PRIMARY KEY ((name), tx_id)
);
// initialize user
INSERT INTO bottlecaps (name, tx_id, current_caps)
VALUES ('ian', 'tx001', 0);
15. 15
name
current_caps tx_id amount balance
ian
10
tx001
null
null
tx002
10
10
Get Some Caps
BEGIN BATCH
UPDATE bottlecaps SET current_caps = 10
WHERE name='ian'
IF current_caps = 0;
INSERT INTO bottlecaps (name, tx_id, amount, balance)
VALUES ('ian', 'tx003', 7, 17);
APPLY BATCH;
16. 16
name
current_caps tx_id amount balance
ian
17
tx001
null
null
tx002
10
10
tx003
7
17
Get Some More Caps
BEGIN BATCH
UPDATE bottlecaps SET current_caps = 17
WHERE name='ian'
IF current_caps = 10;
INSERT INTO bottlecaps (name, tx_id, amount, balance)
VALUES ('ian', 'tx003', 7, 17);
APPLY BATCH;
17. 17
name
current_caps tx_id amount balance
ian
2
tx001
null
null
tx002
10
10
tx003
7
17
tx004
-15
2
Spend 15 Caps
BEGIN BATCH
UPDATE bottlecaps SET current_caps = 2
WHERE name='ian'
IF current_caps = 17;
INSERT INTO bottlecaps (name, tx_id, amount, balance)
VALUES ('ian', 'tx004', -15, 2);
APPLY BATCH;
18. 18
Summary
Do
the
work
in
your
applicaQon
code.
1. Consistency
across
all
nodes
• Tune
Cassandra
access
to
behave
with
“strong
consistency”
2. Atomicity
of
TransacQons
• Use
Cassandra
BATCH
3. IsolaQon
of
TransacQons
• Use
a
Lightweight
TransacQon
19. 19
Thanks
☺
Ian
Chen
ian.chen@rakuten.com
@icchanosaur