2.9日学习打卡----初学RabbitMQ(四)

2.9日学习打卡

目录:

  • 2.9日学习打卡
  • 一.RabbitMQ 死信队列
    • 创建死信队列
    • 测试死信队列
  • 二. RabbitMQ 延迟队列
    • 延迟队列_死信队列实现
    • RabbitMQ延迟队列_插件实现
  • 三. RabbitMQ集群
    • 搭建RabbitMQ集群
    • 镜像队列
    • 负载均衡

一.RabbitMQ 死信队列

在这里插入图片描述
在MQ中,当消息成为死信(Dead message)后,消息中间件可以将其从当前队列发送到另一个队列中,这个队列就是死信队列。而在RabbitMQ中,由于有交换机的概念,实际是将死信发送给了死信交换机(Dead Letter Exchange,简称DLX)。死信交换机和死信队列和普通的没有区别。
在这里插入图片描述
消息成为死信的情况

  1. 队列消息长度到达限制。
  2. 消费者拒签消息,并且不把消息重新放入原队列。
  3. 消息到达存活时间未被消费。

在这里插入图片描述
死信队列
死信交换机和普通交换机,只是名字不同,其余的都一样;就是说死信交换机绑定死信队列,普通交换机绑定普通队列。

并且普通队列需要在创建的同时绑定死信交换机和死信队列的路由关键字;就是说当普通队列的消息达到死信的条件时,会通过绑定的死信交换机根据绑定的死信队列路由关键字发送该普通队列的消息,这个就是成为死信的过程。

除了拒签成为死信的需要监听普通队列,其余俩个不需要到达消费者端就会成为死信。
死信会有专门的死信消费者去监听。

创建死信队列

package com.jjy.rabbitproducer;import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class RabbitmqConfig4 {private final String DEAD_EXCHANGE = "dead_exchange";private final String DEAD_QUEUE = "dead_queue";private final String NORMAL_EXCHANGE = "normal_exchange";private final String NORMAL_QUEUE = "normal_queue";// 死信交换机@Bean(DEAD_EXCHANGE)public Exchange deadExchange(){return ExchangeBuilder.topicExchange(DEAD_EXCHANGE).durable(true).build();}// 死信队列@Bean(DEAD_QUEUE)public Queue deadQueue(){return QueueBuilder.durable(DEAD_QUEUE).build();}// 死信交换机绑定死信队列@Beanpublic Binding bindDeadQueue(@Qualifier(DEAD_EXCHANGE) Exchange exchange, @Qualifier(DEAD_QUEUE)Queue queue){return BindingBuilder.bind(queue).to(exchange).with("dead_routing").noargs();}// 普通交换机@Bean(NORMAL_EXCHANGE)public Exchange normalExchange(){return ExchangeBuilder.topicExchange(NORMAL_EXCHANGE).durable(true).build();}// 普通队列@Bean(NORMAL_QUEUE)public Queue normalQueue(){return QueueBuilder.durable(NORMAL_QUEUE).deadLetterExchange(DEAD_EXCHANGE) // 绑定死信交换机.deadLetterRoutingKey("dead_routing") // 死信队列路由关键字.ttl(10000) // 消息存活10s.maxLength(10) // 队列最大长度为10.build();}// 普通交换机绑定普通队列@Beanpublic Binding bindNormalQueue(@Qualifier(NORMAL_EXCHANGE) Exchange exchange,@Qualifier(NORMAL_QUEUE)Queue queue){return BindingBuilder.bind(queue).to(exchange).with("my_routing").noargs();}
}

测试死信队列

