Redis实践之高级用法:管道、消息队列、事务、分布式锁

server/2024/10/18 17:29:27/

一、概念与简介:

  1. 管道(Pipeline)的使用

    • 使用 CreateBatch 方法创建一个批处理对象。
    • 将多个操作添加到批处理中,然后执行批处理以提高性能。
  2. 发布-订阅模式(Pub/Sub)的实现

    • 使用 GetSubscriber 方法获取订阅者对象。
    • 使用 PublishAsync 方法发布消息。
    • 使用 SubscribeAsync 方法订阅频道并处理接收到的消息。
  3. 事务(Transaction)的应用

    • 使用 CreateTransaction 方法创建一个事务对象。
    • 将多个操作添加到事务中,然后执行事务以确保原子性。
  4. 分布式锁的实现

    • 使用 LockTakeAsync 方法尝试获取锁。
    • 在获取锁后执行关键操作,并使用 LockReleaseAsync 方法释放锁。

二、高级用法实践

1、首先,在你的 ASP.NET Core 项目中安装 StackExchange.Redis 包:

dotnet add package StackExchange.Redis

2、在Program.cs文件,配置redis服务接口

//注册redis 服务连接接口IConnectionMultiplexer
builder.Services.AddSingleton<IConnectionMultiplexer>(c =>
{return ConnectionMultiplexer.Connect(builder.Configuration.GetConnectionString("Redis")??"localhost:6379");
});

 3、appsetting.json文件,配置redis连接串

"ConnectionStrings": {"Redis": "localhost:6379"
},

 4、新增RedisServices.cs文件,实现高级用法

public class RedisServices
{private readonly IConnectionMultiplexer _redis;public RedisServices(IConnectionMultiplexer redis){_redis = redis;}/// <summary>/// redis 管道用法/// </summary>/// <returns></returns>public async Task UsePipelineAsync(){var db = _redis.GetDatabase(3);var batch = db.CreateBatch();var tasks = new List<Task>();for (int i = 0;i<100;i++){_=batch.StringSetAsync($"key{i}", $"value{i}", TimeSpan.FromMinutes(1));//tasks.Add(batch.StringSetAsync($"key{i}",$"value{i}",TimeSpan.FromMinutes(1)));}batch.Execute();//await Task.WhenAll(tasks);await Console.Out.WriteLineAsync("Pipeline execution completed.");}/// <summary>/// redis 发布订阅用法:发布/// </summary>/// <param name="channel"></param>/// <param name="message"></param>/// <returns></returns>public async Task PublishAsync(RedisChannel channel,string message){           var subscriber = _redis.GetSubscriber();await subscriber.PublishAsync(channel, message);Console.WriteLine($"Message '{message}' published to channel '{channel}'.");}//订阅public async Task SubscriberAsync(RedisChannel channel){var subscriber = _redis.GetSubscriber();await subscriber.SubscribeAsync(channel, (ch,msg) => {Console.WriteLine($"Received message '{msg}' from channel '{ch}'.");});}/// <summary>/// redis 事务用法/// </summary>/// <returns></returns>public async Task UseTransactionAsync(){var  db = _redis.GetDatabase(3);var trans = db.CreateTransaction();_=trans.StringSetAsync("key1", "new_value1");_=trans.StringSetAsync("keyk", "new_valuek");bool committed = await trans.ExecuteAsync();Console.WriteLine($"Transaction committed: {committed}");}/// <summary>/// redis 分布式锁用法/// </summary>/// <param name="lockkey"></param>/// <returns></returns>public async Task UseDistributedLockAsync(string lockkey){var db = _redis.GetDatabase(3);string lockvalue = Guid.NewGuid().ToString();TimeSpan expiry = TimeSpan.FromMinutes(1);bool acquired = await db.LockTakeAsync(lockkey,lockvalue,expiry);if (acquired){try{Console.WriteLine("Lock acquired, performing critical operation...");// Perform critical operation here}finally{await db.LockReleaseAsync(lockkey,lockvalue);Console.WriteLine("Lock released.");}}else{Console.WriteLine("Failed to acquire lock.");}}public async Task<bool> GetRedisLock(){var db = _redis.GetDatabase(3);string lockkey = "_redisLock_";string lockvalue = Guid.NewGuid().ToString();TimeSpan expiry = TimeSpan.FromMinutes(1);return await db.LockTakeAsync(lockkey, lockvalue, expiry);}
}

