C# Redis分布式锁

embedded/2024/12/23 17:54:13/

使用包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();}}


http://www.ppmy.cn/embedded/148127.html

相关文章

fastAPI接口的请求与响应——基础

1. 后端接口 1.接口实现 pip install fastapi pip install uvicorn# api.py from pydantic import BaseModel from fastapi import FastAPI import uvicorn import os# 定义请求体模型 class Payload(BaseModel):key1: strkey2: str# 创建一个FastAPI应用程序实例 app Fast…

【数据结构】平衡二叉树

目录 一、概念 二、平衡二叉树的插入 &#xff08;一&#xff09;插入步骤 &#xff08;二&#xff09;旋转 1、左旋 2、右旋 3、左右双旋 4、右左双旋 三、特点 四、整体代码 一、概念 平衡二叉树是在二叉搜索树的改进&#xff0c;二叉搜索树详见&#xff1a;【数据结…

Linux系统加固

Linux系统安全加固 文章目录 Linux系统安全加固密码策略文件、目录安全未授权suid、未授权sgid排查与加固禁止root登录ftp、禁止匿名访问ftp计划任务排查与加固、开机自启排查与加固限定root用户远程ssh登录日志加固 无用账号、用户组和空口令账户排查与加固 禁用或删除无用账号…

【mysql】1205 -Lock wait timeout exceeded; try restarting transaction

问题&#xff1a; mysql8执行SQL提示下面错误&#xff1a; 1205 -Lock wait timeout exceeded; try restarting transaction 1205-超过锁定等待超时&#xff1b;尝试重新启动事务 可能的原因&#xff1a; 事务冲突&#xff1a;多个事务同时尝试修改同一行数据&#xff0c;导…

使用ElasticSearch实现全文检索

文章目录 全文检索任务描述技术难点任务目标实现过程1. java读取Json文件&#xff0c;并导入MySQL数据库中2. 利用Logstah完成MySQL到ES的数据同步3. 开始编写功能接口3.1 全文检索接口3.2 查询详情 4. 前端调用 全文检索 任务描述 在获取到数据之后如何在ES中进行数据建模&a…

设计模式の享元模板代理模式

文章目录 前言一、享元模式二、模板方法模式三、代理模式3.1、静态代理3.2、JDK动态代理3.3、Cglib动态代理3.4、小结 前言 本篇是关于设计模式中享元模式、模板模式、以及代理模式的学习笔记。 一、享元模式 享元模式是一种结构型设计模式&#xff0c;目的是为了相似对象的复用…

druid与pgsql结合踩坑记

最近项目里面突然出现一个怪问题&#xff0c;数据库是pgsql&#xff0c;jdbc连接池是alibaba开源的druid&#xff0c;idea里面直接启动没问题&#xff0c;打完包放在centos上和windows上cmd窗口都能直接用java -jar命令启动&#xff0c;但是放到国产信创系统上就是报错&#xf…

STM32F407 | Embedded IDE01 - vscode搭建Embedded IDE开发环境(支持JLINK、STLINK、DAPLINK)

导言 Embedded IDE官网:https://em-ide.com/docs/intro 我猜肯定有部分人使用SI Keil开发STM32项目&#xff0c;也有vscode Keil开发STM32程序。SI或vscode编写代码&#xff0c;然后切换Keil编译、下载、调试程序。有一段时间&#xff0c;我也是这么干的。但是&#xff0c;程…