We’ve just added a new course on using Concurrency with FoundationDB. Like all of our online courses, it’s free and browser-accessible. The course is targeted to developers who are familiar with the FoundationDB Key-Value Store API and want to achieve high throughput in their applications. If you’re new to FoundationDB or the Key-Value Store API, you can get up to speed by first taking the introductory course on Building FoundationDB Layers.
Concurrency and Throughput
FoundationDB makes it easy to get good performance from the start. At the same time, the Key-Value Store is designed to maximize throughput as an application scales, and effective use of concurrency is essential to that goal. If you're developing a high-throughput application with FoundationDB, you need to know how to take advantage of concurrency.
FoundationDB reaches its maximum performance only with a highly concurrent workload. A FoundationDB cluster might have a read latency of 1 ms and yet be capable of far more than 1 thousand reads per second. In fact, millions of reads per second are possible. To achieve this rate, there must be thousands of read requests happening concurrently. Not having enough pending requests is the single biggest cause of under-performance with FoundationDB.
That’s why it’s important to understand how transactions work with optimistic concurrency control. Transactions guarantee the ACID properties and make it easy to write code that’s correct. However, correct transactions can still conflict with each other. The course explains the read-write patterns that lead to conflicts and teaches you how to avoid them. Let’s look a bit more closely at transactions and conflicts.
Transactions let you safely access multiple keys as logical unit, greatly simplifying the task of having multiple clients concurrently access shared data. By default, FoundationDB’s transactions enforce the ACID property of isolation in the strong form of serializability.This property means that, if your transactions work correctly in any sequential order, then they remain correct when executed concurrently. In other words, transactions let you write concurrent functions as if they were serial, making it easy to write code that’s “correct by default.”
Serializability is a powerful tool, and like any such tool, it must be used appropriately. When serializable transactions concurrently read and write the same keys, they become vulnerable to conflicts. Transactions that conflict usually need to be retried, and if this happens too often, it can degrade performance and threaten the scalability of your system.
FoundationDB supports a number of effective techniques for avoiding conflicts with various read-write patterns. In many cases, conflicts can be avoided using design recipes for data modeling that decompose data over multiple keys. For more challenging read-write patterns, the API supports capabilities such as:
- atomic operations for common operations on single keys;
- snapshot reads that weaken the isolation of individual transactions;
- conflict ranges for ensuringinvariants even without serializability.
Best of all, these techniques can be encapsulated within high-contention data structures that allow data to be accessed using a simple, familiar interface. As an illustration, the course walks through a high-contention priority queue for multiple clients and shows how to use it with a concurrent search algorithm.
Get In Touch!
We'd love your feedback on the course. If you have questions or comments on the anything in the course, come discuss it with us in our Google Group!