5、注册RedisServices

 //注册redis高级用法builder.RegisterType<RedisServices>();

6、新建RedisController.cs

[Route("api/[controller]")]
[ApiController]
public class RedisController : ControllerBase
{private readonly Repository.IRepository<Product> _repository;private readonly RedisServices _redisServices;public RedisController(Repository.IRepository<Product> repository,RedisServices redisServices){_repository = repository;_redisServices = redisServices;}//测试redis高级用法[Route("UseRedis")][HttpPost]public async Task<ActionResult> UseRedis(){//管道await _redisServices.UsePipelineAsync();//在 Redis 的发布/订阅(Pub/Sub)模式下,消息是即时传递的,这意味着消息只会发送给当前在线的订阅者。//如果在发布消息时没有任何订阅者,那么这些消息将会丢失。因此,如果你在发布消息之后才开始订阅,之前发布的消息将不会被接收到。RedisChannel channel = new("mychannel",RedisChannel.PatternMode.Literal);await _redisServices.SubscriberAsync(channel);//先订阅await _redisServices.PublishAsync(channel, "hello redis!");//再发布//事务await _redisServices.UseTransactionAsync();//分布式锁await _redisServices.UseDistributedLockAsync("distributeLock");for (int i = 0;i<5000; i++){bool acquired = await _redisServices.GetRedisLock();if (acquired){await Console.Out.WriteLineAsync($"第{i}次请求获取锁成功,并执行成功");}else{Thread.Sleep(1000);}}return Ok();}
}

三、代码详解

1、IConnectionMultiplexer 接口

IConnectionMultiplexer 是 StackExchange.Redis 库中的一个接口,代表了与 Redis 服务器的连接。它是使用 StackExchange.Redis 与 Redis 进行交互的核心组件。

作用

  1. 管理连接IConnectionMultiplexer 管理与 Redis 服务器的所有连接,包括连接池、连接复用等。

  2. 提供数据库操作接口:通过 GetDatabase 方法获取 IDatabase 对象,用于执行各种 Redis 命令。

  3. 发布-订阅功能:通过 GetSubscriber 方法获取 ISubscriber 对象,用于实现发布-订阅模式。

  4. 服务器管理:通过 GetServer 方法获取 IServer 对象,用于执行服务器级别的命令,如清空数据库、查看键空间等。

  5. 配置和监控:可以获取连接的配置信息,并提供一些监控和诊断功能

2. 基于Redis的分布式

        Redis提供了一种高效的分布式锁实现方式,通常使用 SETNX 命令(Set if Not Exists)和 EXPIRE 命令(设置过期时间)来实现。

  • 获取锁:使用 SETNX 命令尝试设置一个键,如果键不存在则设置成功并返回1,否则返回0。然后使用 EXPIRE 命令为该键设置一个过期时间,以防止死锁。
  • 释放锁:删除该键即可释放锁。
3. 数据结构

Redis 支持多种数据结构,每种结构都有其特定的应用场景:

  • 字符串(String):最基本的数据类型,可以存储任何形式的字符串,包括二进制数据。
  • 哈希(Hash):适合存储对象,类似于 Python 的字典。
  • 列表(List):有序集合,支持从两端进行操作,适合实现队列和栈。
  • 集合(Set):无序集合,自动去重,适合做交集、并集、差集运算。
  • 有序集合(Sorted Set):带权重的集合,元素有序排列,适合排行榜等场景。

四、总结

        Redis 作为一个高性能的内存数据结构存储系统,具有许多优点,使其在各种应用场景中广受欢迎。以下是 Redis 的一些主要优点:

1. 高性能

  • 低延迟:由于数据存储在内存中,读写操作非常快速,通常在毫秒级别。

  • 高吞吐量:支持每秒数十万次的读写操作,非常适合高并发场景。

2. 丰富的数据结构

  • 支持字符串、哈希、列表、集合、有序集合、位图(Bitmaps)、HyperLogLog 和地理位置(GEO)等多种数据结构,满足不同的应用需求。

3. 持久化

  • 提供 RDB(快照)和 AOF(追加日志)两种持久化机制,可以根据需要选择合适的方式来保证数据的持久性。

4. 主从复制

  • 支持主从复制,一个主节点可以有多个从节点,从节点可以分担读请求,提高系统的可用性和扩展性。

