中间件redis的使用

简介: 【9月更文挑战第28天】Redis 是一个开源的、基于内存的数据结构存储系统,可用作数据库、缓存和消息中间件。它支持多种数据结构,如字符串、哈希、列表、集合和有序集合等,使其在各种应用场景中表现出色。Redis 作为缓存中间件能显著提高数据访问速度,其缓存过期策略有助于管理数据生命周期。在 .NET 应用程序中使用 Redis 缓存,可通过安装 `StackExchange.Redis` 库并连接到 Redis 服务器来实现数据的读写操作。此外,Redis 作为消息中间件,基于生产者-消费者模型实现消息队列,确保消息的可靠性和顺序性。

一、Redis 简介


Redis(Remote Dictionary Server)是一个开源的、基于内存的数据结构存储系统,它可以用作数据库、缓存和消息中间件。Redis 支持多种数据结构,如字符串、哈希、列表、集合、有序集合等,这使得它在各种应用场景中都非常灵活。


二、Redis 作为缓存中间件的使用


(一)缓存的基本原理


  1. 数据存储与读取
  • 当应用程序需要频繁访问某些数据时,将这些数据存储在 Redis 缓存中。例如,在一个电商网站中,商品信息(如价格、库存等)是经常被用户查询的数据。在首次查询商品信息时,从数据库中获取数据,同时将其存储到 Redis 缓存中,下次查询相同商品信息时,就可以直接从 Redis 缓存中获取,大大提高了数据访问速度。
  • 缓存的读取速度比传统数据库快很多,因为 Redis 是基于内存的存储系统。内存的读写速度比磁盘快几个数量级,所以能够快速响应应用程序的数据请求。
  1. 缓存过期策略
  • Redis 提供了多种缓存过期策略来管理缓存数据的生命周期。可以为每个缓存键设置一个过期时间(TTL - Time To Live),当缓存数据超过过期时间后,Redis 会自动删除该数据。
  • 例如,对于一些实时性较强的数据,如股票价格信息,可以设置较短的过期时间,如几分钟,以确保数据的及时性;而对于一些相对稳定的数据,如商品分类信息,可以设置较长的过期时间,如一天或更长。


(二)在.NET 应用程序中使用 Redis 缓存


  1. 安装 Redis 客户端库
  • 在.NET 应用程序中使用 Redis,首先需要安装 Redis 客户端库。例如,StackExchange.Redis是一个流行的.NET Redis 客户端库。可以通过 NuGet 包管理器安装它。
  • 在 Visual Studio 中,打开 NuGet 包管理器控制台,运行命令Install - Package StackExchange.Redis来安装该库。
  1. 连接到 Redis 服务器
  • 安装好客户端库后,可以在应用程序中创建一个 Redis 连接。例如:


using StackExchange.Redis;
   class Program
   {
       static void Main()
       {
           var redis = ConnectionMultiplexer.Connect("localhost");
           IDatabase db = redis.GetDatabase();
           // 在这里可以使用db进行数据操作
           redis.Close();
       }
   }


  • 在上述代码中,ConnectionMultiplexer.Connect方法用于连接到本地的 Redis 服务器(这里假设 Redis 服务器运行在本地,地址为localhost)。GetDatabase方法获取一个用于数据操作的IDatabase对象。最后,记得关闭连接(redis.Close),不过在实际应用中,连接复用器通常是单例模式,不需要频繁地打开和关闭连接。


  1. 缓存数据的读写操作
  • 写入缓存数据
  • 假设要缓存一个用户对象的信息,首先将用户对象序列化为 JSON 字符串(可以使用Newtonsoft.Json等库),然后将其存储到 Redis 缓存中。


using Newtonsoft.Json;
     using StackExchange.Redis;
     class Program
     {
         static void Main()
         {
             var redis = ConnectionMultiplexer.Connect("localhost");
             IDatabase db = redis.GetDatabase();
             var user = new User { Name = "John", Age = 30 };
             string userJson = JsonConvert.SerializeObject(user);
             db.StringSet("user:1", userJson, TimeSpan.FromMinutes(30));
             redis.Close();
         }
     }
     class User
     {
         public string Name { get; set; }
         public int Age { get; set; }
     }


  • 在上述代码中,StringSet方法用于将用户信息以 JSON 字符串的形式存储到 Redis 缓存中,键为user:1,过期时间设置为 30 分钟。
  • 读取缓存数据
  • 当需要读取用户信息时,从 Redis 缓存中获取数据并反序列化。


