We all know that Cassandra is a distributed database. However there’re situations where one needs to perform an atomic operation and for such cases a consensus must be reached between all the replicas.
For instance when dealing with payments we might require that we only insert the row once.
CQL provides an easy to use IF syntax to deal with such cases.
INSERT INTO payments (payment_time, customer_id, amount) VALUES (2016-11-02 12:23:34Z, 123, 12.00) IF NOT EXISTS;
Note: You can also use
IF EXISTS or any other
UPDATE payments SET amount = 10.00 WHERE payment_date = 2016-11-02 12:23:34Z AND customer_id = 123 IF amount = 12.00
IF NOT EXISTS isn’t free. Under the hood it triggers a lightweight transaction (also known as CAS for Compare And Set).
It’s called lightweight because it doesn’t imply locking as it’s the case in traditional (SQL) databases.
Lightweight doesn’t mean free either. In fact such queries require a read and a write and they also need to reach consensus among all the replicas.
In Cassandra the consensus is reached by implementing the Paxos algorithm (that we’ve already discussed previously).
The leader role is not a master role (any node can act as a leader or more accurately as a proposer).
Briefly the proposer picks a proposal number and sends it to the participating replicas. (Remember the number of replicas is determined by the keyset’s replication factor). If the proposal number is the highest the replica has seen, the replica promises to not accept any earlier proposal (i.e. a proposal with a smaller number).
If the majority promises to accept the proposal, the leader may proceed with its proposal. However if a replica replies with another value for that proposal it’s the value the leader must propose.
This gives the linearisable or serial property because if a leader interrupts an on-going proposal it must complete it before proposing its own value.
Cassandra uses Paxos to implement a Compare-And-Set operation so it needs to intertwin read and writes into the Paxos protocol.
Now that we have a clear picture in mind of what’s happening during a lightweight transaction (LWT) let’s discuss the consistency levels.
As there is a read and a write phase involved in the transaction we need 2 consistency levels.
Serial consistency levels
The read consistency is called the serial consistency and is set using the
SERIAL CONSISTENCY command. It can take only 2 values:
The only difference is when Cassandra uses several datacenters.
LOCAL_SERIAL runs Paxos only in the local datacenter whereas
SERIAL runs it accross all datacenters.
SERIAL CONSISTENCY command is only available for conditional updates (
INSERT with the
Then the write phase uses the regular
CONSISTENCY command. It default to
ONE but can be set to any of the write consistency levels.
The last thing is if we want to consider any on-going lightweight transactions when reading a value. In this case we want to read the value of any on-going transaction.
This can be done by setting the read consistency level to
SERIAL. This is the regular consistency level, the one set with the
CONSISTENCY command (not the serial consistency) and it applies to read queries only (i.e.