1.添加包:StackExchange.Redis

2.在配置文件里面,新建Redis的有关配置信息

Name是别名,可以任意起。Ip是Redis的服务端地址,例如安装本地,就是127.0.0.1,端口号Port默认是6379,密码可以通过Redis安装的根目录下的配置文件进行设置,Timeout是连接的超时时间,Db是使用Redis的DB区,一般Redis的DB区默认是0到15。注意:此处的配置使用的是数组,用于将来进行Redis分布式操作的可拓展。

注:我是本地部署的Redis,所以在本地有服务端和客户端,在初始情况下,Redis还没有密码,需要我们自己去设置,找到Redis的安装文件

进入图中的.conf文件去编辑

把#requirepass的#注释去掉 然后重新设置密码,设置完成后保存

cmd运行该文件夹,启动服务端并且指定配置文件

然后开启服务端,就可以进行本地redis开发调试了

3.Ysq.Core.Entity,然后新建一个实体类,叫RedisConfig,用于读取到配置文件的Redis信息进行赋值使用

4.在Common工具文件夹下,新建 Ysq.Core.Redis类库项目,并新建 RedisManage 类和对应接口 IRedisManage,如下图。然后,在该项目里面,引用共用包项目Ysq.Core.Package,用以使用Redis有关功能。