using Newtonsoft.Json;
     using StackExchange.Redis;
     class Program
     {
         static void Main()
         {
             var redis = ConnectionMultiplexer.Connect("localhost");
             IDatabase db = redis.GetDatabase();
             string userJson = db.StringGet("user:1");
             if (!string.IsNullOrEmpty(userJson))
             {
                 var user = JsonConvert.DeserializeObject<User>(userJson);
                 Console.WriteLine($"Name: {user.Name}, Age: {user.Age}");
             }
             else
             {
                 // 如果缓存中没有数据,可以从数据库中获取并缓存
                 Console.WriteLine("Data not found in cache.");
             }
             redis.Close();
         }
     }


  • 首先使用StringGet方法获取缓存中的数据,如果数据存在,则将其反序列化并使用;如果数据不存在,可以考虑从数据库中获取数据,然后再缓存起来。


三、Redis 作为消息中间件的使用


(一)消息队列的基本概念


  1. 生产者 - 消费者模型
  • Redis 可以实现简单的消息队列,基于生产者 - 消费者模型。生产者将消息发送到 Redis 中的队列(如使用 Redis 的列表数据结构实现队列),消费者从队列中获取消息并进行处理。
  • 例如,在一个订单处理系统中,当有新订单生成时,订单生成模块作为生产者将订单信息发送到 Redis 消息队列。订单处理模块作为消费者从队列中获取订单信息并进行处理,如库存管理、发货安排等。
  1. 消息的可靠性和顺序性
  • 在消息队列中,消息的可靠性是很重要的。Redis 提供了一些机制来确保消息不会丢失。例如,使用 Redis 的持久化功能(RDB 和 AOF)可以将队列中的消息存储到磁盘上,即使 Redis 服务器重启,消息也不会丢失。
  • 对于消息的顺序性,在简单的队列场景下,按照先进先出(FIFO)的原则,先进入队列的消息先被处理。但在一些复杂的场景下,可能需要额外的机制来保证消息的顺序,如使用消息的时间戳或优先级队列等。


(二)在.NET 应用程序中使用 Redis 消息队列


  1. 发送消息(生产者)
  • 同样使用StackExchange.Redis库,假设要发送一个订单消息到队列中。


using StackExchange.Redis;
   class Program
   {
       static void Main()
       {
           var redis = ConnectionMultiplexer.Connect("localhost");
           IDatabase db = redis.GetDatabase();
           var orderMessage = new OrderMessage { OrderId = 1, ProductName = "Book" };
           string messageJson = JsonConvert.SerializeObject(orderMessage);
           db.ListRightPush("order_queue", messageJson);
           redis.Close();
       }
   }
   class OrderMessage
   {
       public int OrderId { get; set; }
       public string ProductName { get; set; }
   }


  • 在上述代码中,ListRightPush方法将订单消息(以 JSON 字符串形式)发送到名为order_queue的 Redis 队列的右侧(遵循队列的插入规则,新消息添加到队列尾部)。


  1. 接收和处理消息(消费者)
  • 消费者可以通过循环从队列中获取消息并处理。


using Newtonsoft.Json;
   using StackExchange.Redis;
   class Program
   {
       static void Main()
       {
           var redis = ConnectionMultiplexer.Connect("localhost");
           IDatabase db = redis.GetDatabase();
           while (true)
           {
               string messageJson = db.ListLeftPop("order_queue");
               if (!string.IsNullOrEmpty(messageJson))
               {
                   var orderMessage = JsonConvert.DeserializeObject<OrderMessage>(messageJson);
                   Console.WriteLine($"Processing order {orderMessage.OrderId} for {orderMessage.ProductName}");
               }
               else
               {
                   // 队列为空,等待一段时间后再检查
                   System.Threading.Thread.Sleep(1000);
               }
           }
       }
   }


  • 这里使用ListLeftPop方法从队列的左侧(头部)获取消息。如果消息存在,则将其反序列化并处理;如果队列为空,则等待 1 秒钟后再次检查队列。


四、Redis 的其他数据结构在中间件场景中的应用


  1. 哈希(Hash)数据结构
  • 哈希数据结构在存储对象数据时非常有用。例如,在缓存用户信息时,除了使用字符串存储整个用户对象的 JSON 表示,还可以使用哈希结构。每个用户的属性可以作为哈希的一个字段,键可以是用户 ID。