生产者发送消息

 @Testpublic void TestDlx(){// 存活时间过期后变成死信rabbitTemplate.convertAndSend("normal_exchange","my_routing","测试死信");// 超过队列长度后变成死信for (int i = 0; i < 20; i++) {rabbitTemplate.convertAndSend("normal_exchange","my_routing","测试死信");}// 消息拒签但不返回原队列后变成死信rabbitTemplate.convertAndSend("normal_exchange","my_routing","测试死信");}

消费者拒收消息

package com.jjy.rabbitconsumer;import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;import java.io.IOException;@Component
public class DlxConsumer {@RabbitListener(queues = "normal_queue")public void listenMessage(Message message, Channel channel) throws IOException {// 拒签消息channel.basicNack(message.getMessageProperties().getDeliveryTag(),true,false);}
}

二. RabbitMQ 延迟队列

在这里插入图片描述
延迟队列,即消息进入队列后不会立即被消费,只有到达指定时间后,才会被消费。

例如:用户下单后,30分钟后查询订单状态,未支付则会取消订单
在这里插入图片描述
但RabbitMQ中并未提供延迟队列功能,我们可以使用死信队列实现延迟队列的效果。
在这里插入图片描述

延迟队列_死信队列实现

在这里插入图片描述
编写配置文件


spring:rabbitmq:host: 192.168.66.100port: 5672username: jjypassword: jjyvirtual-host: /# 日志格式
logging:pattern:console: '%d{HH:mm:ss.SSS} %clr(%-5level) ---  [%-15thread] %cyan(%-50logger{50}):%msg%n'

创建队列和交换机

package com.jjy.yanchirabbitmqdemo;import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class RabbitmqConfig {// 订单交换机和队列private final String ORDER_EXCHANGE = "order_exchange";private final String ORDER_QUEUE = "order_queue";// 过期订单交换机和队列private final String EXPIRE_EXCHANGE = "expire_exchange";private final String EXPIRE_QUEUE = "expire_queue";// 过期订单交换机@Bean(EXPIRE_EXCHANGE)public Exchange deadExchange(){return ExchangeBuilder.topicExchange(EXPIRE_EXCHANGE).durable(true).build();}// 过期订单队列@Bean(EXPIRE_QUEUE)public Queue deadQueue(){return QueueBuilder.durable(EXPIRE_QUEUE).build();}// 将过期订单队列绑定到交换机@Beanpublic Binding bindDeadQueue(@Qualifier(EXPIRE_EXCHANGE) Exchange exchange,@Qualifier(EXPIRE_QUEUE) Queue queue){return BindingBuilder.bind(queue).to(exchange).with("expire_routing").noargs();}// 订单交换机@Bean(ORDER_EXCHANGE)public Exchange normalExchange(){return ExchangeBuilder.topicExchange(ORDER_EXCHANGE).durable(true).build();}// 订单队列@Bean(ORDER_QUEUE)public Queue normalQueue(){return QueueBuilder.durable(ORDER_QUEUE).ttl(10000) // 存活时间为10s,模拟30min.deadLetterExchange(EXPIRE_EXCHANGE) // 绑定死信交换机.deadLetterRoutingKey("expire_routing") // 死信交换机的路由关键字.build();}// 将订单队列绑定到交换机@Beanpublic Binding bindNormalQueue(@Qualifier(ORDER_EXCHANGE) Exchange exchange,@Qualifier(ORDER_QUEUE) Queue queue){return BindingBuilder.bind(queue).to(exchange).with("order_routing").noargs();}
}

编写下单的控制器方法,下单后向订单交换机发送消息

@RestController
public class OrderController {@Autowiredprivate RabbitTemplate rabbitTemplate;@GetMapping("/place/{orderId}")public String placeOrder(@PathVariable String orderId){System.out.println("处理订单数据");//将订单id发送到订单队列rabbitTemplate.convertAndSend("order_exchange","order_routing",orderId);return "下单成功,修改库存";}}

编写监听死信队列的消费者

package com.jjy.yanchirabbitmqdemo.consumer;import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;@Component
public class ExpireOrderConsumer {//监听过期订单队列@RabbitListener(queues = "expire_queue")public void listenMessage(String orderId){System.out.println("查询"+orderId+"订单状态,如果已支付无需处理,未支付,回退库存");}@RabbitListener(queues = "delayed_queue")public void listenMessage2(String orderId){System.out.println("查询"+orderId+"号订单的状态,如果已支付则无需处理,如果未支付则需要回退库存");}}

RabbitMQ延迟队列_插件实现

在这里插入图片描述
在使用死信队列实现延迟队列时,会遇到一个问题:RabbitMQ只会移除队列顶端的过期消息,如果第一个消息的存活时长较长,而第二个消息的存活时长较短,则第二个消息并不会及时执行。
在这里插入图片描述
RabbitMQ虽然本身不能使用延迟队列,但官方提供了延迟队列插
件,安装后可直接使用延迟队列。
在这里插入图片描述
安装延迟队列插件

  1. 使用rz将rabbitmq_delayed_message_exchange-3.10.2.ez 插件上传到虚拟机
  2. 安装插件
# 将插件放入RabbitMQ插件目录中
mv rabbitmq_delayed_message_exchange-
3.9.0.ez /usr/local/rabbitmq/plugins/
# 启用插件
rabbitmq-plugins enable
rabbitmq_delayed_message_exchange
  1. 重启RabbitMQ服务
#停止rabbitmq
rabbitmqctl stop
#启动rabbitmq
rabbitmq-server restart -detached

此时登录管控台可以看到交换机类型多了延迟消息
管控台地址(https://自己地址:15672)默认账号和密码都是 guest
在这里插入图片描述
此时交换机是x-delayed-message类型的;延迟队列就是说发送延迟交换机及其绑定延迟队列的路由关键字和MessagePostProcessor对象,MessagePostProcessor对象是用来设置延迟时长等属性的。

延迟队列只是创建延迟交换机时跟普通不同,其他基本相同。

执行流程就是浏览器通过url映射到Controller的@RequestMapping注解的value中,然后执行方法体,执行到发送MQ,然后结束方法体;MQ此时延迟方法体中设置的时长,再发送给消费端,消费端监听到再处理延迟队列的MQ。
使用延迟队列

package com.jjy.yanchirabbitmqdemo;import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.HashMap;
import java.util.Map;@Configuration
public class RabbitmqConfig2 {public final String DELAYED_EXCHANGE = "delayed_exchange";public final String DELAYED_QUEUE = "delayed_queue";//1.延迟交换机@Bean(DELAYED_EXCHANGE)public Exchange delayedExchange() {// 创建自定义交换机Map<String, Object> args = new HashMap<>();args.put("x-delayed-type", "topic"); // topic类型的延迟交换机return new CustomExchange(DELAYED_EXCHANGE, "x-delayed-message", true, false, args);}//2.延迟队列@Bean(DELAYED_QUEUE)public Queue delayedQueue() {return QueueBuilder.durable(DELAYED_QUEUE).build();}// 3.绑定@Beanpublic Binding bindingDelayedQueue(@Qualifier(DELAYED_QUEUE) Queue queue, @Qualifier(DELAYED_EXCHANGE) Exchange exchange) {return BindingBuilder.bind(queue).to(exchange).with("order_routing").noargs();}
}

编写下单的控制器方法

package com.jjy.yanchirabbitmqdemo.controller;import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;@RestController
public class OrderController {@Autowiredprivate RabbitTemplate rabbitTemplate;@GetMapping("/place2/{orderId}")public String placeOrder2(@PathVariable String orderId) {System.out.println("处理订单数据...");// 设置消息延迟时间为10秒MessagePostProcessor messagePostProcessor = new MessagePostProcessor() {@Overridepublic Message postProcessMessage(Message message) throws AmqpException {message.getMessageProperties().setDelay(10000);return message;}};// 将订单id发送到订单队列rabbitTemplate.convertAndSend("delayed_exchange", "order_routing", orderId, messagePostProcessor);return "下单成功,修改库存";}}

编写消费者

package com.jjy.yanchirabbitmqdemo.consumer;import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;@Component
public class ExpireOrderConsumer {//监听过期订单队列@RabbitListener(queues = "expire_queue")public void listenMessage(String orderId){System.out.println("查询"+orderId+"订单状态,如果已支付无需处理,未支付,回退库存");}@RabbitListener(queues = "delayed_queue")public void listenMessage2(String orderId){System.out.println("查询"+orderId+"号订单的状态,如果已支付则无需处理,如果未支付则需要回退库存");}}

三. RabbitMQ集群

在这里插入图片描述
在生产环境中,当单台RabbitMQ服务器无法满足消息的吞吐量及
安全性要求时,需要搭建RabbitMQ集群。

搭建RabbitMQ集群

设置两个RabbitMQ服务

# 关闭RabbitMQ服务
rabbitmqctl stop
# 设置服务一
RABBITMQ_NODE_PORT=5673 RABBITMQ_NODENAME=rabbit1 rabbitmq-server
start -detached
# 设置服务二
RABBITMQ_NODE_PORT=5674 RABBITMQ_SERVER_START_ARGS="-rabbitmq_management listener
[{port,15674}]" RABBITMQ_NODENAME=rabbit2 rabbitmq-server start -detached

将两个服务设置到同一集群中

# 关闭服务2
rabbitmqctl -n rabbit2 stop_app
# 重新设置服务2
rabbitmqctl -n rabbit2 reset
# 将服务2加入服务1中
rabbitmqctl -n rabbit2 join_cluster rabbit1@localhost(自己的主机名)
# 启动服务2
rabbitmqctl -n rabbit2 start_app

这个主机名可以到管控台看
在这里插入图片描述
@后面的就是主机名

镜像队列

在这里插入图片描述

搭建了集群后,虽然多个节点可以互相通信,但队列只保存在了一个节点中,如果该节点故障,则整个集群都将丢失消息。

# 关闭服务1
rabbitmqctl -n rabbit1 stop_app

在这里插入图片描述

此时我们需要引入镜像队列机制,它可以将队列消息复制到集群中的其他节点上。如果一个节点失效了,另一个节点上的镜像可以保证服务的可用性。
在这里插入图片描述

在管此时某个节点故障则不会影响整个集群。控台点击Admin—>Policies设置镜像队列
在这里插入图片描述

Name为镜像策略的名字;Pattern(模式)的值为^,即应用于所有交换机和队列, ^xxx则是应用到以xxx开头交换机和队列。
ha-mode=all则是镜像模式:所有,即将队列镜像到集群的所有服务器中。
ha-sync-mode: automatic设置为自动同步,即当某一服务器宕机,而有新的消息发送到来,当该服务器再次启动后,它已经拿不到该消息了,但是通过设置该参数可以自动同步消息。

负载均衡

在这里插入图片描述

无论是生产者还是消费者,只能连接一个RabbitMQ节点,而在我们使用RabbitMQ集群时,如果只连接一个RabbitMQ节点,会造成该节点的压力过大。我们需要平均的向每个RabbitMQ节点发送请求,此时需要一个负载均衡工具帮助我们分发请求,接下来使用Haproxy做负载均衡:
安装Haproxyyum -y install haproxy
配置Haproxyvim /etc/haproxy/haproxy.cfg
添加下面内容

# 以下为修改内容
defaults# 修改为tcpmode tcp# 以下为添加内容
listen rabbitmq_cluster# 对外暴露端口bind 0.0.0.0:5672mode tcpbalance roundrobin# 代理RabbitMQ的端口server node1 127.0.0.1:5673 check inter 5000 rise 2 fall 2server node2 127.0.0.1:5674 check inter 5000 rise 2 fall 2listen stats# Haproxy控制台路径bind 自己地址:8100mode httpoption httplogstats enablestats uri /rabbitmq-statsstats refresh 5s

访问Haproxy控制台:http://自己地址/rabbitmq-stats
在这里插入图片描述

生产者连接Haproxy发送消息

// 生产者
public class Producer {public static void main(String[] args) throws IOException, TimeoutException {ConnectionFactory connectionFactory = new ConnectionFactory();connectionFactory.setHost("192.168.66.100");connectionFactory.setPort(5672);connectionFactory.setUsername("guest");connectionFactory.setPassword("guest");connectionFactory.setVirtualHost("/");Connection conn = connectionFactory.newConnection();Channel channel = conn.createChannel();channel.queueDeclare("simple_queue", false, false, false, null);channel.basicPublish("", "simple_queue", null, "hello!rabbitmq!".getBytes());channel.close();conn.close();}
}

总结

  1. 由Springboot整合RabbitMQ实现通配符模式,通配符模式使用topic交换机,展示消息从生产者到消费者的一个过程。
    生产者由Config配置类+yml配置文件还有发送消息的一个调用操作组成;而消费者由yml配置文件和多个监听指定队列方法的类组成。
    RabbitMQ的Config配置类用来创建交换机、创建队列和将队列绑定到交换机;此时yml配置文件的内容是用来连接RabbitMQ的信息和一些模式的开关。
    模式有确认模式(Confirm),回退模式(Return),消费者消息确认(Consumer Ack) 三种;前俩种用在生产者,第三种用在消费者。
  • 确认模式是用以消息发送到交换机,此时不论成功或失败都会调用setConfirmCallback返回发送的结果(成功或失败),在失败时打印结果并处理失败的业务,成功时处理成功后的业务。
  • 回退模式则是消息从交换机发到队列的过程,当失败时调用setReturnsCallback方法,输出失败的原因等信息和失败后的处理操作。
  • 消费者消息确认可以设置手动和自动确认,自动确认因消费者监听方法内出现问题或者其他原因会导致消息丢失,所以一般是手动确认,在正常处理后确认签收,在出现异常时捕获异常,处理异常并拒签。
    整个过程总而言之,即从生产者发送消息到指定交换机,交换机再根据生产者给的路由键发送到指定队列,队列再发送到消费者。
  1. 在RabbitMQ的高级属性中,有消费端限流、公平与不公平分发、消息存活时间、优先级队列、死信队列、延迟队列。
  • 消费端限流就是说从队列到消费者的消息,消费者最多只能存在x条未处理的消息。
  • 公平分发就是每个消费者都得到平均分发的消息,一般不设置限流,不公平分发则是处理快的继续处理,没有数额限制,但是需要设置限流且值为1。
  • 消息存活时间可以设置队列消息的存活时间时需要在配置类在创建队列时指定,也可以设置单条消息的存活时间,但是需要在发送消息时创建并添加MessageProperties对象设置存活时间作为参数,俩这都是存活时间一过,消息等到队列顶端后移除。
  • 优先级队列,即需要在创建队列时指定队列的最大优先级,然后在发送消息时创建并添加MessageProperties对象设置优先级数作为参数。
  • 死信队列,即分别创建俩个交换机和俩个队列并将队列绑定到交换机,一个作为死信队列和交换机,一个作为普通队列和交换机,但是普通队列创建时需要绑定死信交换机和死信队列的路由键,并且当普通队列消息过期、拒收并且不重回普通队列、超过普通队列设置的最大消息长度时,将消息发送到死信交换机,死信交换机再发到死信队列,死信队列有专门的消费者进行监听。
  • 延迟队列有2种实现,一种是通过死信队列,设置普通队列的存活时间为延迟的时长,通过死信消费者处理延迟的消息;第二种是通过rabbitmq的延迟队列插件实现延迟队列。

3. RabbitMQ搭建集群及其实现镜像队列、负载均衡

  • 搭建集群就是多个独立的服务器在一个系统中组成一个群体;用以提高系统的可用性、处理能力、响应能力,防止宕机出现数据丢失,和解决服务器无法承受高并发的等问题。
  • 镜像队列就是复制主节点的数据到其他的从节点中,防止因为主节点宕机导致数据丢失。
  • 负载均衡就是将请求访问平均分发到集群的每个节点中,从而提高系统的性能,不会导致某个节点因为访问量过大从而出现系统性能降低或者该节点宕机。

关于RabbitMQ的学习就告一段落了 ,下次就是学习第二个消息中间件RocketMQ

如果我的内容对你有帮助,请点赞,评论,收藏。创作不易,大家的支持就是我坚持下去的动力!
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/258873.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

php基础学习之可变函数(web渗透测试关键字绕过rce和回调函数)

可变函数 看可变函数的知识点之前&#xff0c;蒟蒻博主建议你先去看看php的可变变量&#xff0c;会更加方便理解&#xff0c;在本篇博客中的第五块知识点->php基础学习之变量-CSDN博客 描述 当一个变量所保存的值刚好是一个函数的名字&#xff08;由函数命名规则可知该值必…

【复现】某公司指挥调度管理平台 RCE漏洞_51

目录 一.概述 二 .漏洞影响 三.漏洞复现 1. 漏洞一&#xff1a; 四.修复建议&#xff1a; 五. 搜索语法&#xff1a; 六.免责声明 一.概述 该平台提供强大的指挥调度功能&#xff0c;可以实时监控和管理通信网络设备、维护人员和工作任务等。用户可以通过该平台发送指令…

AD9361多片同步设计方法

本文基于ZC706FMCOMMS5的平台&#xff0c;介绍了多片AD9361同步的方法。并将该设计移植到自行设计的ZYNQ70354片AD9361(实现8路同步收发)的电路板上。 工程主要特点包括&#xff1a; 本设计采用纯逻辑的方式 1.4片AD9361组合&#xff0c;组成8通道发和8通道收 2.同步相位误差小…

[HTML]Web前端开发技术26(HTML5、CSS3、JavaScript )JavaScript基础——喵喵画网页

希望你开心&#xff0c;希望你健康&#xff0c;希望你幸福&#xff0c;希望你点赞&#xff01; 最后的最后&#xff0c;关注喵&#xff0c;关注喵&#xff0c;关注喵&#xff0c;佬佬会看到更多有趣的博客哦&#xff01;&#xff01;&#xff01; 喵喵喵&#xff0c;你对我真的…

PLC-Recorder的延伸分析功能说明

目录 一、缘起 二、如何从PLC-Recorder获取数据 1、在线获取 2、全自主打开数据文件 3、延伸分析 三、设置方法 四、效果展示 一、缘起 在各个行业&#xff0c;在不同的场景中&#xff0c;朋友们拿到数据后&#xff0c;想做的事情五花八门&#xff0c;有做宏观分析的、…

wps使用方法(包括:插入倒三角符号,字母上面加横线,将word中的所有英文设置为time new roman)

倒三角符号 字母上面加横线 将word中的所有英文设置为time new roman ctrla选中全文

Java基于微信小程序的医院挂号小程序,附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

作业帮 x TiDB丨多元化海量数据业务的支撑

导读 作业帮是一家成立于 2015 年的在线教育品牌&#xff0c;致力于用科技手段助力教育普惠。经过近十年的积累&#xff0c;作业帮运用人工智能、大数据等技术&#xff0c;为学生、老师、家长提供学习、教育解决方案&#xff0c;智能硬件产品等。随着公司产品和业务场景越来越…

CSS概述 | CSS的引入方式 | 选择器

文章目录 1.CSS概述2.CSS的引入方式2.1.内部样式表2.2.行内样式表2.3.外部样式表 3.选择器 1.CSS概述 CSS&#xff0c;全称Cascading Style Sheets&#xff08;层叠样式表&#xff09;&#xff0c;是一种用来设置HTML&#xff08;或XML等&#xff09;文档样式的语言。CSS的主要…

AI专题:5G-A扬帆风正劲,踏AI增长新浪潮

今天分享的是AI系列深度研究报告&#xff1a;《AI专题&#xff1a;5G-A扬帆风正劲&#xff0c;踏AI增长新浪潮》。 &#xff08;报告出品方&#xff1a;开源证券&#xff09; 报告共计&#xff1a;22页 足立连接&#xff0c;拓展算力&#xff0c;双曲线稳步发力 中兴通讯拥…

Rocky Linux 下载安装

一、VMware Workstation下载安装 1、安装教程 VMware Workstation下载安装&#xff08;含密钥&#xff09; 二、VMware Workstation 创建虚拟机 1、创建教程 VMware Workstation 创建虚拟机 三、Rocky Linux 下载 1、下载官网 RockyLinux.org 2、选择X86架构_64位系统_DVD镜…

Redis面试题整理(持续更新)

1. 缓存穿透&#xff1f; 缓存穿透是指查询一个一定不存在的数据&#xff0c;如果从存储层查不到数据则不写入缓存&#xff0c;这将导致这个不存在的数据每次请求都要到 DB 去查询&#xff0c;可能导致DB挂掉&#xff0c;这种情况大概率是遭到了攻击。 解决方案&#xff1a; …

【开源】SpringBoot框架开发创意工坊双创管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 管理员端2.2 Web 端2.3 移动端 三、系统展示四、核心代码4.1 查询项目4.2 移动端新增团队4.3 查询讲座4.4 讲座收藏4.5 小程序登录 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVueSpringBootMySQL的创意工坊双创管理…

TiDB in 2023, 一次简单的回顾丨PingCAP 唐刘

2023 年已经过去&#xff0c;TiDB 经过了一年的迭代&#xff0c;又往前进步了一点点&#xff0c;我们非常自豪的看到&#xff0c;TiDB 正在不断地帮助我们的客户成功&#xff0c;包括但不限于&#xff1a; ○ 首个云原生、分布式、全栈国产化银行核心业务系统投产上线丨TiDB …

Apache POI | Java操作Excel文件

目录 1、介绍 2、代码示例 2.1、将数据写入Excel文件 2.2、读取Excel文件中的数据 &#x1f343;作者介绍&#xff1a;双非本科大三网络工程专业在读&#xff0c;阿里云专家博主&#xff0c;专注于Java领域学习&#xff0c;擅长web应用开发、数据结构和算法&#xff0c;初步…

【开源图床】使用Typora+PicGo+Github+CDN搭建个人博客图床

准备工作&#xff1a; 首先电脑得提前完成安装如下&#xff1a; 1. nodejs环境(node ,npm):【安装指南】nodejs下载、安装与配置详细教程 2. Picgo:【安装指南】图床神器之Picgo下载、安装与配置详细教程 3. Typora:【安装指南】markdown神器之Typora下载、安装与无限使用详细教…

LeetCode---384周赛

题目列表 3033. 修改矩阵 3034. 匹配模式数组的子数组数目 I 3035. 回文字符串的最大数量 3036. 匹配模式数组的子数组数目 II 一、修改矩阵 简单模拟即可&#xff0c;代码如下 class Solution { public:vector<vector<int>> modifiedMatrix(vector<vecto…

Stable Diffusion教程——常用插件安装与测试(一)

前言 随着Stable Diffusion不断演进&#xff0c;越来越多的开发者开始涉足插件开发。尽管网络上存在大量教程&#xff0c;但它们通常零散分布&#xff0c;逐个学习和查找非常耗时&#xff0c;使人感觉每天都在劳累思考。这里总结了Stable Diffusion常用的插件安装与测试方法。…

[Angular 基础] - 视图封装 局部引用 父子组件中内容传递

[Angular 基础] - 视图封装 & 局部引用 & 父子组件中内容传递 之前的笔记&#xff1a; [Angular 基础] - Angular 渲染过程 & 组件的创建 [Angular 基础] - 数据绑定(databinding) [Angular 基础] - 指令(directives) 以上为静态页面&#xff0c;即不涉及到跨组…

记一次有趣的逻辑漏洞挖洞经历

前言 前几天在网上冲浪的时候无意间看到了一个Edu的站点&#xff0c;是一个很常见的类似MOOC的那种在线学习系统&#xff0c;对外开放&#xff0c;同时有注册和登录功能。对于我这种常年低危的菜鸡来说&#xff0c;这是最愿意看到的&#xff0c;因为一个Web网站有了登录功能&a…