Distributed ACID Transactions
Couchbase’s traditional strong consistency across single documents is now complemented by multi-document, distributed ACID transactions. The Read Committed model of isolation offers a balance between safety and performance, and preventing the reading of ‘dirty’ data. Couchbase manages transactions automatically, storing metadata in the system as your application executes transactional logic.
Couchbase’s traditional strong consistency across single documents is now complemented by multi-document, distributed ACID transactions. The flexible schema model inherent to JSON allows the expression of data in a more natural way than would be typically found in an RDBMS, including the extension of the inherent schema over time. Careful architecting of your application can avoid the performance trade-off of needing more than single document atomicity. Where a more immediate and guaranteed form of consistency may be required across documents, Couchbase offers Distributed ACID Transactions.
Couchbase transactions offer the same flexibility that users are used to from traditional, relational databases. Reads and writes may be freely mixed, branching logic inside a transaction is supported, and data may be manipulated without restriction. There is no limit to the number of documents that can be updated in a transaction. The provided API has a strong focus on being easy to use when developing, with transactions automatically being retried as required.
This is a Beta release, available on Java only (with both the traditional asynchronous and the reactive asynchronous APIs). Other languages will be available in the future. ACID Transactions are implemented from Couchbase Data Platform 6.5 onwards, and require the Java SDK from 3.0 onwards. It is dependent upon the Synchronous Replication improvements introduced in Couchbase Data Platform 6.5. NTP across the Couchbase cluster is also strongly recommended, to ensure any abandoned transactions are cleaned up in a timely manner.
For single document operations, Couchbase has long provided a form of ACID semantics comparable with that of traditional RDBMSs. In many use cases, it should be possible to combine data into a single document to take advantage of these ACID properties.
Where multi-document operations are unavoidable, and atomicity is required, Couchbase ACID transactions offer all-or-nothing semantics which we break down below into the four components of the ACID model.
All-or-nothing — should any of the statements in a transaction fail, the entire transaction fails, leaving the documents unchanged. This applies to insert, update, and delete operations across multiple documents.
Synchronous Replication, available from Couchbase Data Platform 6.5 onwards, ensures documents are synchronously replicated to a majority of replicas.
In addition, eventual consistency is provided for Global Secondary Indexes and Full Text Search Indexes.
At_Plus (Read Your Own Writes) can be used in N1QL queries to wait for indexes to catch up to a transaction’s updates.
Couchbase offers Read Commited isolation, ensuring that only committed data is seen. Read Committed offers an excellent balance of consistency with the high performance that Couchbase users expect.
Read Committed guarantees two things: 1) that no transaction will see ‘dirty’ (uncommitted) data from another transaction, and 2) that if two transactions try to update the same document then this will be detected, and only one transaction will be allowed to proceed.
In fact, Couchbase’s isolation level is Monotonic Atomic View, a level above Read Committed in the Jepsen hierarchy, which is our solution to providing a single atomic commit in a distributed system. Essentially, as soon as a transaction commits, other transactions will only see committed data from that transaction.
Non-transactional reads will not perform this Monotonic Atomic View logic, and will see the eventually consistent version of the commit. Reads will never see ‘dirty’ uncommitted data.
Changes committed in a transaction survive one or more failures such as node crashes, disk failures, or network partitions. The number and type of concurrent failures tolerated depends upon the durability setting used. For maximum protection, use the
persistToMajority setting provided in the new Synchronous Replication API. The default in transactions is
Majority, meaning that each write must be in-memory on a majority of replicas before the transaction continues.
Couchbase transactions are designed to take advantage of the highly distributed, highly performant nature of the Couchbase architecture. The only nodes that will be involved in the transaction are those that are required to be, meeting the ‘high availability’ guarantees described in this paper by Bailis et al. Care has been taken to ensure that there are no single points of contention, so that your transactions throughput will scale as your system does.
For performance, N1QL indexes are eventually consistent with transaction commits, e.g. they are not atomically updated with the commit.
Support is provided for the common scenario of needing to ‘read your own writes’ (RYOW), using the existing N1QL feature
At_Plus. This allows a N1QL query to first wait for any required indexes to include all the mutations from a transaction.
Read Committed isolation level means that N1QL queries will never see ‘dirty’ uncommitted data. But, snapshot isolation is not provided: if a transaction commits while a query is ongoing, then the query may return some data it had already collected from before the commit, and some from after.
XDCR streams are part of an eventually consistent data model. Atomicity is not provided across XDCR.
XDCR Active-passive configurations are supported with Transactions. Active-active configurations, where documents may be changed in multiple places concurrently relying on XDCR’s conflict resolution, are not supported with the use of ACID Transactions in the current release. They will work in a situation where the application can guarantee that the two clusters will not attempt concurrent transactions involving the same document.
The following guidelines need to be followed for Couchbase ACID Transactions with Active-Passive XDCR: Use Last Write Wins for conflict resolution. Applications must wait for all outstanding requests to complete, or should abort the change before failing over the cluster. Ensure that backup cluster can take on active traffic, only after n ms, where n is the maximum time drift between the two clusters. Application must completely fail over all application requests to the backup cluster.
Users will see additional documents created in each bucket when they first use transactions. Namely:
A number of Active Transaction Records will be created, which will grow to 1024 documents over time. These documents will have ids starting with “atr-”. A single “txn-client-record” document is also created.
These documents are automatically maintained by Couchbase transactions, and should not be changed by the application. These documents do not contain any content directly so they should not accidentally impact query or full text results.
|Staged mutations are stored alongside documents within Couchbase Server, helping to provide excellent performance. This means that the standard Couchbase document size limit of 20 MB is reduced to 10 MB for documents involved in a transaction.|
There is some unavoidable overhead to transactions, in order to provide the atomicity and consistency guarantees. Each write is doubled — first, to stage the data, then to commit it — and four further writes per transaction are used for important metadata.
It is suggested that in many cases where customers may be considering transactions, the application should first consider the single document model. Together with the improved durability guarantees offered by Synchronous Replication this will offer atomicity with the excellent throughput and latency that users expect from Couchbase.
This initial release of Couchbase transactions requires a degree of cooperation from the application.
Applications using the bucket and documents should ensure that non transactional updates (such as KV upserts or N1QL UPDATEs) and transactional updates are never done simultaneously to the same document.
We plan to lift this requirement in a future release. In the meantime, a mechanism is provided whereby the application can subscribe to an events feed that will notify if this requirement has been violated, and on which documents.
This initial release of multi-document, distributed ACID transactions carries certain limitations mentioned above, the majority of which are planned for address in future releases.