点击查看代码
public interface IRedisManage
{
/// <summary>
/// 设置一个 键值对
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <param name="ts"></param>
void SetValue(string key, object value, TimeSpan ts);
/// <summary>
/// //获取 Reids 缓存值
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
string GetValue(string key);
/// <summary>
/// 获取序列化值
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="key"></param>
/// <returns></returns>
TEntity Get<TEntity>(string key);
/// <summary>
/// 判断Key是否存在
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
bool Get(string key);
/// <summary>
/// 移除某个Key和值
/// </summary>
/// <param name="key"></param>
void Remove(string key);
/// <summary>
/// 清空Redis
/// </summary>
void Clear();
/// <summary>
/// 异步获取 Reids 缓存值
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
Task<string> GetValueAsync(string key);
/// <summary>
/// 异步获取序列化值
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="key"></param>
/// <returns></returns>
Task<TEntity> GetAsync<TEntity>(string key);
Task SetAsync(string key, object value, TimeSpan cacheTime);
Task<bool> GetAsync(string key);
/// <summary>
/// 异步移除指定的key
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
Task RemoveAsync(string key);
/// <summary>
/// 异步移除模糊查询到的key
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
Task RemoveByKey(string key);
/// <summary>
/// 异步全部清空
/// </summary>
/// <returns></returns>
Task ClearAsync();
}
点击查看代码
public class RedisManage : IRedisManage
{
public volatile ConnectionMultiplexer _redisConnection;
private readonly object _redisConnectionLock = new object();
private readonly ConfigurationOptions _configOptions;
private readonly ILogger<RedisManage> _logger; public RedisManage(ILogger<RedisManage> logger)
{
_logger = logger;
ConfigurationOptions options = ReadRedisSetting();
if (options == null)
{
_logger.LogError("Redis数据库配置有误");
}
this._configOptions = options;
this._redisConnection = ConnectionRedis();
} private ConfigurationOptions ReadRedisSetting()
{
try
{
List<RedisConfigInfo> config = AppHelper.Instance.ReadAppSettings<RedisConfigInfo>(new string[] { "Redis" }); // 读取Redis配置信息
if (config.Any())
{
ConfigurationOptions options = new ConfigurationOptions
{
EndPoints =
{
{
config.FirstOrDefault().Ip,
config.FirstOrDefault().Port
}
},
ClientName = config.FirstOrDefault().Name,
Password = config.FirstOrDefault().Password,
ConnectTimeout = config.FirstOrDefault().Timeout,
DefaultDatabase = config.FirstOrDefault().Db,
};
return options;
}
return null;
}
catch (Exception ex)
{
_logger.LogError($"获取Redis配置信息失败:{ex.Message}");
return null;
} } private ConnectionMultiplexer ConnectionRedis()
{
if (this._redisConnection != null && this._redisConnection.IsConnected)
{
return this._redisConnection; // 已有连接,直接使用
}
lock (_redisConnectionLock)
{
if (this._redisConnection != null)
{
this._redisConnection.Dispose(); // 释放,重连
}
try
{
this._redisConnection = ConnectionMultiplexer.Connect(_configOptions);
}
catch (Exception ex)
{
_logger.LogError($"Redis服务启动失败:{ex.Message}");
}
}
return this._redisConnection;
} public string GetValue(string key)
{
return _redisConnection.GetDatabase().StringGet(key);
} public void SetValue(string key, object value,TimeSpan time)
{
if (value!=null)
{
_redisConnection.GetDatabase().StringSet(key,JsonConvert.SerializeObject(value),time);
}
} public void Clear()
{
foreach (var endPoint in this.ConnectionRedis().GetEndPoints())
{
var server = this.ConnectionRedis().GetServer(endPoint);
foreach (var key in server.Keys())
{
_redisConnection.GetDatabase().KeyDelete(key);
}
}
} public bool Get(string key)
{
return _redisConnection.GetDatabase().KeyExists(key);
} public TEntity Get<TEntity>(string key)
{
var value = _redisConnection.GetDatabase().StringGet(key);
if (value.HasValue)
{
//需要用的反序列化,将Redis存储的Byte[],进行反序列化
return JsonConvert.DeserializeObject<TEntity>(value);
}
else
{
return default(TEntity);
}
} public void Remove(string key)
{
_redisConnection.GetDatabase().KeyDelete(key);
} public bool SetValue(string key, byte[] value)
{
return _redisConnection.GetDatabase().StringSet(key, value, TimeSpan.FromSeconds(120));
} public async Task ClearAsync()
{
foreach (var endPoint in this.ConnectionRedis().GetEndPoints())
{
var server = this.ConnectionRedis().GetServer(endPoint);
foreach (var key in server.Keys())
{
await _redisConnection.GetDatabase().KeyDeleteAsync(key);
}
}
} public async Task<bool> GetAsync(string key)
{
return await _redisConnection.GetDatabase().KeyExistsAsync(key);
} public async Task<string> GetValueAsync(string key)
{
return await _redisConnection.GetDatabase().StringGetAsync(key);
} public async Task<TEntity> GetAsync<TEntity>(string key)
{
var value = await _redisConnection.GetDatabase().StringGetAsync(key);
if (value.HasValue)
{
return JsonConvert.DeserializeObject<TEntity>(value);
}
else
{
return default;
}
} public async Task RemoveAsync(string key)
{
await _redisConnection.GetDatabase().KeyDeleteAsync(key);
} public async Task RemoveByKey(string key)
{
var redisResult = await _redisConnection.GetDatabase().ScriptEvaluateAsync(LuaScript.Prepare(
//模糊查询:
" local res = redis.call('KEYS', @keypattern) " +
" return res "), new { @keypattern = key }); if (!redisResult.IsNull)
{
var keys = (string[])redisResult;
foreach (var k in keys)
_redisConnection.GetDatabase().KeyDelete(k); }
} public async Task SetAsync(string key, object value, TimeSpan cacheTime)
{
if (value != null)
{
await _redisConnection.GetDatabase().StringSetAsync(key, JsonConvert.SerializeObject(value), cacheTime);
}
} public async Task<bool> SetValueAsync(string key, byte[] value)
{
return await _redisConnection.GetDatabase().StringSetAsync(key, value, TimeSpan.FromSeconds(120));
}
}

5.启动项目新增对Ysq.Core.Redis项目的引用,并且注入Redis类库中的接口

6.在控制器中设置一对key/value,然后进行读取并返回

Redis客户端有内容

另外:

Redis分布式锁是一种利用Redis单线程特性以及操作原子性实现分布式系统中锁功能的机制,以下我来详细解释这张图和Redis分布式锁的原理:

分布式锁的基本概念:

●使用 SET key value EX seconds NX 命令:key: 锁的名称。

○value: 锁的值(可以用来区分客户端)。

○EX seconds: 锁的过期时间(秒),保证锁不会无限存在。

