RabbitMQ 集群与高可用性

目录

单节点与集群部署

1.1. 单节点部署

1.2. 集群部署

 镜像队列

1.定义与工作原理

2. 配置镜像队列

3.应用场景

4. 优缺点

5. Java 示例

分布式部署

1. 分布式部署的主要目标

2. 典型架构设计

3. RabbitMQ 分布式部署的关键技术

4. 部署策略和实践

5. 分布式部署的挑战和解决方案

6.使用Docker Compose 实现分布式部署

总结


前言

RabbitMQ 是一个广泛使用的消息队列系统,具有强大的集群和高可用性特性。以下是有关 RabbitMQ 集群与高可用性方面的详细解析,涵盖了单节点与集群部署、镜像队列、以及分布式架构的部署策略和最佳实践。

单节点与集群部署

1.1. 单节点部署

定义
RabbitMQ 的单节点部署是指在一台服务器上运行一个 RabbitMQ 实例。它适用于开发、测试环境或对高可用性要求不高的场景。

工作原理
在单节点中,所有消息和队列都集中在一个 RabbitMQ 实例上。如果该实例出现故障,则会导致消息服务不可用。

优缺点

  • 优点

    • 简单易用,部署和管理成本低。
    • 适合小规模应用和开发测试场景。
  • 缺点

    • 没有冗余,存在单点故障风险。
    • 扩展性差,难以应对高并发和大流量需求。

应用场景

  • 开发和测试环境。
  • 对消息丢失或短暂服务中断容忍度较高的生产环境。

配置方式

  • 在单台服务器上安装 RabbitMQ。
  • 通过管理插件或命令行工具进行简单的管理和监控。

示例

  • 使用 Docker 启动单节点 RabbitMQ:
docker run -d --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:management

详细可参考之前的文章:

RabbitMQ入门基础及使用Docker安装

1.2. 集群部署

定义
RabbitMQ 集群由多个 RabbitMQ 节点组成,这些节点协同工作以提供更高的可用性和可扩展性。

工作原理
集群中的各个节点共享元数据,但消息存储在单个节点上(默认配置)。当一个节点出现故障时,集群中的其他节点仍然可以继续提供服务。

优缺点

  • 优点

    • 提高了系统的可靠性,减少单点故障。
    • 支持横向扩展,能够处理更多的消息和更高的并发量。
  • 缺点

    • 部署和管理相对复杂。
    • 需要额外的网络和存储资源。

应用场景

  • 高可用性要求高的生产环境。
  • 大流量、大并发的分布式系统。

配置方式一

1. 创建网络

docker network create rabbitmq-network

创建一个 Docker 自定义网络,名为 rabbitmq-network。此网络用于让各个 RabbitMQ 容器节点能够相互通信。Docker 网络确保节点之间的容器可以通过容器名互相访问,这对于集群的节点发现和通信至关重要

2. 启动节点1(磁盘节点)

# rabbitmq:3.12-management 镜像名:版本
docker run -d --hostname rabbit1 --name rabbit1 --network rabbitmq-network -e RABBITMQ_ERLANG_COOKIE='my_cookie' -e RABBITMQ_NODENAME=rabbit@rabbit1 -p 15672:15672 -p 5672:5672 rabbitmq:3.12-management
  • -d:后台运行容器。
  • --hostname rabbit1:设置容器的主机名为 rabbit1,这是 RabbitMQ 节点的名称标识。
  • --name rabbit1:设置容器的名称为 rabbit1,用于 Docker 内部管理。
  • --network rabbitmq-network:将容器连接到前面创建的 rabbitmq-network 网络中。
  • -e RABBITMQ_ERLANG_COOKIE='my_cookie':设置 Erlang Cookie,用于节点间的身份验证,确保集群的安全性。
  • -e RABBITMQ_NODENAME=rabbit@rabbit1:设置 RabbitMQ 节点的名称为 rabbit@rabbit1,这个名称在集群中是唯一的。
  • -p 15672:15672-p 5672:5672:分别映射管理界面和 AMQP 协议的端口到宿主机上,允许外部访问。

