首页 > 其他分享 >9.【RabbitMQ实战】- RabbitMQ其他知识点

9.【RabbitMQ实战】- RabbitMQ其他知识点

时间:2023-04-12 22:46:18浏览次数:43  
标签:实战 知识点 false 队列 RabbitMQ var using hello channel

幂等性

MQ消费者的幂等性的解决一般使用全局ID或者写个唯一标识比如时间戳或者UUID或者订单消费者消费MQ中的消息也可利用MQ的该id来判断,或者可按自己的规则生成一个全局唯一id,每次消费消息时用该id先判断该消息是否已消费过
在海量订单生成的业务高峰期,生产端有可能就会重复发生了消息,这时候消费端就要实现幂等性,这就意味着我们的消息永远不会被消费多次,即使我们收到了一样的消息。业界主流的幂等性有两种操作:a.唯一ID+指纹码机制,利用数据库主键去重, b.利用redis的原子性去实现

场景 解决思路 描述
消费端的幂等性保障 唯一ID+指纹码机制 指纹码:我们的一些规则或者时间戳加别的服务给到的唯一信息码,它并不一定是我们系统生成的,基本都是由我们的业务规则拼接而来,但是一定要保证唯一性,然后就利用查询语句进行判断这个id是否存在数据库中,优势就是实现简单就一个拼接,然后查询判断是否重复;劣势就是在高并发时,如果是单个数据库就会有写入性能瓶颈当然也可以采用分库分表提升性能,但也不是我们最推荐的方式
Redis原子性 利用redis执行setnx命令,天然具有幂等性。从而实现不重复消费

优先级队列

场景

  • 优先处理大客户订单(不同企业规模(500人,200人,100人)在京东下单购买办公用品,优先给人多的企业发货)

注意:设置队列的最大优先级最大可设置0~255 官网推荐设置0~9 如果设置太高会比较占用cup和内存

image.png

生产者代码

image.png

using RabbitMQ.Client;

using System.Reflection;
using System.Text;
using System.Threading.Channels;

namespace _01.Rabbitmq.Producer
{
    public class Program
    {
        
        private static string queueName = "hello";
        static void Main(string[] args)
        {
            // 创建一个连接工厂
            ConnectionFactory factory = new ConnectionFactory
            {
                HostName = "localhost",
                UserName = "guest",
                Password = "guest",
            };

            using var connection = factory.CreateConnection();
            using var channel = connection.CreateModel();
            /*
                *生成一个队列
                *1.队列名称
                *2.队列里面的消息是否持久化默认消息存储在内存中
                *3.该队列是否只供一个消费者进行消费是否进行共享true可以多个消费者消费
                *4.是否自动删除最后一个消费者端开连接以后该队列是否自动删除true自动删除*
                *5.其他参数
             */

            var arguments = new Dictionary<string, object>();
            arguments.Add("x-max-priority", 9);
            channel.QueueDeclare("hello", true, false, false, arguments);//创建一个名称为hello的消息队列
            //channel.QueueDeclare("hello", false, false, false, null);//创建一个名称为hello的消息队列
            for (int i = 0; i < 20; i++)
            {
                string message = i + "Hello World"; //控制台传递的消息内容
                var body = Encoding.UTF8.GetBytes(message);

                /*
                * 发送一个消息
                * 1.发送到那个交换机
                * 2.路由的 key 是哪个
                * 3.其他的参数信息
                * 4.发送消息的消息体
                */

                if (i == 5)
                {
                    var basicProperties = channel.CreateBasicProperties();
                    basicProperties.Priority = 5;
                    channel.BasicPublish(exchange: "", "hello", basicProperties, body); //开始传递
                }
                else
                {
                    channel.BasicPublish(exchange:"", "hello", null, body); //开始传递
                }

                Console.WriteLine("已发送: {0}", message);
            }     
            Console.ReadKey();
        }
    }

}

消费者者代码

image.png


using RabbitMQ.Client;
using RabbitMQ.Client.Events;

using System.Text;

namespace _01.Rabbitmq.Consumer
{
    public class Program
    {
        private static string queueName = "hello";

        static void Main(string[] args)
        {

            // 创建一个连接工厂
            ConnectionFactory factory = new ConnectionFactory
            {
                HostName = "localhost",
                UserName = "guest",
                Password = "guest",
            };


            // publisher/consumer和broker之间的TCP连接
            using var connection = factory.CreateConnection();
            // Channel作为轻量级的Connection极大减少了操作系统建立TCPconnection的开销
            using var channel = connection.CreateModel();

            var arguments = new Dictionary<string, object>();
            arguments.Add("x-max-priority",9);
            // 创建队列/交换机(如队列/交换机已存在的情况可不用再次创建/此创建为:确保先开启消费者,生产者未创建队列/交换机而引发报错)
            channel.QueueDeclare("hello", true, false, false, arguments);
            //channel.QueueDeclare("hello", false, false, false, null);
            // 事件对象
            var consumer = new EventingBasicConsumer(channel);

            /*
            * 消费者消费消息
            * 1.消费哪个队列
            * 2.消费成功之后是否要自动应答 true 代表自动应答 false 手动应答
            * 3.消费者未成功消费的回调
            */
            channel.BasicConsume("hello", true, consumer);

            // 接收消息回调
            consumer.Received += (sender, e) =>
            {
                var body = e.Body.ToArray();
                var message = Encoding.UTF8.GetString(body);
                Console.WriteLine("已接收: {0}", message);

            };
            Console.ReadKey();
        }
    }

}