○NX: 表示“仅在键不存在时设置”(即防止重复设置锁)。

●原理:当某个客户端成功设置了锁后,其他客户端如果尝试设置同样的锁(同样的 key),会失败,直到锁过期或者被释放。

左侧客户端操作:

1.set lock true ex 60 nx:尝试创建一个名为 lock 的锁,值为 true,过期时间为 60 秒。返回 OK,说明锁成功创建。

2.尝试 set lock true ex 60 nx 再次设置锁,返回 (nil),说明锁已经存在,无法再次创建。

3.删除锁:del lock,返回 (integer) 1,表示成功删除锁。

4.再次尝试创建锁:set lock true ex 60 nx,返回 OK,锁被重新创建。

5.删除锁:del lock,返回 (integer) 1。

右侧客户端操作:

1.set lock true ex 60 nx:尝试设置锁。如果锁不存在,返回 OK,锁被设置。

2.再次设置锁:set lock true ex 60 nx,返回 (nil),说明锁已存在,当前客户端无法设置。

3.删除锁:del lock,返回 (integer) 1,锁被成功删除。

观察:

●当锁存在时,其他客户端的 SET lock ... NX 操作会失败。

●但删除锁是无条件的,任何客户端都可以执行 DEL lock 操作,这种情况下存在并发删除的风险。

Redis分布式锁的主要目的是在分布式系统中,确保同一时刻只有一个客户端对某一关键资源进行操作,避免“同时修改”导致数据不一致的问题。例如:

●限制同一资源的并发访问(如用户订单、库存操作)。

●避免定时任务的多次重复执行。

使用锁的伪代码分析:

以下伪代码演示了Redis分布式锁的使用过程:

点击查看代码
If (exists(lock)) {
return false; // 锁存在,返回失败
} else {
set lock true ex 5 nx; // 设置锁(超时时间为5秒)
// 开始操作关键资源
set key1 100; // 资源操作,比如设置值为100
del lock; // 删除锁
return true; // 返回成功
}

(八).NET6.0添加通用的Redis功能的更多相关文章

  1. C# 9.0 添加和增强的功能【基础篇】

    一.记录(record) C# 9.0 引入了记录类型. 可使用 record 关键字定义一个引用类型,以最简的方式创建不可变类型.这种类型是线程安全的,不需要进行线程同步,非常适合并行计算的数据共享 ...

  2. C# 8.0 添加和增强的功能【基础篇】

    .NET Core 3.x和.NET Standard 2.1支持C# 8.0. 一.Readonly 成员 可将 readonly 修饰符应用于结构的成员,来限制成员为不可修改状态.这比在C# 7. ...

  3. C# 6.0 添加和增强的功能【基础篇】

    C# 6.0 是在 visual studio 2015 中引入的.此版本更多关注了语法的改进,让代码更简洁且更具可读性,使编程更有效率,而不是和前几个版本一样增加主导性的功能. 一.静态导入 我们都 ...

  4. C# 7.0 添加和增强的功能【基础篇】

    C# 7.0 版是与 Visual Studio 2017 一起发布. 虽然该版本继承和发展了C# 6.0,但不包含编译器即服务. 一.out 变量 以前我们使用out变量必须在使用前进行声明,C# ...

  5. 手把手教会 VS2022 设计 Winform 高DPI兼容程序 (net461 net6.0 双出)

    本文主要解决两个问题 C# Winform高DPI字体模糊. 高DPI下(缩放>100%), UI设计器一直提示缩放到100%, 如果不重启到100%,设计的控件会乱飞. 建立测试程序 新建.N ...

  6. Vue2.0的通用组件

    饿了么基于Vue2.0的通用组件开发之路(分享会记录)   Element:一套通用组件库的开发之路 Element 是由饿了么UED设计.饿了么大前端开发的一套基于 Vue 2.0 的桌面端组件库. ...

  7. .net core2.0添加json文件并转化成类注入控制器使用 让js调试更简单—console

    .net core2.0添加json文件并转化成类注入控制器使用 上一篇,我们介绍了如何读取自定义的json文件,数据是读取出来了,只是处理的时候太麻烦,需要一遍一遍写,很枯燥.那么有没有很好的办法呢 ...

  8. .NET微服务系统迁移至.NET6.0的故事

    本次迁移涉及的是公司内部一个业务子系统,该系统是一个多样化的应用,支撑着公司的多个业务方向.目前,该系统由40多个基于.NET的微服务应用构成,使用数千个CPU核心和数TB内存,在数百个Linux容器 ...

  9. WCF学习之旅—WCF4.0中的简化配置功能(十五)

    六 WCF4.0中的简化配置功能 WCF4.0为了简化服务配置,提供了默认的终结点.绑定和服务行为.也就是说,在开发WCF服务程序的时候,即使我们不提供显示的 服务终结点,WCF框架也能为我们的服务提 ...

  10. 解析大型.NET ERP系统 通用附件管理功能

    大型系统具备一个通用的附件管理功能,对于单据中无法清晰表达的字段,用一个附件图片或附件文档表示是最好的方法了.比如物料清单附加一张CAD图纸,销售订单评审功能中附加客户的各种表格,通用附件功能对系统起 ...

