RedisDistributedLock Implementation in Aspect-Oriented Programming (AOP)
Aspect-Oriented Programming (AOP) lends itself well to distributed resource management tasks such as locking. Below is an implementation of a Redis-based distributed lock using the StackExchange.Redis
library, focusing on resource isolation and concurrency control.
RedisDistributedLock Class
Here is the complete implementation:
using StackExchange.Redis;
using System;
using System.Threading.Tasks;
public class RedisDistributedLock : IDisposable
{
private readonly IDatabase _redisDb;
private readonly string _lockKey;
private readonly string _lockValue;
private bool _acquired;
public RedisDistributedLock(IDatabase redisDb, string resourceKey)
{
_redisDb = redisDb;
_lockKey = $"lock:{resourceKey}";
_lockValue = Guid.NewGuid().ToString(); // random token
}
/// <summary>
/// Attempts to acquire a lock for the specified lock key with a given expiry.
/// </summary>
/// <param name="expiry">Duration for lock expiry.</param>
/// <returns>True if the lock was acquired; otherwise, false.</returns>
public async Task<bool> AcquireAsync(TimeSpan expiry)
{
_acquired = await _redisDb.StringSetAsync(
key: _lockKey,
value: _lockValue,
expiry: expiry,
when: When.NotExists);
return _acquired;
}
/// <summary>
/// Releases the lock if it’s still held by this instance.
/// </summary>
public async Task ReleaseAsync()
{
if (_acquired)
{
// Verify token before deleting.
var currentValue = await _redisDb.StringGetAsync(_lockKey);
if (currentValue == _lockValue)
{
await _redisDb.KeyDeleteAsync(_lockKey);
}
_acquired = false;
}
}
/// <summary>
/// Cleanup method ensuring the lock is freed.
/// </summary>
public void Dispose()
{
ReleaseAsync().GetAwaiter().GetResult();
}
}
Acquiring and Releasing the Lock
Using the RedisDistributedLock
class to acquire and release locks ensures concurrency control in distributed systems.
// Acquire the lock, do some work, then release it
var lockManager = new RedisDistributedLock(redisDatabase, "someResourceKey");
if (await lockManager.AcquireAsync(TimeSpan.FromSeconds(30)))
{
try
{
// Do protected work here...
}
finally
{
await lockManager.ReleaseAsync();
}
}
else
{
// Could not acquire the lock; handle accordingly
}
Key Features and Advantages
- Isolation: Each lock instance operates independently, ensuring safety in concurrent environments.
- Token Verification: Prevents accidental or malicious lock overrides by matching tokens before releasing locks.
- Efficiency: Leverages Redis’s high-speed in-memory capabilities for rapid lock acquisition and release.
Redis-based distributed locking, combined with AOP principles, offers a reliable solution for managing shared resources in distributed systems.