Redis

alt NuGet

Redis is a very popular key-value store, which is known for being very fast. To support Redis, MassTransit uses the StackExchange.Redis library.

Redis only supports event correlation by CorrelationId, it does not support queries. If a saga uses expression-based correlation, a NotImplementedByDesignException will be thrown.
The Redis package also supports the recent fork of Redis called Valkey

Storing a saga in Redis requires an additional interface, ISagaVersion, which has a Version property used for optimistic concurrency. An example saga is shown below.

public class OrderState :
    SagaStateMachineInstance,
    ISagaVersion
{
    public Guid CorrelationId { get; set; }
    public string CurrentState { get; set; }

    public DateTime? OrderDate { get; set; }

    public int Version { get; set; }
}

Configuration

To configure Redis as the saga repository for a saga, use the code shown below using the AddMassTransit container extension. This will configure Redis to connect to the local Redis instance on the default port using Optimistic concurrency. This will also store the ConnectionMultiplexer in the container as a single instance, which will be disposed by the container.

services.AddMassTransit(x =>
{
    const string configurationString = "127.0.0.1";

    x.AddSagaStateMachine<OrderStateMachine, OrderState>()
        .RedisRepository(configurationString);
});

The example below includes all the configuration options, in cases where additional settings are required.

services.AddMassTransit(x =>
{
    const string configurationString = "127.0.0.1";

    x.AddSagaStateMachine<OrderStateMachine, OrderState>()
        .RedisRepository(r =>
        {
            r.DatabaseConfiguration(configurationString);

            // Default is Optimistic
            r.ConcurrencyMode = ConcurrencyMode.Pessimistic;

            // Optional, prefix each saga instance key with the string specified
            // resulting dev:c6cfd285-80b2-4c12-bcd3-56a00d994736
            r.KeyPrefix = "dev";

            // Optional, to customize the lock key
            r.LockSuffix = "-lockage";

            // Optional, the default is 30 seconds
            r.LockTimeout = TimeSpan.FromSeconds(90);
        });;
});

Concurrency

Redis supports both Optimistic (default) and Pessimistic concurrency.

In optimistic mode, the saga instance is not locked before reading, which can ultimately lead to a write conflict if the instance was updated by another message. The Version property is used to compare that the update would not overwrite a previous update. It is recommended that a retry policy is configured (using UseMessageRetry, see the exceptions documentation).

Pessimistic concurrency uses the Redis lock mechanism. During the message processing, the repository will lock the saga instance before reading it, so that any concurrent attempts to lock the same instance will wait until the current message has completed or the lock timeout expires.

Table of Contents