Redis Batched
A Redis batch projection is a atomic projection
based on Redisson RBatch.
Like Redis transactional projections, also this projection type
is more lightweight than Spring transactional projections.
No Spring PlatformTransactionManager
is needed,
the RBatch object of
the Redisson library is enough.
Working with a Redis batch projection is asynchronous as multiple commands are collected and executed later in an atomic way (all or none).
Motivation
You would want to use Redis Batched for two reasons:
- atomicity of factStreamPosition updates and your projection state updates
- increased fact processing throughput
The performance bit is achieved by skipping unnecessary factStreamPosition updates and (more importantly) by reducing the number of operations on your Redis backend by using a redisson batch
instead of single writes for bulkSize
updates.
The bulkSize
is configurable per projection via the @RedisBatched
annotation.
Redisson batches improve performance significantly by collecting operations and executing them together as well as delegating all possible work to an async thread. It has the effect, that you cannot read non-executed (batched) changes. If this is unacceptable for your projection, consider Redis transactional projections. See the Redisson documentation for details.
Other than a transaction, writes registered (but not yet executed) on a Redis batch can not be read.
A Redis batch projection, therefore, is recommended for projections which
- handle a lot of events and
- don’t require reading the current projection state in an event handler.
For an alternative that allows access to the projection state during event handling, see Redis transactional projection.
Configuration
In order to make use of redisson RBatch support, the necessary dependency has to be included in your project:
<dependency>
<groupId>org.factcast</groupId>
<artifactId>factcast-factus-redis</artifactId>
</dependency>
Structure
A Redis batch projection supports managed- or subscribed projections and is defined as follows:
- it is annotated with
@RedisBatched
- it implements
RedisProjection
revealing theRedisClient
used - it provides the serial number of the projection via the
@ProjectionMetaData
annotation - the handler methods receive an additional
RBatch
parameter
This structure is similar to a Redis transactional projection,
only the @RedisBatched
annotation and the RBatch
method parameter differ.
Example
@Handler
void apply(SomethingHappened fact, RBatch batch) {
myMap = batch.getMap( ... ).putAsync( fact.getKey() , fact.getValue() );
}
a full example can be found here