测试效果

image.png

惰性队列

场景

长时间不能消费消息造成堆积

  • 消费者下线
  • 消费者宕机
  • 消费者由于维护而关闭

配置

var arguments = new Dictionary<string, object>();
arguments.("x-queue-mode", "lazy");
channel.QueueDeclare("hello", true, false, false, arguments);

性能对比

image.png
在发送1百万条消息,每条消息大概占1KB的情况下,普通队列占用内存是1.2GB,而惰性队列仅仅占用1.5MB,但是消费惰性队列的消息就比较慢,因为要先从磁盘读取在加载到内存中,根据场景选择

标签:实战,知识点,false,队列,RabbitMQ,var,using,hello,channel
From: https://www.cnblogs.com/imtudou/p/17311518.html

相关文章

  • Go微服务框架go-kratos实战学习08:负载均衡基本使用
    微服务框架go-kratos中负载均衡使用一、介绍在前面这篇文章负载均衡和它的算法介绍,讲了什么是负载均衡以及作用、算法介绍。go-kratos的负载均衡主要接口是Selector,它是一个可插拔的设计。因为它设计的都是接口,只要实现了接口就实现了负载均衡。go-kratos在目录下提供了......
  • Android Kotlin实战之高阶使用泛型扩展协程懒加载详解
    前言:通过前面几篇文章,我们已基本掌握kotlin的基本写法与使用,但是在开发过程中,以及一些开源的API还是会出现大家模式的高阶玩法以及问题,如何避免,接下来讲解针对原来的文章进行一些扩展,解决大家在工作中遇到的问题,如何去解决如果还有人不了解kotlin,可以查看我的基础篇kotlin。Android......
  • testng+HttpClient项目实战(一)
    参考文档:https://www.cnblogs.com/yingyingja/p/9973960.htmlhttps://www.cnblogs.com/yingyingja/p/9974181.htmlhttps://www.cnblogs.com/yingyingja/p/9974183.htmlhttps://www.cnblogs.com/yingyingja/p/9974186.htmlhttps://www.cnblogs.com/yingyingja/p/9974189.html......
  • (之前的项目复习)我的Java项目实战--校园餐饮商户外卖系统03
    开发笔记三分类管理业务开发公共字段自动填充问题分析前面我们已经完成了后台系统的员工管理功能开发,在新增员工时需要设置创建时间、创建人、修改时间、修改人等字段,在编辑员工时需要设置修改时间和修改人等字段。这些字段属于公共字段,也就是很多表中都有这些字段,如下:能......
  • 学习笔记396—自定义Docker镜像推送到Docker Hub实战
    自定义Docker镜像推送到DockerHub实战云原生探索的必经之路—容器化,而容器化目前最主流的技术莫过于Docker了,因为之前也大量的输出过Docker相关的技术博客,如果感兴趣的话可以直接访问专栏:​​《探索云原生》​​,按需学习哦。这篇文章还是从Docker入手,从0开始讲述下如何将自己的D......
  • #yyds干货盘点 前端小知识点扫盲笔记记录2
    前言大家好我是歌谣今天继续进行前端知识的一些总结想加入前端巅峰交流群私信我innerHTML和innerText的使用<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge">......
  • ansible模块实战练习
    ansible模块实战练习Cloud研习社 Cloud研习社 2023-04-0110:55 发表于山东收录于合集#一站式教程220个#计算机185个#ansible22个#云计算196个#linux209个教程每周二、四、六更新今天我们练习一下ansible模块的用法,也算是一个小复习:准备三个节点:其中一个作......
  • 15.6二叉排序树删除实战
    #include<stdio.h>#include<stdlib.h>typedefintKeyType;typedefstructBSTNode{KeyTypekey;structBSTNode*lchild,*rchild;}BSTNode,*BiTree;//非递归的创建二叉查找数intBST_Insert(BiTree&T,KeyTypek){BiTreeTreeNew=(BiTree)cal......
  • 15.5二叉排序树原理及建树实战
    #include<stdio.h>#include<stdlib.h>typedefintKeyType;typedefstructBSTNode{KeyTypekey;structBSTNode*lchild,*rchild;}BSTNode,*BiTree;//非递归的创建二叉查找数intBST_Insert(BiTree&T,KeyTypek){BiTreeTreeNew=(BiTree)cal......
  • 程序员下班做什么副业好?实战方法新手小白可上手!1000多字总结
    以前我就是个程序员,所以,现在有做副业的想法是很不错的,可以多点收入,而且以下方法即使不是程序员,新手小白也可以干。我来分享一下做副业的经验和看法;现在我已经往运营方向发展了。作为一个网站开发工程师,我在上家公司干了3年的活,做过javaweb,前端html、js、css,asp.net we......