随机推荐

  1. Discuz7.2 faq.php页面注入漏洞分析

    由于discuz在全局会对GET数组进行addslashes转义,导致该漏洞的产生. 参数问题存在于faq.php的grouppermission函数中.   具体细节访问:网易博客siberia h ...

  2. 论文发表汇款:SWIFT code跨境汇款 —— 如何向境外账号汇款

    如何向境外账号汇款? 有以下几种方式: 对方开通中国金融产品账号或在中国有代理公司:如对方开通中国的银行卡,微信.支付宝,等等,这样其实就不属于跨境汇款了,外国的一些公司已经开设中国的金融产品和银行账 ...

  3. 2022年3月(202203)小米路由R3G(3G)刷openwrt和padavan的总结

    本篇文章是本人这2天刷小米路由R3G的记录,中间可能有很多错误,欢迎留言指出. 1.千万别断电 2.刷机的时候要多等待 小米路由很多型号有着很强的可玩性,128M以上的ROM,256M以上的内存,R3 ...

  4. SAX,DOM,JAXP,JDOM,DOM4J比较分析

    第一:首先介绍一下SAX,DOM,JAXP,JDOM,DOM4J的基本知识:(注意:至于 JAXP JAXB JAXM JAXR JAX-RPC 分别指什么,查看http://gceclub.sun. ...

  5. HZNUOJ-1503公路乘车--DP

    题目传送门:https://acm.hznu.edu.cn/OJ/problem.php?id=1503 题解:我们发现后一状态由前一状态决定,即后一公里由前面十公里的状态决定,经典 dp,我们直接列 ...

  6. 【ElementPlus】el-form使用技巧:动态切换校验规则的最佳实践

    喵~ 今天分享一篇在 ElementPlus 中使用 el-form 动态切换校验规则 的实用方法. 一.问题概述 作为前端开发人员,在开发项目中,特别是后台管理系统,表单的使用是必不可少的.当业务需 ...

  7. PYENV安装与使用

    1.概述 pyenv 是一个python的版本管理软件,通过他,我们可以 方便的安装python 的版本,切换版本,解决版本不同带来问题. 2.安装pyenv 我们可以通过链接下载pyenv http ...

  8. CentOS 更换国内源

    前言 centos默认为官方yum源,国内使用的下载速度完全随缘,且不稳定,一般都需要更换国内源 过程 了解版本 通过cat /etc/redhat-release 可以获取当前centos的版本 知 ...

  9. nrm安装后无法使用

    前情 在使用node.js的过程中,经常会时不是遇到有些包下载安装慢或者失败,有时可以尝试切换源来解决这类问题 坑 通过npm install nrm -g安装完nrm后运行nrm一直报错 Why? ...

  10. 二进制安装Kubernetes(k8s)v1.32.0

    二进制安装Kubernetes(k8s)v1.32.0 介绍 https://github.com/cby-chen/Kubernetes 开源不易,帮忙点个star,谢谢了 kubernetes(k ...