Rystem.Concurrency.Redis
10.0.7
See the version list below for details.
dotnet add package Rystem.Concurrency.Redis --version 10.0.7
NuGet\Install-Package Rystem.Concurrency.Redis -Version 10.0.7
<PackageReference Include="Rystem.Concurrency.Redis" Version="10.0.7" />
<PackageVersion Include="Rystem.Concurrency.Redis" Version="10.0.7" />
<PackageReference Include="Rystem.Concurrency.Redis" />
paket add Rystem.Concurrency.Redis --version 10.0.7
#r "nuget: Rystem.Concurrency.Redis, 10.0.7"
#:package Rystem.Concurrency.Redis@10.0.7
#addin nuget:?package=Rystem.Concurrency.Redis&version=10.0.7
#tool nuget:?package=Rystem.Concurrency.Redis&version=10.0.7
What is Rystem?
Rystem.Concurrency.Redis
Rystem.Concurrency.Redis swaps the default in-memory ILockable from Rystem.Concurrency with a Redis-backed distributed implementation.
Use it when lock and race-condition state must be shared across:
- multiple application instances
- multiple worker processes
- multiple machines or containers
The package keeps the same higher-level APIs from Rystem.Concurrency:
ILockIRaceCoditionILockable
Only the storage backend changes.
Resources
- Complete Documentation: https://rystem.net
- MCP Server for AI: https://rystem.cloud/mcp
- Discord Community: https://discord.gg/tkWvy4WPjt
- Support the Project: https://www.buymeacoffee.com/keyserdsoze
Installation
dotnet add package Rystem.Concurrency.Redis
The current 10.x package targets net10.0 and builds on top of:
StackExchange.RedisRystem.Concurrency
Package Architecture
The package is intentionally small and only adds the Redis-specific pieces.
| Piece | Purpose |
|---|---|
RedisConfiguration |
Holds the Redis connection string |
RedisLock |
Implements ILockable on top of StackExchange.Redis |
AddRedisLock(...) |
Registers ILock plus the Redis lockable |
AddRaceConditionWithRedis(...) |
Registers IRaceCodition plus the Redis lock stack |
AddRedisLockable(...) |
Registers only the Redis ILockable backend |
Conceptually, this package does not replace the concurrency model. It only replaces the backend used by that model.
Table of Contents
- Package Architecture
- Distributed Async Lock
- Distributed Race Condition
- Redis Lockable Only
- Redis Backend Behavior
- Configuration and Registration Notes
- Repository Examples
Distributed Async Lock
Register a distributed ILock with Redis as the backing store:
services.AddRedisLock(options =>
{
options.ConnectionString = configuration["ConnectionString:Redis"]!;
});
Internally this does two things:
- registers the standard
ILockexecutor - registers
RedisLockas the activeILockable
Usage stays identical to the in-memory version from Rystem.Concurrency:
using System.Threading.Concurrent;
LockResponse response = await distributedLock.ExecuteAsync(
async () =>
{
await Task.Delay(15);
await SaveAsync();
},
key: "inventory");
if (response.InException)
throw response.Exceptions!;
The repository test in src/Extensions/Concurrency/Test/Rystem.Concurrency.UnitTest/RedisLockTest.cs uses this registration and starts 100 concurrent lock executions. The final counter still ends at 200, confirming that the distributed backend preserves the same serialized behavior as the in-memory version.
Distributed Race Condition
Register the race-condition guard with Redis:
services.AddRaceConditionWithRedis(options =>
{
options.ConnectionString = configuration["ConnectionString:Redis"]!;
});
This composes:
AddRedisLock(...)AddRaceConditionExecutor()
So the high-level race-condition logic remains the same as the base package, but the lock state is now shared through Redis.
Usage also stays the same:
using System.Threading.Concurrent;
RaceConditionResponse response = await raceCondition.ExecuteAsync(
async () =>
{
await Task.Delay(15);
await RefreshCacheAsync();
},
key: "cache-refresh",
timeWindow: TimeSpan.FromSeconds(30));
if (response.IsExecuted)
{
// this instance won and executed the action
}
There is no separate Redis-specific race-condition test in the repository at the moment, so this section is source-backed rather than test-backed. The important implementation detail is that the Redis package reuses the same RaceConditionExecutor from the base concurrency package.
Redis Lockable Only
If you want Redis as the backend but your own higher-level executor, register only ILockable:
services.AddRedisLockable(options =>
{
options.ConnectionString = configuration["ConnectionString:Redis"]!;
});
Then add your own executor on top:
services.AddLockExecutor<MyCustomLock>();
services.AddRaceConditionExecutor<MyCustomRaceCondition>();
This is the lowest-level integration point exposed by the package.
Redis Backend Behavior
RedisLock implements ILockable like this:
AcquireAsync(key, maxWindow)usesStringSetAsync(..., When.NotExists)IsAcquiredAsync(key)checks whether the key currently existsReleaseAsync(key)uses a Lua script so the key is deleted only when the stored value matches the expected key value
That gives you two useful properties:
- acquisition is atomic across all Redis-connected processes
- release is guarded, so one caller does not accidentally delete another caller's lock entry
The optional maxWindow parameter is important for race-condition scenarios because it becomes the Redis key expiration window.
Configuration and Registration Notes
RedisConfiguration is intentionally minimal:
public sealed class RedisConfiguration
{
public string? ConnectionString { get; set; }
}
The package creates the IConnectionMultiplexer immediately during registration:
services.AddSingleton<IConnectionMultiplexer>(
ConnectionMultiplexer.Connect(redisConfiguration.ConnectionString));
So connection issues can surface as soon as the service collection is being built.
Also note the registration order behavior:
AddRedisLockable(...)usesTryAddSingleton<ILockable, RedisLock>()AddRedisLock(...)andAddRaceConditionWithRedis(...)rely on that registration
That means if another ILockable has already been registered earlier, Redis will not override it automatically. In practice, use the Redis registration path as the primary setup for the service collection instead of mixing it with AddLock() or AddRaceCondition() first.
Repository Examples
The most useful references for this package are:
- Redis lock registration: src/Extensions/Concurrency/Rystem.Concurrency.Redis/Lock/ServiceCollectionExtensions.cs
- Redis race-condition registration: src/Extensions/Concurrency/Rystem.Concurrency.Redis/RaceCondition/ServiceCollectionExtensions.cs
- Redis lockable registration: src/Extensions/Concurrency/Rystem.Concurrency.Redis/Lockable/ServiceCollectionExtensions.cs
- Redis backend implementation: src/Extensions/Concurrency/Rystem.Concurrency.Redis/Lockable/RedisLock.cs
- Redis configuration model: src/Extensions/Concurrency/Rystem.Concurrency.Redis/Configurations/RedisConfiguration.cs
- Distributed lock test: src/Extensions/Concurrency/Test/Rystem.Concurrency.UnitTest/RedisLockTest.cs
This README stays focused because Rystem.Concurrency.Redis is a backend package, not a separate concurrency model. The API shape comes from Rystem.Concurrency; Redis only supplies the shared lock state.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Rystem.Concurrency (>= 10.0.7)
- StackExchange.Redis (>= 2.12.8)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 10.0.8 | 100 | 5/13/2026 |
| 10.0.7 | 114 | 3/26/2026 |
| 10.0.6 | 424,339 | 3/3/2026 |
| 10.0.5 | 116 | 2/22/2026 |
| 10.0.4 | 121 | 2/9/2026 |
| 10.0.3 | 147,884 | 1/28/2026 |
| 10.0.1 | 209,344 | 11/12/2025 |
| 9.1.3 | 233 | 9/2/2025 |
| 9.1.2 | 764,764 | 5/29/2025 |
| 9.1.1 | 97,856 | 5/2/2025 |
| 9.0.32 | 186,688 | 4/15/2025 |
| 9.0.31 | 5,763 | 4/2/2025 |
| 9.0.30 | 88,763 | 3/26/2025 |
| 9.0.29 | 8,984 | 3/18/2025 |
| 9.0.28 | 225 | 3/17/2025 |
| 9.0.27 | 205 | 3/16/2025 |
| 9.0.26 | 199 | 3/13/2025 |
| 9.0.25 | 52,079 | 3/9/2025 |
| 9.0.21 | 692 | 3/6/2025 |
| 9.0.20 | 19,567 | 3/6/2025 |