JfYu.Redis
10.0.1
.NET 8.0
This package targets .NET 8.0. The package is compatible with this framework or higher.
.NET Standard 2.0
This package targets .NET Standard 2.0. The package is compatible with this framework or higher.
dotnet add package JfYu.Redis --version 10.0.1
NuGet\Install-Package JfYu.Redis -Version 10.0.1
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="JfYu.Redis" Version="10.0.1" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="JfYu.Redis" Version="10.0.1" />
<PackageReference Include="JfYu.Redis" />
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add JfYu.Redis --version 10.0.1
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: JfYu.Redis, 10.0.1"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package JfYu.Redis@10.0.1
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=JfYu.Redis&version=10.0.1
#tool nuget:?package=JfYu.Redis&version=10.0.1
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
Redis
A high-performance Redis client library for .NET with support for multiple serialization formats, distributed locking, pub/sub messaging, and comprehensive data structure operations.
Features
- ✅ Support for all major Redis data structures (String, Hash, List, Set, Sorted Set)
- ✅ Pub/Sub messaging with pattern matching support
- ✅ Multiple serialization formats (Newtonsoft.Json, MessagePack)
- ✅ Distributed locking with unique token per instance
- ✅ Batch operations for improved performance
- ✅ Connection health monitoring and automatic recovery
- ✅ Key prefix support for multi-tenant scenarios
- ✅ High-performance logging with LoggerMessage source generators
- ✅ Custom value filtering for sensitive data
- ✅ Multi-targeting: .NET Standard 2.0, .NET 8.0, .NET 9.0, and .NET 10.0
Installation
Install-Package JfYu.Redis
Configuration
appsettings.json
{
"Redis": {
"EndPoints": [
{
"Host": "127.0.0.1",
"Port": 6379
}
],
"Password": "YourPassword",
"DbIndex": 0,
"Timeout": 5000,
"Ssl": false,
"Prefix": "MyApp:",
"EnableLogs": true
}
}
Usage
Service Registration
Option 1: Using Configuration
services.AddRedisService(options =>
{
configuration.GetSection("Redis").Bind(options);
options.UsingNewtonsoft(settings =>
{
settings.MaxDepth = 12;
settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
});
});
Option 2: Manual Configuration
services.AddRedisService(options =>
{
options.EndPoints.Add(new RedisEndPoint { Host = "localhost", Port = 6379 });
options.Password = "password";
options.SSL = false;
options.DbIndex = 1;
options.Prefix = "MyTest:";
options.EnableLogs = true;
// Optional: Custom value filter for logging (e.g., hide sensitive data)
options.ValueFilter = value => value.Length > 100 ? value.Substring(0, 100) + "..." : value;
// Choose serialization format
options.UsingMessagePack(settings =>
{
// MessagePack configuration
});
});
Basic Operations
public class MyService
{
private readonly IRedisService _redisService;
public MyService(IRedisService redisService)
{
_redisService = redisService;
}
public async Task BasicOperationsAsync()
{
// String operations
await _redisService.AddAsync("user:1", new User { Name = "John", Age = 30 });
var user = await _redisService.GetAsync<User>("user:1");
// With expiration
await _redisService.AddAsync("session:abc", "data", TimeSpan.FromMinutes(30));
// Check existence
bool exists = await _redisService.ExistsAsync("user:1");
// Remove key
await _redisService.RemoveAsync("user:1");
// Increment/Decrement (Newtonsoft only)
await _redisService.IncrementAsync("counter", 1);
await _redisService.DecrementAsync("counter", 1);
}
}
Batch Operations
// Batch get
var keys = new List<string> { "user:1", "user:2", "user:3" };
var users = await _redisService.GetBatchAsync<User>(keys);
// Batch set
var keyValues = new Dictionary<string, User>
{
{ "user:1", new User { Name = "Alice" } },
{ "user:2", new User { Name = "Bob" } }
};
await _redisService.AddBatchAsync(keyValues, TimeSpan.FromHours(1));
Hash Operations
// Hash set
await _redisService.HashSetAsync("user:1:profile", "name", "John");
await _redisService.HashSetAsync("user:1:profile", "email", "john@example.com");
// Hash get
var name = await _redisService.HashGetAsync<string>("user:1:profile", "name");
// Get all hash entries
var entries = await _redisService.HashGetAllAsync("user:1:profile");
// Check field existence
bool hasEmail = await _redisService.HashExistsAsync("user:1:profile", "email");
// Delete field
await _redisService.HashDeleteAsync("user:1:profile", "email");
List Operations
// Add to list (right/tail)
await _redisService.ListAddAsync("queue", "task1");
await _redisService.ListAddAsync("queue", "task2");
// Add to left (head)
await _redisService.ListAddToLeftAsync("queue", "urgent-task");
// Pop from right
var task = await _redisService.ListPopFromRightAsync<string>("queue");
// Pop from left
var urgentTask = await _redisService.ListPopFromLeftAsync<string>("queue");
// Get list length
var count = await _redisService.ListLengthAsync("queue");
// Get range
var tasks = await _redisService.ListGetRangeAsync("queue", 0, 10);
// Remove items
await _redisService.ListRemoveAsync("queue", "task1", 0); // Remove all occurrences
Set Operations
// Add to set
await _redisService.SetAddAsync("tags", "redis");
await _redisService.SetAddAsync("tags", "cache");
// Add multiple
await _redisService.SetAddAllAsync("tags", new List<string> { "nosql", "database" });
// Check membership
bool isMember = await _redisService.SetContainsAsync("tags", "redis");
// Get all members
var allTags = await _redisService.SetMembersAsync("tags");
// Get random member
var randomTag = await _redisService.SetRandomMemberAsync("tags");
// Remove
await _redisService.SetRemoveAsync("tags", "redis");
// Get set length
var tagCount = await _redisService.SetLengthAsync("tags");
Sorted Set Operations
// Add with score
await _redisService.SortedSetAddAsync("leaderboard", "player1", 100);
await _redisService.SortedSetAddAsync("leaderboard", "player2", 200);
// Add multiple
var scores = new Dictionary<string, double>
{
{ "player3", 150 },
{ "player4", 250 }
};
await _redisService.SortedSetAddAllAsync("leaderboard", scores);
// Increment score
await _redisService.SortedSetIncrementScoreAsync("leaderboard", "player1", 50);
// Get rank (0-based)
var rank = await _redisService.SortedSetRankAsync("leaderboard", "player1");
// Get range by rank
var topPlayers = await _redisService.SortedSetRangeByRankAsync("leaderboard", 0, 9);
// Get range by score
var midRange = await _redisService.SortedSetRangeByScoreAsync("leaderboard", 100, 200);
// Count by score range
var count = await _redisService.SortedSetCountAsync("leaderboard", 100, 200);
// Remove
await _redisService.SortedSetRemoveAsync("leaderboard", new List<string> { "player1" });
Distributed Locking
// Acquire lock
bool locked = await _redisService.LockTakeAsync("resource:lock", TimeSpan.FromSeconds(30));
if (locked)
{
try
{
// Critical section - only one instance can execute this
await DoSomethingCritical();
}
finally
{
// Always release the lock
await _redisService.LockReleaseAsync("resource:lock");
}
}
Pub/Sub Messaging
// Subscribe to a channel
await _redisService.SubscribeAsync<string>("notifications", (channel, message) =>
{
Console.WriteLine($"Received on {channel}: {message}");
});
// Subscribe with pattern matching
await _redisService.SubscribePatternAsync<string>("events:*", (channel, message) =>
{
Console.WriteLine($"Pattern matched {channel}: {message}");
});
// Publish a message
var subscriberCount = await _redisService.PublishAsync("notifications", "Hello World");
Console.WriteLine($"Message delivered to {subscriberCount} subscribers");
// Unsubscribe from specific channel
await _redisService.UnsubscribeAsync("notifications");
// Unsubscribe from pattern
await _redisService.UnsubscribePatternAsync("events:*");
// Unsubscribe from all channels
await _redisService.UnsubscribeAllAsync();
Key Management
// Set expiration
await _redisService.ExpireAsync("temp:data", TimeSpan.FromMinutes(5));
// Get time to live
var ttl = await _redisService.GetTimeToLiveAsync("temp:data");
// Remove expiration (persist)
await _redisService.PersistAsync("temp:data");
// Health check
var pingTime = await _redisService.PingAsync();
if (pingTime > TimeSpan.Zero)
{
Console.WriteLine($"Redis is responding in {pingTime.TotalMilliseconds}ms");
}
Serialization Options
Newtonsoft.Json (Default)
options.UsingNewtonsoft(settings =>
{
settings.MaxDepth = 12;
settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
settings.NullValueHandling = NullValueHandling.Ignore;
});
MessagePack
options.UsingMsgPack(settings =>
{
// MessagePack configuration
settings = settings.WithCompression(MessagePackCompression.Lz4Block);
});
Logging Configuration
Enable Logging
services.AddRedisService(options =>
{
options.EndPoints.Add(new RedisEndPoint { Host = "localhost" });
options.EnableLogs = true; // Enable logging
// Custom value filter to sanitize logged values
options.ValueFilter = value =>
{
// Remove sensitive information
if (value.Contains("password", StringComparison.OrdinalIgnoreCase))
return "***FILTERED***";
// Truncate long values
return value.Length > 200 ? value.Substring(0, 200) + "..." : value;
};
});
Logging Output
When enabled, Redis operations are logged at Trace level:
[Trace] Redis GetAsync - Key: user:123, Value: {"Name":"John","Age":30}
[Trace] Redis SetAddAsync - Key: tags, Value:
[Trace] Redis PublishAsync - Key: notifications, Value: Hello World
Best Practices
- Use Key Prefixes: Organize keys with prefixes for different tenants or modules
- Set Expiration: Always set TTL for temporary data to prevent memory leaks
- Batch Operations: Use batch methods when working with multiple keys
- Connection Pooling: The library uses singleton ConnectionMultiplexer for optimal performance
- Error Handling: Always wrap Redis operations in try-catch blocks
- Distributed Locks: Always release locks in finally blocks to prevent deadlocks
- Pub/Sub: Use pattern matching for flexible message routing across multiple channels
- Logging: Use custom value filters to sanitize sensitive data before logging
Connection Events
The library automatically logs connection events:
- Connection failures
- Connection restoration
- Error messages
Monitor these logs to ensure Redis health.
License
See LICENSE file in the project root.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. 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. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
-
.NETStandard 2.0
- MessagePack (>= 3.1.4)
- Microsoft.Extensions.DependencyInjection (>= 10.0.3)
- Microsoft.Extensions.Options (>= 10.0.3)
- Newtonsoft.Json (>= 13.0.4)
- StackExchange.Redis (>= 2.11.3)
-
net10.0
- MessagePack (>= 3.1.4)
- Microsoft.Extensions.DependencyInjection (>= 10.0.3)
- Microsoft.Extensions.Options (>= 10.0.3)
- Newtonsoft.Json (>= 13.0.4)
- StackExchange.Redis (>= 2.11.3)
-
net8.0
- MessagePack (>= 3.1.4)
- Microsoft.Extensions.DependencyInjection (>= 10.0.3)
- Microsoft.Extensions.Options (>= 10.0.3)
- Newtonsoft.Json (>= 13.0.4)
- StackExchange.Redis (>= 2.11.3)
-
net9.0
- MessagePack (>= 3.1.4)
- Microsoft.Extensions.DependencyInjection (>= 10.0.3)
- Microsoft.Extensions.Options (>= 10.0.3)
- Newtonsoft.Json (>= 13.0.4)
- StackExchange.Redis (>= 2.11.3)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.