72 lines
2.3 KiB
C#
72 lines
2.3 KiB
C#
using Hncore.Infrastructure.Extension;
|
||
using System;
|
||
using System.Diagnostics;
|
||
using System.Reflection;
|
||
using System.Runtime.InteropServices;
|
||
|
||
namespace Hncore.Infrastructure.Common
|
||
{
|
||
public class RedisLocker
|
||
{
|
||
private string _key;
|
||
private long _lockTime;
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
/// <param name="key">锁的键</param>
|
||
/// <param name="outTime">锁超时时间 单位毫秒</param>
|
||
public RedisLocker(string key,long outTime)
|
||
{
|
||
_key =$"Lock:{Assembly.GetCallingAssembly().GetFriendName()}:{key}" ;
|
||
_lockTime = outTime;
|
||
}
|
||
public void Exec(Action action)
|
||
{
|
||
if (GetLock())
|
||
{
|
||
action();
|
||
ReleaseLock();
|
||
}
|
||
}
|
||
|
||
protected bool GetLock()
|
||
{
|
||
try
|
||
{
|
||
var currentTime = DateTime.Now.GetUnixTimeStamp();
|
||
if (RedisHelper.SetNx(this._key, currentTime + _lockTime))
|
||
{
|
||
Console.WriteLine("获取到Redis锁了");
|
||
RedisHelper.Expire(_key, TimeSpan.FromMilliseconds(_lockTime)); //设置过期时间
|
||
return true;
|
||
}
|
||
|
||
//防止SetNx成功但是设置过期时间(Expire)失败造成死锁
|
||
var lockValue = Convert.ToInt64(RedisHelper.Get(_key));
|
||
currentTime = DateTime.Now.GetUnixTimeStamp();
|
||
if (lockValue > 0 && currentTime > lockValue)
|
||
{
|
||
var getsetResult = Convert.ToInt64(RedisHelper.GetSet(_key, currentTime));
|
||
if (getsetResult == 0 || getsetResult == lockValue)
|
||
{
|
||
Console.WriteLine("获取到Redis锁了");
|
||
RedisHelper.Expire(_key, TimeSpan.FromMilliseconds(_lockTime));
|
||
return true;
|
||
}
|
||
}
|
||
Console.WriteLine("没有获取到锁");
|
||
return false;
|
||
}
|
||
catch
|
||
{
|
||
ReleaseLock();
|
||
return false;
|
||
}
|
||
}
|
||
|
||
protected bool ReleaseLock()
|
||
{
|
||
return RedisHelper.Del(_key) > 0;
|
||
}
|
||
}
|
||
} |