5. 高可用和自动故障转移

  • 通过 Redis Sentinel 实现高可用性监控和自动故障转移,确保系统在节点故障时仍能正常运行。

  • Redis Cluster 提供了分布式解决方案,支持数据分片和自动故障转移,实现水平扩展。

6. 灵活的发布/订阅机制

  • 支持发布/订阅模式,可以用于实时消息传递、通知系统等场景。

7. 脚本支持

  • 内置 Lua 脚本支持,通过 EVAL 命令执行脚本,实现复杂的原子操作。

8. 缓存功能

  • 提供多种缓存淘汰策略,如 LRU、LFU 等,可以根据需求选择合适的策略,优化内存使用。

9. 管道技术

  • 支持管道技术,一次性发送多个命令,减少网络延迟,提高性能。

10. 易于使用

  • 简单易懂的命令集和丰富的客户端库,支持多种编程语言,方便开发者快速上手。

11. 社区和生态系统

  • 拥有活跃的开源社区和丰富的生态系统,提供了大量的工具和扩展,方便集成和管理。

12. 安全性

  • 支持基于密码的访问控制和 SSL/TLS 加密通信,增强数据传输的安全性。

        这些优点使得 Redis 成为一个强大且灵活的内存数据库,广泛应用于缓存、会话管理、实时分析、消息队列等各种场景。


http://www.ppmy.cn/server/124763.html

相关文章

微信小程序公共样式:设计与实现指南

文章目录 前言一、小程序公共样式的概念和作用什么是公共样式&#xff1f;公共样式的作用 二、公共样式的需求分析三、如何编写小程序公共样式3.1 公共样式的命名规范3.2 公共样式的文件结构3.3 公共样式的内容设计局3.3.1 变量定义3.3.2 字体样式3.3.3 按钮样式3.3.4 间距与布…

Python 异步编程:如何从入门到精通

在现代编程实践中&#xff0c;异步编程已成为提高程序性能和效率的关键技术之一。Python&#xff0c;作为一种动态、解释型的高级编程语言&#xff0c;提供了强大的异步编程能力。本文将带你从异步编程的基础知识入手&#xff0c;逐步深入到实际应用&#xff0c;探索Python异步…

甄选范文“论软件架构建模技术与应用”,软考高级论文,系统架构设计师论文

论文真题 软件架构用来处理软件高层次结构的设计和实施,它以精心选择的形式将若干结构元素进行装配,从而满足系统的主要功能和性能需求。软件架构设计的首要问题是如何表示软件架构,即如何对软件架构建模。根据建模的侧重点不同,可以将软件架构模型分为结构模型、框架模型…

Java项目实战II基于Java+Spring Boot+MySQL的汽车销售网站(文档+源码+数据库)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 在数字化时…

JS对不同浏览器的检测问题

Navigator对象也称浏览器对象&#xff0c;该对象包含了浏览器的整体信息&#xff0c;如浏览器名称&#xff0c;版本号等。Navigator对象由Navigator浏览器率先使用&#xff0c;后来各方浏览器都开始支持Navigator对象&#xff0c;逐步成为一种标准。 一、Navigator对象的属性 …

万博智云CEO王嘉在华为全联接大会:以创新云应用场景,把握增长机遇

一、大会背景 2024年9月19-21日&#xff0c;第九届华为全联接大会将在上海世博展览馆和上海世博中心举办。作为华为的旗舰盛会&#xff0c;本次大会以“共赢行业智能化”为主题邀请了众多思想领袖、商业精英、技术专家、合作伙伴、开发者等业界同仁&#xff0c;从战略、产业、…

【STM32】江科大STM32笔记汇总(已完结)

STM32江科大笔记汇总 STM32学习笔记课程简介(01)STM32简介(02)软件安装(03)新建工程(04)GPIO输出(05)LED闪烁& LED流水灯& 蜂鸣器(06)GPIO输入(07)按键控制LED 光敏传感器控制蜂鸣器(08)OLED调试工具(09)OLED显示屏(10)EXTI外部中断(11)对射式红外传感器计次 旋转编码器…

DrawDB本地Windows环境部署结合内网穿透远程设计数据库

文章目录 前言1. Windows本地部署DrawDB2. 安装Cpolar内网穿透3. 实现公网访问DrawDB4. 固定DrawDB公网地址 前言 我们在开发项目时很多时候都会使用到数据库&#xff0c;所以选择一个好用的数据库设计工具会让工作效率翻倍。在当今数字化时代&#xff0c;数据库管理是许多企业…