Apache Cassandra vs. Apache Ignite: Strong Consistency and Transactions

DZone 's Guide to

Apache Cassandra vs. Apache Ignite: Strong Consistency and Transactions

Ignite proves that distributed ACID transactions and strong consistency are widely adopted by modern databases, along with horizontal scalability and high availability.

· Database Zone ·
Free Resource

NoSQL databases such as Apache Cassandra are the best-known examples of eventually consistent systems. A contract of such systems is simple: if an application triggers a data change on one machine, then the update will be propagated to all the replicas at some point in time — in other words, eventually.

Until the change is fully replicated, the system as a whole will stay in an inconsistent state. And who knows where the application will end up if it tries to read the changed value from an out-of-sync replica — or even worse, update the value concurrently?

NoSQL vendors and users accept this contract and behavior because eventual consistency makes a distributed system highly scalable and performant. That's true. If strong consistency or transactions are required, then examine offerings of the RDBMS world. That's no longer true!

Image title

In the previous article, we figured out that SQL can be efficiently used even if a distributed database is your system of records. Apache Ignite, for instance, allows us not only execute simple SQL operations but also to join data stored on several machines easily. What was impossible a decade ago has become a standard capability of modern distributed databases.

The same story repeats with consistency and transactions: we can mix and match the horizontal scalability and high performance of the NoSQL world with capabilities of the RDBMS realm. Let's take Apache Cassandra as a NoSQL database sample and compare it to Apache Ignite that represents modern distributed databases.

Tunable Consistency and Lightweight Transactions

It's not a secret that Cassandra takes care of higher data consistency and transactions. There is a demand for that from its users.

First, if we set write and read consistency levels to ALL, we will get the highest consistency possible. In this mode, Cassandra will complete a write after it's written to the commit log and memtable on all replica nodes in the cluster. A read, respectively, will return a value only after all the replicas agree on it. It's a handy capability that brings down performance in favor of consistency and can be enabled if you need it.

Second, this write-read ALL mode doesn't solve a problem of concurrent updates. What if we want to update a user account making sure nobody intervents while the update happens? Transactions usually address such tasks and Cassandra users can leverage from so-called lightweight transactions (LWT).

The lightweight transactions are explicitly designed for the situations to prevent concurrent updates of a single row. For instance, if two different applications are attempting to update a user account, then the LWT ensures that only one application succeeds while the other fails. Assuming that the first application will initiate a transaction earlier, we can safely and atomically set Bob Smith's age to 35 as follows:

UPDATE user_account
SET    user_age=35
IF     user_id=’Bob Smith’; 

But what about more complex operations such as a money transfer from one bank account to another? Unfortunately, that's out of the scope of both Cassandra and its LWT because the latter is restricted to a single partition while the banks account can be stored on different cluster nodes.

Strong Consistency and ACID Transactions

While the money transfer is a big deal for Cassandra, it's a typical operation you can do in Apache Ignite.

First, to achieve the strongest consistency in Ignite, we will set FULL_SYNC synchronization and transactional modes for caches (AKA tables). We can even request Ignite to fsync every update to a write-ahead-log file to survive power failures of the whole cluster.

Second, by using Ignite transactional APIs, we can do the money transfers between two accounts that might be stored on different nodes:

try (Transaction tx = Ignition.ignite().transactions().txStart(PESSIMISTIC, REPEATABLE_READ)) {
    Account acctA = accounts.get(acctAid);

    Account acctB = accounts.get(acctBid);

    // Withdraw from accountB.

    // Deposit into accountA.

    // Store updated accounts in the cluster.
    accounts.put(acctAid, acctA);
    accounts.put(acctBid, acctB);


That's it. Ignite ACID transactions are based on an advanced version of two-phase commit protocol (2PC) that guarantees data consistency even during failures. Refer to this series to learn more about Ignite's transactional subsystem implementation details.


Apache Ignite proves that distributed ACID transactions and strong consistency are real and widely adopted by modern databases along with horizontal scalability and high availability. It's all about configuration and your needs. Just check out how many financial institutions trust Ignite with their mission-critical applications — confirming that this ASF project is not bluffing.

acid, apache cassandra, apache ignite, availability, consistency, database, nosql, scalability, transactions

Published at DZone with permission of Denis Magda . See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}