Client Concurrency Model
Aeron Client Concurrency Model
This page is intended to complement the Aeron GitHub Client Concurrency Model page, with more of a focus on the underlying files (shared memory buffers).
The application uses a Publication API object that lives in the Client API to write messages to a log buffer. This is either an ExclusivePublication or a ConcurrentPublication. They differ in their thread safety - ExclusivePublication has no thread safety code and is faster, but it can only be used by one thread; ConcurrentPublication can safely be used by multiple threads.
The two types of Publication we've discussed so far (IpcPublication and NetworkPublication) are Media Driver concerns. They control what happens to a message after it has been written to a Publication log buffer. Once a message is in a Publication log buffer, it will either be read directly by a Subscription (for an IPC Publication) or sent over the network (for a Network Publication).
The two Client-side Publication API objects and the two Driver-side Publication objects are orthogonal and all four combinations are allowed. The application chooses between the Publication API classes by choosing between two different methods in the Client API when creating the Publication:
Aeron.addPublication(channel, streamId) // creates a ConcurrentPublication
Aeron.addExclusivePublication(channel, streamId)
Concurrent Publications
A Concurrent Publication is thread safe and allows messages to be safely written to the log buffer from multiple threads, or even different processes on the same machine.
The first time a Concurrent Publication is created for a given Channel and StreamId, the Media Driver creates the
Publication log buffer, then returns a ConcurrentPublication
API object to the application. This API object can be
used by multiple threads to write messages to the Publication log buffer.
If the application creates a second Concurrent Publication for the same Channel and StreamId, it is returned a second
ConcurrentPublication
API object, but the API object writes to the existing Publication log buffer. The same applies
if a different process on the same machine (same Media Driver) creates a Concurrent Publication for the same Channel
and StreamId - it will get a new ConcurrentPublication
API object, but it will write to the existing Publication
log buffer (remember the log buffer is in shared memory, so it can be written to by any process on that machine).
Thread-safety is maintained by the way the ConcurrentPublication
updates the log buffer. It uses a
CAS operation
to bump the tail position in the log buffer to reserve space for the message. This is safe across threads and
processes - it doesn't matter which ConcurrentPublication
API object is used to write to the log buffer.
Exclusive Publications
When an application knows it will only publish to a Publication from a single thread, it can create an Exclusive Publication, which uses faster operations that are not thread safe. It takes advantage of the Single Writer Principle to achieve greater throughput. Each Exclusive Publication has its own log buffer, which will not be shared with any other Publication. If a second Exclusive Publication (or even a Concurrent Publication) is created for the same Channel and StreamId, it will have its own log buffer and the Subscription will have to iterate over them both.
Log buffer data format
The data format in a Publication log buffer is the same, whether it is written to by an Exclusive or a Concurrent Publication. The difference is just in the thread-safety of the write operations.
SessionIds
You can think of SessionIds as belonging to the log buffer files. Each ExclusivePublication
has its own log buffer
file and thus its own SessionId. If there is more than one ConcurrentPublication
API object for the same Channel
and StreamId on a given machine, they will all use the same log buffer file and thus use the same SessionId (and
note that the Subscriber won't be able to tell which API object wrote each message). ConcurrentPublications
for the same Channel and StreamId on a different machine will have a different log buffer (different Media Driver
as they're on different machines) and a different SessionId.
Subscriptions
There is only one kind of Subscription. They do not vary based on Concurrent vs Exclusive or Network vs IPC. Subscriptions are not thread-safe and should only be used by a single thread. However, it is possible to create multiple Subscriptions for the same Channel and StreamId. Each Subscription tracks its own position in each log buffer it reads from.
Note that if there is more than one log buffer for a Channel and StreamId (more than one SessionId), and more than one Subscription, the Subscriptions may read from the log buffers in a different order and receive messages from different Sessions in a different order.