Redis入门到进阶之消息队列

一、消息队列

1.1消息队列概述

消息队列(Message Queue),是分布式系统中重要的组件

1.2消息队列使用场景

分布式场景

  • 异步处理
  • 应用解耦
  • 流量削峰

日志场景

  • 优化日志传输,提升系统性能 

及时通信

  • 聊天室 

解决应用解耦,异步消息,流量削锋等问题,实现高性能,高可用,可伸缩

 

1.3消息队列相关概念 

  1. 消息队列:即存储消息的容器,图中的两条直线描绘的管道即消息队列
  2. 消息:消息即需要写入的队列的数据,图中用A1、A2、A3、An表示
  3. 入队出队:消息队列是先进先出的
  4. 生产者:数据的来源
  5. 消费者:数据的去向

 我们常用RabbitMQ和kafka等专业的消息队列中间件完成异步消息队列功能,这些专业的消息队列功能强大特性丰富,但是使用也相对繁琐。对于一些简单的消息队列场景和对消息的可靠性没有极致的追求,可以使用Redis完成消息队列的需求。我们这里讲的是Redis 的消息队列,相了解RabbitMQ的相关知识可以关注我的另一个系列《RabbitMQ入门到进阶系列》

二、Redis消息队列

我们在上一讲中已经了解了redis有5中数据结构,其中list 数据常被用来作为消息队列使用。操作redis消息队列时,使用lpush/rpush操作入队列,使用lpop/rpop操作出队列。lpush/rpop是一组操作,rpush/lpop是一组操作,也就是说左边进队,右边出队,右边进队,左边出队,二者使用上没有区别。这个很容易理解,消息队列就像一个密闭的管道左边进去肯定是右边出来,右边进去肯定是左边出来,中间是没办法掉头的。

 

要在.Net Core 中使用Redis的话最好是使用Service.Stack.Redis进行操作。可以使用Nuget安装(Service.Stack.Redis是收费的,免费的一小时限制6000次请求,后面会教大家如何破解)

 生产者代码

            //1、创建RedisClient
            RedisClient redisClient = new RedisClient("localhost:6379");
            //2、创建生产者,并插入消息
            byte[] bytes = Encoding.UTF8.GetBytes("这是一条消息");
            redisClient.LPush("TestMQ", bytes);//参数解析:1、消息队列名字,消息转换成的byte数组

第一行代码:通过RedisClient对象(需要引入ServiceStack.Redis命名空间)创建Redis 的连接实例,参数为redis服务器和端口

第二行代码:由于在消息队列中都是通过byte数组传输的,所以得先把要入队的消息转换成byte数组

第三行代码:使用LPush方法向队列插入信息,第一个参数为目标队列名字,如果redis中没有这个队列则会创建一个,第二个参数是刚才转换好的消息byte数组

代码执行后在Redis Desktop Manager中看到响应的消息

消费者代码

 

            //1、创建RedisClient
            RedisClient redisClient = new RedisClient("localhost:6379");
            //2、消费消息
            while(true){
            byte[]reads= redisClient.RPop("TestMQ");
            Console.WriteLine($"获取到消息为:{Encoding.UTF8.GetString(reads)}");
            }

因为我们生产者使用的LPush插入数据,所以消费者端需要使用RPop来获取数据 。插入数据时需要转换成byte数组,接受也是通过byte数组接受,后面再转成正确类型。

BRPop/BLPop

细心的同学可能会发现,上面的代码使用while循环获取队列消息,但是如果队列已经没有数据,肯定会陷入死循环。这时我们可以使用BRPop或者BLpop方法替换原先的RPop/LPop。Brpop 命令移出并获取列表的最后一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。

 如果有多个消费者端,将会通过轮询的方式分摊给消费者端。下面结合BRPop进行演示

修改生产者代码变成手动输入消息,以便更好演示

生产者代码

 Console.WriteLine("当前为生产者:请输入消息,输入exit退出!");
string input;
            do
            {
                input = Console.ReadLine();
 
                var msg = Encoding.UTF8.GetBytes(input);
                redisClient.LPush("hello", msg);               
            } while (input.Trim().ToLower() != "exit");

 消费者代码

            while (true) 
            {
                
                RedisClient redisClient = new RedisClient("localhost:6379");
                byte[] reads = redisClient.BRPopValue("hello",60);
                Console.WriteLine($"获取到消息为:{Encoding.UTF8.GetString(reads)}");
            }   

 然后通过命令或exe启动两个消费者

可以看到消息被两个消费者端通过轮询的方式给分摊掉了。

即使使用了BRpop阻塞获取队列,如果队列长时间没有数据,最终还是会抛异常,我们应该捕获异常,并第一时间重试

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值