下面是Redis分布式锁常用的概念说明:设置、获取、过期时间、删除。
1、 Setnx
2、Getset
3、Expire
4、Del
锁的分类说明:
相对方 | 相对方 |
---|---|
悲观锁 | 乐观锁 |
公平锁 | 非公平锁 |
独享锁 | 共享锁 |
线程锁 | 进程锁 |
以下以.NET 7控制台为实例测试
using StackExchange.Redis;
namespace Redis
{
public class RedisHelper
{
#region Fileds
private static string? _redisConnection= "127.0.0.1:6379,defaultDatabase=1";
private static int _db = 0;
private static ConnectionMultiplexer? connection;
#endregion
#region Constructors
public RedisHelper()
{
}
public static ConnectionMultiplexer CacheConnection
{
get
{
try
{
if (connection == null || !connection.IsConnected)
{
connection = new Lazy<ConnectionMultiplexer>(() => ConnectionMultiplexer.Connect(_redisConnection!)).Value;
}
}
catch (Exception ex)
{
return null;
}
return connection;
}
}
#endregion
#region Methons
///
/// 缓存当前数据库
///
public static IDatabase CacheRedis => CacheConnection.GetDatabase(_db);
///
/// 新增单条值
///
///
///
public static bool StringSet(string key, string values)
{
if (string.IsNullOrEmpty(key) && string.IsNullOrEmpty(values))
throw new AggregateException("values or is null");
return CacheRedis.StringSet(key, values);
}
///
/// 查询单个key值
///
///
///
public static RedisValue GetStringKey(string key)
{
return CacheRedis.StringGet(key);
}
///
/// 判断key是否存储
///
/// redis key
///
public bool KeyExists(string key)
{
return CacheRedis.KeyExists(key);
}
///
/// 删除单个key
///
/// redis key
/// 是否删除成功
public bool KeyDelete(string key)
{
return CacheRedis.KeyDelete(key);
}
///
/// redis加锁
///
/// 需要加锁的锁名
/// 需要加锁的值
/// 该锁自动到期时间,如果没其他要求可设置为最大时常,该方式一定要手动解锁
///
#region 分布式锁
public static bool LockByRedis(string key, string values)
{
try
{
//expireTimeSeconds = expireTimeSeconds > 20 ? 10 : expireTimeSeconds;
//var data = TimeSpan.FromSeconds(expireTimeSeconds);
//var token = Environment.MachineName;
//bool lockflag = CacheRedis.LockTake(key, Thread.CurrentThread.ManagedThreadId, TimeSpan.FromSeconds(expireTimeSeconds));
bool lockflag = CacheRedis.LockTake(key, values, TimeSpan.MaxValue);
if (!lockflag)
{
return false;
}
return true;
}
catch (Exception ex)
{
throw new Exception($"Redis加锁异常:原因{ex.Message}");
}
}
///
/// 解锁
///
/// 需要解锁的锁名
/// 需要解锁的值
///
///
public static bool UnLockByRedis(string key, string valuse)
{
try
{
// Thread.CurrentThread.ManagedThreadId
//Environment.MachineName
return CacheRedis.LockRelease(key, valuse);
}
catch (Exception ex)
{
throw new Exception($"Redis加锁异常:原因{ex.Message}");
}
}
#endregion
#endregion
}
}
using Redis;
int count=11;
Console.WriteLine($"进入秒杀时刻,进入时间{DateTime.Now}");
Parallel.For(0, 1000, i =>
{
//锁键-值
var lockKey = "lockKey";
var lockValue = Guid.NewGuid().ToString("N");
//加锁
bool result = RedisHelper.LockByRedis(lockKey, lockValue);
if (!result)
{
Console.WriteLine("没有抢到锁,这次请求停止");
return;
}
string data = RedisHelper.GetStringKey("Sum").ToString();
int sum = int.Parse(string.IsNullOrEmpty(data) ? "0" : data);
if (sum <= 0)
{
RedisHelper.StringSet("Sum", count.ToString());
}
else
{
if (sum <=count)
{
count--;
Console.WriteLine("商品还剩:" + sum.ToString());
RedisHelper.StringSet("Sum", count.ToString());
}
}
//释放锁
var unlock = RedisHelper.UnLockByRedis(lockKey, lockValue);
});
Console.WriteLine($"结束秒杀时刻,结束时间{DateTime.Now}");