Using Redis¶
Hangfire with Redis job storage implementation processes jobs much faster than with SQL Server storage. On my development machine I observed more than 4x throughput improvement with empty jobs (method that does not do anything). Hangfire.Pro.Redis
leverages the BRPOPLPUSH
command to fetch jobs, so the job processing latency is kept to minimum.
Redis ≥ 2.6.12 is required. Please, see the downloads page to obtain latest version of Redis. If you unfamiliar with this great storage, please see its documentation. Binaries for Windows are available through NuGet (32-bit, 64-bit) and Chocolatey galleries (64-bit package only).
Limitations¶
Multiple Redis endpoints are only supported in Redis Cluster configuration starting from Hangfire.Pro.Redis 2.1.0. You can’t use multiple detached masters or Redis Sentinel configurations.
Redis Configuration¶
Please read the official Redis documentation to learn how to configure it, especially Redis Persistence and Redis Administration sections to get started with the fundamentals. The following options should be configured to run your background jobs smoothly.
Ensure the following options are configured
These values are default for on-premise Redis installations, but other environments may have different defaults, for example Azure Redis Cache and AWS ElastiCache use non-compatible settings by default.
# Hangfire neither expect that non-expired keys are deleted,
# nor expiring keys are evicted before the expiration time.
maxmemory-policy noeviction
If you are planning to use the Redis ACL feature, below you can find a minimal supported set of rules you can specify to use Redis as a job storage. They restrict keyspace for regular and pub/sub commands to the default prefix used by Hangfire (hangfire:
) and declare a minimal set of Redis commands used by Hangfire.Pro.Redis.
resetkeys ~hangfire:* resetchannels &hangfire:* nocommands +info +ping +echo +select +cluster +time +@read +@write +@set +@sortedset +@list +@hash +@string +@pubsub +@transaction +@scripting
Installation¶
Ensure that you have configured the private Hangfire Pro NuGet feed as written here, and use your favorite NuGet client to install the Hangfire.Pro.Redis
package:
PM> Install-Package Hangfire.Pro.Redis
If your project targets .NET Core, just add a dependency in your *.csproj
file:
<ItemGroup>
<PackageReference Include="Hangfire.Pro.Redis" Version="3.*" />
</ItemGroup>
Configuration¶
After installing the package, a couple of the UseRedisStorage
extension method overloads will be available for the IGlobalConfiguration
interface. They allow you to configure Redis job storage, using both configuration string and Hangfire-specific options.
Connection string¶
The basic one is the following, will connect to the Redis on localhost using the default port, database and options:
GlobalConfiguration.Configuration.UseRedisStorage();
For ASP.NET Core projects, call the UseRedisStorage
method from the AddHangfire
method delegate:
services.AddHangfire(configuration => configuration.UseRedisStorage());
You can customize the connection string using the StackExchange.Redis’ configuration string format. Please read their documentation for details. The values for the following options have their own defaults in Hangfire, but can be overridden in the connection string:
Option |
Default |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
GlobalConfiguration.Configuration
.UseRedisStorage("contoso5.redis.cache.windows.net,abortConnect=false,ssl=true,password=...");
Redis Cluster support¶
You can use a single endpoint to connect to a Redis cluster, Hangfire will detect other instances automatically by querying the node configuration. However, it’s better to pass multiple endpoints in order to mitigate connectivity issues, when some of endpoints aren’t available, e.g. during the failover process.
Since Hangfire requires transactions, and Redis doesn’t support ones that span multiple hash slots, you also need to configure the prefix to assign it to the same hash tag:
GlobalConfiguration.Configuration.UseRedisStorage(
"localhost:6379,localhost:6380,localhost:6381",
new RedisStorageOptions { Prefix = "{hangfire-1}:" });
This will bind all the keys to a single Redis instance. To be able to fully utilize your Redis cluster, consider using multiple JobStorage
instances and leveraging some load-balancing technique (round-robin is enough for the most cases). To do so, pick different hash tags for different storages and ensure they are using hash slots that live on different masters by using commands CLUSTER NODES
and CLUSTER KEYSLOT
.
Passing options¶
You can also pass the Hangfire-specific options for Redis storage by using the RedisStorageOptions
class instances:
var options = new RedisStorageOptions
{
Prefix = "hangfire:app1:"
};
GlobalConfiguration.Configuration.UseRedisStorage("localhost", options);
The following options are available for configuration:
Option |
Default |
Description |
---|---|---|
Prefix |
|
Prefix for all Redis keys related to Hangfire. |
Database |
|
Redis database number to be used by Hangfire. When null, then the defaultDatabase option from the configuration string is used. |
MaxSucceededListLength |
|
Maximum visible background jobs in the succeed list to prevent it from growing indefinitely. |
MaxDeletedListLength |
|
Maximum visible background jobs in the deleted list to prevent it from growing indefinitely. |
InvisibilityTimeout |
|
Obsolete since 2.4.0 Time interval, within which background job is considered to be still successfully processed by a worker. When a timeout is elapsed, another worker will be able to pick the same background job. |
SubscriptionIntegrityTimeout |
|
Obsolete since 2.1.3 Timeout for subscription-based fetch. The value should be high enough (hours) to decrease the stress on a database. This is an additional layer to provide integrity, because otherwise subscriptions can be active for weeks, and bad things may happen during this time. |
Using key prefixes¶
If you are using a shared Redis server for multiple environments, you can specify unique prefix for each environment:
var options = new RedisStorageOptions
{
Prefix = "hangfire:"; // default value
};
GlobalConfiguration.Configuration.UseRedisStorage("localhost", 0, options);