这是一个磁盘节点(默认),数据会保存在磁盘上。

3.启动节点2(RAM节点)

docker run -d --hostname rabbit2 --name rabbit2 --network rabbitmq-network -e RABBITMQ_ERLANG_COOKIE='my_cookie' -e RABBITMQ_NODENAME=rabbit@rabbit2 rabbitmq:3.12-management

 与启动节点1类似,但不暴露端口,并且这个节点稍后会加入到集群中并设置为 RAM 节点。RAM 节点的数据存储在内存中,适合对性能要求高的场景。

4.将节点2加入集群

docker exec -it rabbit2 bash
rabbitmqctl stop_app
rabbitmqctl join_cluster rabbit@rabbit1
rabbitmqctl start_app
exit
  • docker exec -it rabbit2 bash:进入 rabbit2 容器的交互式终端。
  • rabbitmqctl stop_app:停止 RabbitMQ 应用,准备加入集群。
  • rabbitmqctl join_cluster rabbit@rabbit1:将 rabbit2 节点加入到 rabbit1 节点所在的集群中。
  • rabbitmqctl start_app:启动 RabbitMQ 应用,使节点成为集群的一部分。
  • exit:退出容器的交互式终端。

5.启动节点3(RAM节点)

docker run -d --hostname rabbit3 --name rabbit3 --network rabbitmq-network -e RABBITMQ_ERLANG_COOKIE='my_cookie' -e RABBITMQ_NODENAME=rabbit@rabbit3 rabbitmq:3.12-management

 启动另一个 RAM 节点 rabbit3,与启动节点2类似。

6.将节点3加入集群

docker exec -it rabbit3 bash
rabbitmqctl stop_app
rabbitmqctl join_cluster rabbit@rabbit1
rabbitmqctl start_app
exit

与节点2的加入过程相同,将 rabbit3 加入到集群中,使其成为集群的一部分

  • 这组指令搭建了一个包含一个磁盘节点(rabbit1)和两个 RAM 节点(rabbit2 和 rabbit3)的 RabbitMQ 集群。
  • 磁盘节点负责持久化数据,RAM 节点利用内存加快消息的处理速度。
  • 每个节点通过指定的网络相互通信,并通过 Erlang Cookie 进行身份验证。
     

7.启动并访问

注:由于本次启动时并没有指定用户与密码,所以使用默认的guest/guest进行登录即可,也可以自己基于之前的文章 进行添加用户:
RabbitMQ日常运维指令集

 配置方式二

使用 Docker Compose 部署一个简单的 RabbitMQ 集群是一种便捷的方法,可以轻松管理多个 RabbitMQ 节点。以下是详细的步骤,包括如何编写 docker-compose.yml 文件以及配置、启动集群的过程。

1. 准备 docker-compose.yml 文件

首先,创建一个名为 docker-compose.yml 的文件,该文件定义了 RabbitMQ 集群的服务配置:

version: '3.8'
services:rabbit1:image: rabbitmq:3.12-managementcontainer_name: rabbit1hostname: rabbit1environment:RABBITMQ_ERLANG_COOKIE: 'my_cookie'RABBITMQ_NODENAME: 'rabbit@rabbit1'ports:- "15672:15672"  # 管理界面端口- "5672:5672"    # AMQP 协议端口networks:- rabbitmq_networkvolumes:- rabbit1_data:/var/lib/rabbitmqrabbit2:image: rabbitmq:3.12-managementcontainer_name: rabbit2hostname: rabbit2environment:RABBITMQ_ERLANG_COOKIE: 'my_cookie'RABBITMQ_NODENAME: 'rabbit@rabbit2'networks:- rabbitmq_networkvolumes:- rabbit2_data:/var/lib/rabbitmqrabbit3:image: rabbitmq:3.12-managementcontainer_name: rabbit3hostname: rabbit3environment:RABBITMQ_ERLANG_COOKIE: 'my_cookie'RABBITMQ_NODENAME: 'rabbit@rabbit3'networks:- rabbitmq_networkvolumes:- rabbit3_data:/var/lib/rabbitmqnetworks:rabbitmq_network:volumes:rabbit1_data:rabbit2_data:rabbit3_data:

docker-compose.yml 文件说明

  • version: 3.8 指定了 Docker Compose 文件的版本。
  • services: 定义了三个 RabbitMQ 服务 rabbit1rabbit2rabbit3,分别对应三个节点。
  • image: 使用 rabbitmq:3-management 镜像,包含 RabbitMQ 和管理插件。
  • container_name: 每个服务对应的容器名称。
  • hostname: 指定每个 RabbitMQ 节点的主机名,这对于集群中的节点名称是必要的。
  • environment: 配置环境变量:
    • RABBITMQ_ERLANG_COOKIE: Erlang Cookie,用于节点间的通信和认证。
    • RABBITMQ_NODENAME: 节点名称,必须唯一。
  • ports: 将 RabbitMQ 的管理界面和 AMQP 端口映射到宿主机上。
  • networks: 使用自定义的 rabbitmq_network 网络,以确保各节点之间可以互相通信。
  • volumes: 为每个节点配置持久化存储,以便重启后数据不会丢失。

2.启动集群

在包含 docker-compose.yml 文件的目录下,运行以下命令以启动集群:

docker-compose up -d

 此命令将在后台启动所有定义的 RabbitMQ 节点,并且这些节点将自动连接到同一个 Docker 网络 rabbitmq_network

验证集群

要验证集群是否正常运行,可以通过以下步骤:

检查服务状态

查看所有运行的容器,确保三个 RabbitMQ 容器都在运行:

docker ps

检查集群状态

进入 rabbit1 容器并检查集群状态:

docker exec -it rabbit1 bash
rabbitmqctl cluster_status

停止和删除集群

要停止并删除容器及其相关的网络和卷,运行以下命令:

docker-compose down -v

-v 选项将删除创建的卷,确保数据被清除。

 镜像队列

1.定义与工作原理

镜像队列是指将主节点的队列内容同步到集群中的其他节点上。当消费者从队列消费消息时,消息会从主节点发送,镜像节点会同步地更新其状态。如果主节点出现故障,RabbitMQ 会自动将其中一个镜像节点提升为新的主节点,从而继续处理队列中的消息。

工作原理

  • 主队列(Master Queue):在集群中的某个节点上维护的队列。
  • 镜像节点(Mirror Nodes):集群中的其他节点,它们会保持主队列的完整副本。
  • 故障切换(Failover):当主队列所在节点宕机时,RabbitMQ 自动选择一个镜像节点作为新的主队列,并继续处理消息。
2. 配置镜像队列

镜像队列可以通过 RabbitMQ 的策略(Policy)来配置。在 RabbitMQ 中,策略通过正则表达式匹配队列名称,然后应用指定的配置项来控制镜像队列的行为。

配置镜像队列的步骤:

  1. 连接到 RabbitMQ 管理界面或通过命令行执行操作。

  2. 创建策略,指定要镜像的队列以及镜像的规则:

    通过 RabbitMQ 管理界面:

    • 进入 "Admin" 选项卡,选择 "Policies"。
    • 创建新的策略,指定名称、匹配队列的正则表达式(如 ^mirrored.*)、配置镜像参数。

    通过命令行:

rabbitmqctl set_policy ha-all "^mirrored.*" '{"ha-mode":"all"}'
  • 以上命令的含义:

    • ha-all:策略名称。
    • ^mirrored.*:匹配队列名称的正则表达式,所有以 mirrored 开头的队列都会应用该策略。
    • {"ha-mode":"all"}:指定将队列镜像到集群中的所有节点。
  • 验证配置

    • 使用 RabbitMQ 管理界面查看队列状态,确认队列已被镜像。
    • 或使用以下命令行查看队列详细信息:
rabbitmqctl list_queues name policy slave_pids
3.应用场景