using StackExchange.Redis;
   class Program
   {
       static void Main()
       {
           var redis = ConnectionMultiplexer.Connect("localhost");
           IDatabase db = redis.GetDatabase();
           var user = new User { Name = "John", Age = 30 };
           db.HashSet("user:1", new HashEntry[]
           {
               new HashEntry("name", user.Name),
               new HashEntry("age", user.Age)
           });
           string name = db.HashGet("user:1", "name");
           int age = (int)db.HashGet("user:1", "age");
           redis.Close();
       }
   }


  • 这种方式在更新和查询单个用户属性时更加高效,因为不需要对整个用户对象进行序列化和反序列化。


  1. 集合(Set)和有序集合(Sorted Set)数据结构
  • 集合数据结构:可以用于存储一些不重复的元素,如用户的关注列表。在社交应用中,当一个用户关注其他用户时,可以将被关注用户的 ID 添加到一个集合中。
  • 有序集合数据结构:可以用于实现排行榜等功能。例如,在一个游戏应用中,玩家的分数可以存储在有序集合中,根据分数进行排序,方便获取排行榜信息。


using StackExchange.Redis;
   class Program
   {
       static void Main()
       {
           var redis = ConnectionMultiplexer.Connect("localhost");
           IDatabase db = redis.GetDatabase();
           // 使用集合存储用户关注列表
           db.SetAdd("user:1:followers", "user2", "user3");
           long count = db.SetLength("user:1:followers");
           // 使用有序集合存储游戏排行榜
           db.SortedSetAdd("game_rank", "player1", 100);
           db.SortedSetAdd("game_rank", "player2", 200);
           double score = db.SortedSetScore("game_rank", "player1");
           redis.Close();
       }
   }
相关文章
|
18天前
|
缓存 NoSQL 中间件
redis高并发缓存中间件总结!
本文档详细介绍了高并发缓存中间件Redis的原理、高级操作及其在电商架构中的应用。通过阿里云的角度,分析了Redis与架构的关系,并展示了无Redis和使用Redis缓存的架构图。文档还涵盖了Redis的基本特性、应用场景、安装部署步骤、配置文件详解、启动和关闭方法、systemctl管理脚本的生成以及日志警告处理等内容。适合初学者和有一定经验的技术人员参考学习。
111 7
|
4月前
|
存储 监控 NoSQL
中间件Redis性能瓶颈
【7月更文挑战第13天】
108 11
|
4月前
|
存储 消息中间件 NoSQL
中间件键值存储模型Redis
【7月更文挑战第11天】
52 3
|
4月前
|
消息中间件 NoSQL Kafka
消息中间件(RocketMQ、RabbitMQ、ActiveMQ、Redis、kafka、ZeroMQ)以及之间的区别
消息中间件(RocketMQ、RabbitMQ、ActiveMQ、Redis、kafka、ZeroMQ)以及之间的区别
|
6月前
|
存储 缓存 NoSQL
Redis__中间件
Redis__中间件
|
消息中间件 NoSQL 关系型数据库
【Kubernetes部署Shardingsphere、Mycat、Mysql、Redis、中间件Rocketmq、Rabbitmq、Nacos】
【Kubernetes部署Shardingsphere、Mycat、Mysql、Redis、中间件Rocketmq、Rabbitmq、Nacos】
249 0
|
6月前
|
缓存 NoSQL 关系型数据库
【中间件】Redis与MySQL双写一致性如何保证?--缓存和数据库在双写场景下一致性是如何保证的
【中间件】Redis与MySQL双写一致性如何保证?--缓存和数据库在双写场景下一致性是如何保证的
339 0
【中间件】Redis与MySQL双写一致性如何保证?--缓存和数据库在双写场景下一致性是如何保证的
|
6月前
|
存储 NoSQL 中间件
中间件Redis的学习记录
中间件Redis的学习记录
|
6月前
|
消息中间件 缓存 NoSQL
[中间件] 秒杀系统秒杀率提高300%?教你如何利用redis和rabbitmq 优化应用!
[中间件] 秒杀系统秒杀率提高300%?教你如何利用redis和rabbitmq 优化应用!
262 0
阿里Java高级岗中间件二面:GC+IO+JVM+多线程+Redis+数据库+源码
虽然“钱多、事少、离家近”的工作可能离技术人比较远,但是找到一份合适的工作,其实并不像想象中那么难。但是,有些技术人确实是认真努力工作,但在面试时表现出的能力水平却不足以通过面试,或拿到高薪,其实不外乎以下 2 个原因:
下一篇
无影云桌面