c# redis 自动延迟 锁的过期时间

 

using StackExchange.Redis;
using System;
using System.Threading.Tasks;
 
public class RedisDistributedLock
{
    private readonly IDatabase _database;
    private readonly string _lockKey;
    private readonly string _uniqueId;
    private readonly TimeSpan _expiry;
 
    public RedisDistributedLock(IDatabase database, string lockKey, string uniqueId, TimeSpan expiry)
    {
        _database = database;
        _lockKey = lockKey;
        _uniqueId = uniqueId;
        _expiry = expiry;
    }
 
    public async Task<bool> TryLockAsync()
    {
        // 尝试获取锁
        bool acquired = await _database.StringSetAsync(_lockKey, _uniqueId, _expiry, When.NotExists);
        if (acquired)
        {
            // 如果获取锁成功,开启后台任务自动延长锁的过期时间
            Task.Run(async () =>
            {
                while (true)
                {
                    await Task.Delay(expiry.TotalMilliseconds / 2); // 延长锁的有效时间的一半
                    if (await _database.StringGetAsync(_lockKey) == _uniqueId)
                    {
                        // 只有当锁仍然是当前持有者的时候才尝试延长
                        await _database.KeyExpireAsync(_lockKey, _expiry);
                    }
                }
            });
        }
        return acquired;
    }
 
    public async Task ReleaseLockAsync()
    {
        // 释放锁的操作,确保只有锁的拥有者才能释放锁
        if (await _database.StringGetAsync(_lockKey) == _uniqueId)
        {
            await _database.KeyDeleteAsync(_lockKey);
        }
    }
}




var redis = ConnectionMultiplexer.Connect("localhost");
var database = redis.GetDatabase();
var lockKey = "my_lock_key";
var uniqueId = Guid.NewGuid().ToString(); // 生成唯一ID,用于识别锁的拥有者
var expiry = TimeSpan.FromSeconds(10); // 锁的过期时间
 
var distributedLock = new RedisDistributedLock(database, lockKey, uniqueId, expiry);
 
if (await distributedLock.TryLockAsync())
{
    try
    {
        // 业务逻辑
    }
    finally
    {
        await distributedLock.ReleaseLockAsync();
    }
}

  

posted on 2024-07-24 23:15  是水饺不是水饺  阅读(9)  评论(0)    收藏  举报

导航