镜像队列特别适用于以下场景:

  • 高可用性要求高的系统:如金融、医疗等行业,需要保证消息不丢失且系统持续可用。
  • 灾备系统:需要容灾功能,保证在某个节点宕机时,系统仍然可以正常运行。
  • 关键任务应用:不能容忍消息丢失的业务逻辑。
4. 优缺点

优点

  • 高可用性:在节点故障时,自动故障切换确保队列的持续可用性。
  • 数据冗余:消息会在多个节点上存储,有助于防止单点故障导致的数据丢失。

缺点

  • 性能开销:每条消息的操作都需要在多个节点间进行同步,可能会影响吞吐量和延迟。
  • 资源消耗:由于数据在多个节点间复制,需要更多的存储和网络资源。
  • 复杂性:配置和维护镜像队列相对复杂,特别是在集群规模较大时。
5. Java 示例

假设我们有一个需要镜像的队列,以下是使用 Java 和 Spring AMQP 创建并连接到一个镜像队列的示例。

import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.QueueBuilder;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class RabbitConfig {@Beanpublic Queue mirroredQueue() {return QueueBuilder.durable("mirrored.queue").withArgument("x-ha-policy", "all") // 配置为镜像队列.build();}@Beanpublic RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {return new RabbitTemplate(connectionFactory);}@Beanpublic RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory) {return new RabbitAdmin(connectionFactory);}
}

使用了 x-ha-policy 参数来配置队列为镜像队列

分布式部署

分布式部署意味着将 RabbitMQ 节点分布在不同的数据中心、地理位置或网络环境中。这种部署方式适用于需要跨多个地区或数据中心实现高可用性和容灾的场景。

1. 分布式部署的主要目标
  • 容灾:确保在一个数据中心或地理位置发生故障时,系统仍然能够正常运行。
  • 负载均衡:通过分布多个节点,均衡不同区域的请求负载。
  • 数据局部化:为不同区域的用户提供更低延迟的服务。
2. 典型架构设计

分布式部署通常包括以下几种架构模式:

  • 多集群架构:在不同的数据中心或地理位置各自运行一个独立的 RabbitMQ 集群,之间通过某种消息传递机制进行通信,如使用 ShovelFederation 插件。
  • 跨数据中心的集群:在不同的数据中心部署一个跨越数据中心的 RabbitMQ 集群,节点之间通过 WAN 网络进行同步。该方案适合低延迟且带宽足够的环境。
3. RabbitMQ 分布式部署的关键技术

3.1 Shovel 插件

Shovel 插件用于在两个不同的 RabbitMQ 实例或集群之间转发消息。它能有效地在跨网络的 RabbitMQ 实例之间传递消息。

示例配置

# 在 rabbit1 节点上安装并配置 Shovel 插件
rabbitmq-plugins enable rabbitmq_shovel
rabbitmq-plugins enable rabbitmq_shovel_management# 创建 Shovel 配置
rabbitmqctl set_parameter shovel my-shovel \'{"src-uri": "amqp://user:pass@rabbit1/vhost", "src-queue": "queue1", "dest-uri": "amqp://user:pass@rabbit2/vhost", "dest-queue": "queue2"}'

Shovel 插件会从 queue1 拉取消息并转发到 queue2,实现不同 RabbitMQ 实例之间的消息传递。

3.2 Federation 插件

Federation 插件允许不同的 RabbitMQ 集群通过逻辑链接进行消息传递。与 Shovel 不同,Federation 更适合跨地理位置的集群之间建立动态连接。

示例配置

# 在 rabbit1 节点上启用 Federation 插件
rabbitmq-plugins enable rabbitmq_federation
rabbitmq-plugins enable rabbitmq_federation_management# 配置 Federation Upstream
rabbitmqctl set_parameter federation-upstream my-upstream '{"uri":"amqp://user:pass@rabbit2/vhost"}'# 配置 Federation Policy
rabbitmqctl set_policy my-federation ".*" \'{"federation-upstream-set":"all"}'

Federation 插件会将消息从一个集群传递到另一个集群。

4. 部署策略和实践

4.1 地理分布式集群

在每个主要地区或数据中心部署一个 RabbitMQ 集群,使用 Federation 或 Shovel 在这些集群之间转发消息。这种策略可以为每个地区的用户提供低延迟服务,并且在一个地区发生故障时,其他地区的服务不受影响。

4.2 多租户架构

在分布式部署中,可以通过虚拟主机(vhost)隔离不同租户的数据和操作。不同租户可以在不同的数据中心有各自的 RabbitMQ 集群,Shovel 或 Federation 可以实现租户数据的跨区域同步。

4.3 数据局部化

根据用户地理位置,将用户请求路由到最近的数据中心。使用分布式 RabbitMQ 结构可以有效减少延迟,提升用户体验。

5. 分布式部署的挑战和解决方案
  • 网络延迟:跨数据中心的通信会受到网络延迟的影响。解决方案包括在低延迟网络上部署节点,或使用本地缓存。
  • 数据一致性:保证跨节点或集群的数据一致性是一个挑战。可以通过消息的持久化和确认机制来减少不一致的风险。
  • 运维复杂性:分布式部署增加了运维的复杂性,需要更复杂的监控、报警和自动化工具来管理。

通过合理的架构设计和技术手段,可以有效地在不同网络环境下实现 RabbitMQ 的分布式部署,从而实现系统的高可用性、容灾和低延迟服务。

6.使用Docker Compose 实现分布式部署

在每个服务器上,创建一个 docker-compose.yml 文件,用于定义 RabbitMQ 服务的配置。假设我们有两台服务器 server1server2

Server 1 的 docker-compose.yml:

version: '3.7'
services:rabbitmq1:image: rabbitmq:3.12-managementcontainer_name: rabbitmq1hostname: rabbit1environment:- RABBITMQ_ERLANG_COOKIE=my_cookie- RABBITMQ_DEFAULT_USER=user- RABBITMQ_DEFAULT_PASS=passwordports:- "15672:15672" # 管理界面- "5672:5672"   # AMQP 端口networks:- rabbitmq-networknetworks:rabbitmq-network:driver: bridge

Server 2docker-compose.yml:

version: '3.7'
services:rabbitmq2:image: rabbitmq:3.12-managementcontainer_name: rabbitmq2hostname: rabbit2environment:- RABBITMQ_ERLANG_COOKIE=my_cookie- RABBITMQ_DEFAULT_USER=user- RABBITMQ_DEFAULT_PASS=passwordports:- "15672:15672" # 管理界面- "5672:5672"   # AMQP 端口networks:- rabbitmq-networknetworks:rabbitmq-network:driver: bridge

部署 RabbitMQ 实例

server1server2 上分别运行以下命令来启动 RabbitMQ 服务:

docker-compose up -d

这将在每个服务器上启动一个 RabbitMQ 实例。

4. 配置 Shovel 插件或 Federation 插件

接下来,使用 ShovelFederation 插件来连接这两个分布式的 RabbitMQ 实例。

使用 Shovel 插件配置消息传递

server1 上:

docker exec -it rabbitmq1 bash
rabbitmq-plugins enable rabbitmq_shovel
rabbitmq-plugins enable rabbitmq_shovel_management
rabbitmqctl set_parameter shovel my-shovel \'{"src-uri": "amqp://user:password@rabbit1/vhost", "src-queue": "queue1", "dest-uri": "amqp://user:password@rabbit2/vhost", "dest-queue": "queue2"}'

server2 上:

docker exec -it rabbitmq2 bash
rabbitmq-plugins enable rabbitmq_shovel
rabbitmq-plugins enable rabbitmq_shovel_management
rabbitmqctl set_parameter shovel my-shovel \'{"src-uri": "amqp://user:password@rabbit2/vhost", "src-queue": "queue2", "dest-uri": "amqp://user:password@rabbit1/vhost", "dest-queue": "queue1"}'

使用 Federation 插件配置消息传递

server1 上:

docker exec -it rabbitmq1 bash
rabbitmq-plugins enable rabbitmq_federation
rabbitmq-plugins enable rabbitmq_federation_management
rabbitmqctl set_parameter federation-upstream my-upstream \'{"uri":"amqp://user:password@rabbit2/vhost"}'
rabbitmqctl set_policy my-federation ".*" \'{"federation-upstream-set":"all"}'

 在 server2 上:

docker exec -it rabbitmq2 bash
rabbitmq-plugins enable rabbitmq_federation
rabbitmq-plugins enable rabbitmq_federation_management
rabbitmqctl set_parameter federation-upstream my-upstream \'{"uri":"amqp://user:password@rabbit1/vhost"}'
rabbitmqctl set_policy my-federation ".*" \'{"federation-upstream-set":"all"}'

总结

  • 单节点与集群部署:单节点适用于开发和测试环境,集群部署用于生产环境,提高了系统的可靠性和可扩展性。
  • 镜像队列:为关键业务场景提供高可用性,确保消息在节点故障时不会丢失。
  • 分布式架构:通过 Federation 和 Shovel 插件,RabbitMQ 可以在不同地理位置的集群间实现消息的传递,适用于复杂的分布式系统。

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

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

相关文章

解决银河麒麟桌面操作系统V10(特别是2101版本)中无法通过interfaces设置网络

解决银河麒麟桌面操作系统V10(特别是2101版本)中无法通过interfaces设置网络 1、问题简述2、解决方案1. 尝试删除ppp文件、重启2. 使用NetworkManager 💖The Begin💖点点关注,收藏不迷路💖 1、问题简述 在…

day44——C++对C的扩充

八、C对函数的扩充 8.1 函数重载(overload) 1> 概念 函数重载就是能够实现"一名多用",是实现泛型编程的一种 泛型编程:试图以不变的代码,来实现可变的功能 2> 引入背景 程序员在写函数时&#x…

k8s的组件以及安装

目录 概念 k8s的使用场景 k8s的特点 核心组件 master主组件 1.kube-apiserver 2.etcd 3.kube-controller-manager 控制器 4.kube-scheduler node从节点组件 1.kubelet 2.kube-proxy 3.docker 总结 k8s的核心概念 安装k8s 架构 安装步骤 实验:创…

Linux学习笔记(4)----Debian压力测试方法

使用命令行终端压力测试需要两个实用工具:s-tui和stress sudo apt install s-tui stress 安装完成后,在终端中启动 s-tui实用工具: s-tui 执行后如下图: 你可以使用鼠标或键盘箭头键浏览菜单,然后点击“压力选项(Str…

Leetcode Day14排序算法

动态git可以看 :https://leetcode.cn/problems/sort-an-array/solutions/179370/python-shi-xian-de-shi-da-jing-dian-pai-xu-suan-fa/ 选择排序 def selection_sort(nums):n len(nums)for i in range(n):for j in range(i, n):if nums[i] > nums[j]:nums[i], nums[j] …

甲基化组学全流程生信分析教程

甲基化组学全流程分析和可视化教程 读取数据目录下的idat文件的甲基化全流程一键分析 功能简介 甲基化分析模块可以实现甲基化芯片450K, 870kEPIC数据的自动读取,可以读取idat文件,也可以读取beta甲基化矩阵文件甲基化数据的缺失值插值甲基化数据的质…

python测试框架之Pytest

初识Pytest Pytest1.Pytest的特点:2.Pytest的基本使用规则3.pytest安装1)使用编译器安装2)使用命令安装 4.pytest规则 Pytest Pytest是python的一个第三方单元测试库,它的目的是让单元测试变得容易,并且也能扩展到支持…

