使用包StackExchange.Redis,可以在NuGet中下载到
可以支持多并发请求,保持数据一致性和不重复已经保证代码只再一次请求结束后再执行
public static async Task<bool> TryAcquireLockAsync()
{bool isAcquired = false;while (!isAcquired){isAcquired = await _redisConn.GetDatabase().LockTakeAsync(_lockKey, "my_lock_instance", LockTimeout);if (!isAcquired){// 没有获取到锁,可以在这里等待一段时间再尝试await Task.Delay(100); // 等待100毫秒}}return isAcquired;
}public static async Task ReleaseLockAsync()
{await _redisConn.GetDatabase().LockReleaseAsync(_lockKey, "my_lock_instance");
}
/// <summary>
/// 获取锁
/// </summary>
/// <returns></returns>
public static bool TryAcquireLock()
{bool isAcquired = false;while (!isAcquired){isAcquired = _redisConn.GetDatabase().LockTake(_lockKey, "my_lock_instance", LockTimeout);if (!isAcquired){// 没有获取到锁,可以在这里等待一段时间再尝试Task.Delay(100); // 等待100毫秒}}return isAcquired;
}
/// <summary>
/// 释放锁
/// </summary>
public static void ReleaseLock()
{_redisConn.GetDatabase().LockReleaseAsync(_lockKey, "my_lock_instance");
}
本次代码使用在生成唯一Code的使用:
redis主要代码
//锁主要参数private static readonly object Locker = new object();private static ConnectionMultiplexer _redisConn;private static readonly string LockKey = "redis_lock";private static string _lockKey;private static readonly TimeSpan AcquireTimeout = TimeSpan.FromSeconds(10);private static readonly TimeSpan LockTimeout = TimeSpan.FromSeconds(30);//配置参数public static string RedisIp = AppConfigurtaionServices.Configuration["RedisSetting:Host"];public static string RedisPort = AppConfigurtaionServices.Configuration["RedisSetting:Port"];public static string RedisPwd = AppConfigurtaionServices.Configuration["RedisSetting:PassWord"];private static ConfigurationOptions ConfigurationOptions = ConfigurationOptions.Parse($"{RedisIp}:{RedisPort},allowAdmin=true{(RedisPwd.IsNullOrEmpty() ? "" : $",{RedisPwd}")}");/// <summary>/// 单例获取/// </summary>public static ConnectionMultiplexer RedisConn{get{if (_redisConn == null){InitConfiguration();// 锁定某一代码块,让同一时间只有一个线程访问该代码块lock (Locker){if (_redisConn == null || !_redisConn.IsConnected){_redisConn = ConnectionMultiplexer.Connect(ConfigurationOptions);}}_lockKey = LockKey;}return _redisConn;}}public static void InitConfiguration(){string password = RedisPwd.IsNullOrEmpty() ? "" : $",password ={RedisPwd}";ConfigurationOptions = ConfigurationOptions.Parse($"{RedisIp}:{RedisPort},allowAdmin=true{password}");//}/// <summary>/// 设置定时过期redis key/// </summary>/// <param name="key">键</param>/// <param name="expireTime">过期时间 分钟</param>/// <param name="dbs">redis db 默认db(1)</param>public static void SetRedisExpireKey(string key, int expireTime, int dbs = 1){//将订单和时间存住到redis中,走定时执行任务TimeSpan expiry = TimeSpan.FromSeconds(expireTime * 60);var db = _redisConn.GetDatabase(dbs);db.StringSet($"{key}", "", expiry);}/// <summary>/// 删除定时过期redis key/// </summary>/// <param name="key">键</param>/// <param name="dbs">redis db默认db(1)</param>public static void DeleteRedisExpireKey(string key, int dbs = 1){var db = _redisConn.GetDatabase(dbs);db.KeyDelete($"{key}");}#region Redis方法public static bool Exists(string key){var db = _redisConn.GetDatabase();return db.KeyExists(key);}public static bool Exists(string key, int dbs = 0){var db = _redisConn.GetDatabase(dbs);return db.KeyExists(key);}public static string Get(string key){var db = _redisConn.GetDatabase();return db.StringGet(key);}public static bool Set(string key, string value){var db = _redisConn.GetDatabase();return db.StringSet(key, value);}public static bool SetStr(string key, string value, int dbs = 0){var db = _redisConn.GetDatabase(dbs);return db.StringSet(key, value);}public static string SetStrDelete(string key, int dbs = 0){//将订单和时间存住到redis中,走定时执行任务var db = _redisConn.GetDatabase(dbs);return db.StringGetDelete(key);}public static bool Set(string key, string value, int expireTime){//将订单和时间存住到redis中,走定时执行任务TimeSpan expiry = TimeSpan.FromSeconds(expireTime * 60);var db = _redisConn.GetDatabase();return db.StringSet(key, value, expiry);}public static string SetStrDelete(string key){//将订单和时间存住到redis中,走定时执行任务var db = _redisConn.GetDatabase();return db.StringGetDelete(key);}public static bool RemoveKey(string key){var db = _redisConn.GetDatabase();return db.KeyDelete(key);}public static bool RemoveKey(string key, int dbs = 0){var db = _redisConn.GetDatabase(dbs);return db.KeyDelete(key);}public static bool HashSet(string redisName, string key, string value){var db = _redisConn.GetDatabase();return db.HashSet(redisName, key, value);}public static bool HashSet(string redisName, string key, string value, int dbs = 0){var db = _redisConn.GetDatabase(dbs);return db.HashSet(redisName, key, value);}public static string HashGet(string redisName, string key){var db = _redisConn.GetDatabase();return db.HashGet(redisName, key);}public static string HashGet(string redisName, string key, int dbs = 0){var db = _redisConn.GetDatabase(dbs);return db.HashGet(redisName, key);}public static bool HashRemove(string redisName, string key){var db = _redisConn.GetDatabase();return db.HashDelete(redisName, key);}public static bool HashKeyExists(string redisName, string key){var db = _redisConn.GetDatabase();return db.HashExists(redisName, key);}public static IEnumerable<string> GetPageList(string hashKey,int pageIndex ,int pageSize){var db = _redisConn.GetDatabase();var start=(pageIndex - 1) * pageSize;var end = pageIndex * pageSize-1;var values= db.ListRange(hashKey, start, end);return values.Select(x=>x.ToString());}public static bool HashKeyExists(string redisName, string key, int dbs = 0){var db = _redisConn.GetDatabase(dbs);return db.HashExists(redisName, key);}#endregionpublic static async Task<bool> TryAcquireLockAsync(){bool isAcquired = false;while (!isAcquired){isAcquired = await _redisConn.GetDatabase().LockTakeAsync(_lockKey, "my_lock_instance", LockTimeout);if (!isAcquired){// 没有获取到锁,可以在这里等待一段时间再尝试await Task.Delay(100); // 等待100毫秒}}return isAcquired;}public static async Task ReleaseLockAsync(){await _redisConn.GetDatabase().LockReleaseAsync(_lockKey, "my_lock_instance");}/// <summary>/// 获取锁/// </summary>/// <returns></returns>public static bool TryAcquireLock(){bool isAcquired = false;while (!isAcquired){isAcquired = _redisConn.GetDatabase().LockTake(_lockKey, "my_lock_instance", LockTimeout);if (!isAcquired){// 没有获取到锁,可以在这里等待一段时间再尝试Task.Delay(100); // 等待100毫秒}}return isAcquired;}/// <summary>/// 释放锁/// </summary>public static void ReleaseLock(){_redisConn.GetDatabase().LockReleaseAsync(_lockKey, "my_lock_instance");}
}
调用方式:
/// <summary>/// 获取新的条形码刷新数据,分布式控制/// </summary>/// <param name="orgCode"></param>public static void SetOneTicketBarCode(string orgCode){try{DateTime nowTime = DateTime.Now;string StartTime = nowTime.AddSeconds(-5).ToString("yyyy-MM-dd HH:mm:ss");string EndTime = nowTime.AddSeconds(5).ToString("yyyy-MM-dd HH:mm:ss");var isLockAcquired = RedisHelper.TryAcquireLock();if (isLockAcquired){DataSet set = EntityBase.GetDB().GetDS($"select Code from MemberTicket where orgCode='{orgCode}' and TicketState in (0,1,3) and (BarCode is null or BarCode='') and crDate>='{StartTime}' and crDate<='{EndTime}';" +$"select Code,BarCode from MemberTicket where orgCode='{orgCode}' and TicketState in (0,1,3) and crDate>='{StartTime}' and crDate<='{EndTime}';" +$"select Code,BarCode from MemberTicket where orgCode='{orgCode}' and TicketState in (0,1,3) and (BarCode is null or BarCode='') and crDate>='{StartTime}' and crDate<='{EndTime}';");if (set.Tables[0].Rows.Count > 0){var dt = set.Tables[1];var dthas = set.Tables[2];List<string> list = new List<string>();foreach (DataRow item in dthas.Rows){if (!item.GetStringValue("BarCode").IsNullOrEmpty()){continue;}string BarCode = DateTime.Now.ToString("hmmssfff");BarCode = (Convert.ToInt32(BarCode) + new Random().Next(0, 99999)).ToString();while (list.Contains(BarCode)){BarCode = (Convert.ToInt32(BarCode) + new Random().Next(0, 99999)).ToString();}while (dt.AsEnumerable().Any(x => x.Field<string>("BarCode") == BarCode)){BarCode = (Convert.ToInt32(BarCode) + new Random().Next(0, 99999)).ToString();}list.Add(BarCode);EntityBase entityBase = new EntityBase("MemberTicket");entityBase.DoType = "Update";entityBase.FieldValueList.Add("Code", new FieldValue() { Name = "Code", CurrentValue = item.GetStringValue("Code") });entityBase.FieldValueList.Add("BarCode", new FieldValue() { Name = "BarCode", CurrentValue = BarCode });entityBase.AddOrUpdate();}}}else{}}catch (Exception ex){ErrorLogs.InsertErrorLog(LogType.Error, "生成条形码报错:" + ex.ToString());}finally{RedisHelper.ReleaseLock();}}