What is Chronicle Queue?
A Low-latency message queue
Chronicle Queue is a "record everything" message queue which operates with microsecond real-time latency. It can be used for rapid Interprocess Communication (IPC) without affecting your system performance. Hence, it is tailored to transfer and store large amounts of data in low-latency environments, where recording of information is a central e.g. the most demanding High Frequency Trading systems.
You could consider Chronicle Queue to be similar to a low-latency broker-less durable/persisted JVM topic. It is a distributed, unbounded, and persisted queue that:
-
supports asynchronous RMI and Publish/Subscribe interfaces with microsecond latencies.
-
passes messages between JVMs in under a microsecond (in optimised examples).
-
passes messages between JVMs on different machines via replication in under 10 microseconds (in optimised examples).
-
provides stable, soft, real-time latencies into the millions of messages per second for a single thread to one queue; with total ordering of every event.
Efficiency
Chronicle Queue aims to achieve latencies of under 40 microseconds for 99% to 99.99% of the time. Without replication, Chronicle Queue delivers latencies below 40 microseconds end-to-end across multiple services. Often the 99% latency is entirely dependent on the choice of operating system and hard disk sub-system.
Benchmarks
When publishing 40-byte messages, a high percentage of the Chronicle Queue yields latencies under 1 microsecond. In the tables below, the 99th percentile latency is the worst 1 in 100, and the 99.9th percentile is the worst 1 in 1000 latency.
Batch Size | 10 million events per minute | 60 million events per minute | 100 million events per minute |
---|---|---|---|
99%ile |
0.78 µs |
0.78 µs |
1.2 µs |
99.9%ile |
1.2 µs |
1.3 µs |
1.5 µs |
Batch Size | 10 million events per minute | 60 million events per minute | 100 million events per minute |
---|---|---|---|
99%ile |
20 µs |
28 µs |
176 µs |
99.9%ile |
901 µs |
705 µs |
5,370 µs |
100 million events per minute is sending an event every 660 nanoseconds; replicated and persisted. |
This performance is not achieved using a large cluster of machines. This is using one thread to publish, and one thread to consume. |
No garbage collection
High-performance applications simply cannot tolerate the non-deterministic slowdowns that the Java garbage collector yields when cleaning the heap. Therefore, Chronicle Queue avoids garbage collection altogether by managing the memory stack manually with RandomAccessFiles
. This means a Chronicle Queue can be viewed as a management interface over off-heap memory, on which anyone can build their own solution. E.g. it is suitable for exceptionally fast interprocess communication (IPC) with no negative impact on the system performance.
Persistent
Chronicle Queue assumes disk space is cheap compared with memory. It makes full use of the disk space available, hence is not limited to the main memory of the machine. A complementary spinning HDD can store many TBs of disk space for little cost. Further, all data is saved in memory-mapped files which have a trivial on-heap overhead, even with 100 TB of data.
Instead of using a broker, Chronicle Queue relies on the operating system (OS) to do all the work. If the application dies, the OS keeps running for seconds longer, meaning no data is lost; even without replication.
Compression
Replication for Chronicle Queue supports Chronicle Wire Enterprise. This enables real-time compression by calculating the deltas for individual objects, as they are written. This can reduce the size of messages by a factor of 10, or better, without the need for batching; that is, without introducing significant latency.
Chronicle Queue also supports LZW, Snappy, and GZIP compression. These formats however add significant latency. These are only useful if you have strict limitations on network bandwidth.
Delivery mode semantics
Chronicle Queue supports a number of semantics:
-
Every message is replayed on restart.
-
Only new messages are played on restart.
-
Restart from any known point using the index of the entry.
-
Replay only the messages you have missed. This is supported directly using the methodReader/methodWriter builders.