解析云上实时数仓的挑战与实践 | Databend @DTCC 2024 演讲回顾

8 月 22 日 ~ 24 日,由 IT168 联合旗下 ITPUB、ChinaUnix 两大技术社区主办的第 15 届中国数据库技术大会(DTCC2024)在北京朗丽兹西山花园酒店成功召开。本次大会以“自研创新 数智未来”为主题,通过深度交流与探讨,推…

如何在手机上设置国内代理IP地址:详细指南

在某些情况下,我们可能需要在手机上设置国内代理IP地址,以便访问特定的网络服务或提高网络连接的稳定性。本文将详细介绍如何在Android和iOS设备上设置代理IP地址。 在Android设备上设置代理IP地址 在Android设备上设置代理IP地址非常简单,只…

MYSQL:简述对B树和B+树的认识

MySQL的索引使用B树结构。 1、B树 在说B树之前,先说说B树,B树是一个多路平衡查找树,相较于普通的二叉树,不会发生极度不平衡的状况,同时也是多路的。 B树的特点是:他会将数据也保存在非叶子节点。而这个…

C语言典型例题55

《C程序设计教程(第四版)——谭浩强》 题目: 例题4.7 兔子的繁殖。这是一个有趣的古典问题:有一对兔子,从出生后的第3个月开始起每个月都生一对兔子。小兔子长到第3个月又生一对兔子。假设所有兔子都不死,…

