Cassandra support for transactions
Unlike commonly used relational database platforms, Cassandra does not support ACID transactions. Cassandra prioritizes availability and being partition-tolerant above consistency. Consistency is tuneable, but in general, the design precludes transactions. That is, there is no guarantee, even when configuring a high level of consistency, that a read will remain accurate by the time a related write happens.
Cassandra does support what are called lightweight transactions (LWTs), and these are sometimes used in applications to approximate ACID transactions. This feature uses an extension of the Paxos algorithm.
The Paxos algorithm
The Paxos algorithm relies on distributed nodes coming to a consensus. Very basically, a node that wants to accept a write communicates with other nodes to get a “promise” from them that no other writes will be accepted until this one is complete. Cassandra extends this algorithm with LWTs to include two additional steps, so that there are four round-trip network communications in total:
- prepare/promise: The node wishing to accept a write communicates with other nodes, and the other nodes respond with an agreement.
- read/results: The initiating node makes a read request, and the other nodes respond with the data.
- propose/accept: The initiating node sends the proposed write, and the other nodes accept it.
- commit/ack: The initiating node commits the write, and the other nodes acknowledge (and commit) the write.
Usual performance degradation
This series of phases implies two things: (a) time coordination among nodes is important when using LWTs, and (b) the amount of network traffic, memory and CPU usage, and waits for responses around the cluster all increase.
In our experience, LWTs are a likely cause for WriteTimeoutException exceptions. In situations like these, you cannot know for sure if the LWT has been applied, forcing you to retry it to fallback to a stable state. Because they are much more expensive than normal updates, the driver will not for this automatically for you.
Because of this increased load (non-LWT writes require a single round-trip network communication) on all server resources, LWTs are expensive and not meant to make up most of your application queries. They should be used rarely, in the small percentage of your application queries that truly require consistency. For example, you may need to ensure a user has a unique ID number during user creation, but not every time-related user data is written. Alternatively, if your application requires a high percentage of transactional statements, Cassandra is not the best solution.