二叉搜索树进阶之红黑树

前言: 在上文我们已经学习了AVL树的相关知识以及涉及的四种旋转的内容,但是AVL树追求平衡导致旋转操作过多,一些情况下影响性能,由此我们就来了解一下二叉搜索树的另外一个分支,红黑树。 (倘若对旋转知识…

2024版Assimp配置教程

最近想看看图形学,选择速通LearnOpenGL,不出意外最耗时间的依然是配置环境。按照教程上的把GLFW等等配置的没有问题,但是在Assimp这里卡住了。原因是教程上说的不详细,而网上查的又和现在的版本相去甚远,导致捣鼓了好一…

从web.xml动态读取sunspringmvc.xml文件

文章目录 1.问题分析1.SunWebApplicationContext.java 中sunspringmvc.xml是写死的2.但是web.xml已经配置了init-param,所以应该是可以读取的 2.具体实现1.SunDispatcherServlet.java 得到ServletConfig传递给Spring容器完成初始化2.SunWebApplicationContext.java …

【C++从小白到大牛】C++的隐式和显示类型转换基础知识讲解

目录 1、C语言中的类型转换 2、C语言和C中可以相互转换的类型总结 C语言: CPP: 3. 为什么C需要四种类型转换 4、C四大强制类型转换 4.1static_cast 4.2 reinterpret_cast 4.3 const_cast 4.4dynamic_cast 注…

基于x86 平台opencv的图像采集和seetaface6的性别识别功能

目录 一、概述二、环境要求2.1 硬件环境2.2 软件环境三、开发流程3.1 编写测试3.2 配置资源文件3.3 验证功能一、概述 本文档是针对x86 平台opencv的图像采集和seetaface6的性别识别功能,opencv通过摄像头采集视频图像,将采集的视频图像送给seetaface6的性别识别模块从而实现…

谓词和量词

一、个体词和谓词 命题是一句陈述句,命题由个体词和谓词组成。 个体词是句子中的主语部分,比如这里的王童。 谓词是句子里的剩余部分,比如是一个三好学生 个体词用小写字母表示,谓词用大写字母+(&#…

数据库(专业存储数据)

数组、链表、变量----->内存:程序运行结束,数据丢失 文件-------------->硬盘 数据库:专业存储数据,大量数据----------->硬盘 一、数据库文件与普通文件区别: 1.普通文件对数据管理(增刪改查)效率低 2.数据库对数据…

算法: 双指针

题目:环形链表 题目讲解: 判断环 要判断链表是否有环,可以使用快慢指针的方法。快指针每次走两步,慢指针每次走一步。如果链表有环,快慢指针最终会相遇;如果没有环,快指针会先到达链表末尾。 …

MySQL:简述对事务的认识

浅谈对Spring事务的认识:https://xiaoer.blog.csdn.net/article/details/80849971 一、事务的特性 事务是数据库永恒不变的话题, ACID:原子性,一致性,隔离性,持久性。 (1)原子性&am…