[Redis#18] 哨兵机制 | docker 部署实验 | 选举机制(leader主)

目录

基本概念

工作原理

哨兵节点的作用与配置

监控与心跳检测

⭕故障恢复流程

Docker 部署 Redis Sentinel

场景介绍

Docker 简介

Docker 安装

Docker Compose 编排 Redis 主从及哨兵节点

编排 Redis 主从节点

编排 Redis 哨兵节点

创建哨兵配置文件

启动服务

问题与解决

选举机制(常考)

主节点选举过程

实验

注意事项


  • 本章节相关操作不需要记忆,重点在于理解流程和原理。后续工作中如果用到了能查到即可。
  • 问题背景:在Redis的主从复制模式下,主节点故障时需要 人工 进行主从切换,并通知客户端切换到新的主节点,这对大规模应用来说是不可接受的。
  • 因此,自Redis 2.8开始提供了Redis Sentinel(哨兵)来解决这个问题。
基本概念

由于对 Redis 的许多概念都有不同的名词解释,所以在介绍 Redis Sentinel之前,先对几个名词概念进行必要的说明

    • 主节点:独立的redis-server进程。
    • 从节点:独立的redis-server进程,作为主节点的数据备份并分担读压力。
    • 数据节点:包括主节点和从节点。
    • 哨兵节点:监控数据节点的独立redis-sentinel进程。
    • 哨兵节点集合:多个redis-sentinel进程的组合。
    • 应用方:一个或多个连接Redis的进程。

之前我们学到的 人工干预流程如下:

  • 故障发现
    • 运维人员通过监控系统检测到Redis主节点出现宕机情况。
  • 选择新的主节点
    • 运维人员从现有的从节点中挑选一个(例如slave1),并通过执行命令SLAVEOF NO ONE将其转换为新的主节点。
  • 更新其他从节点配置
    • 对剩余的从节点(如slave2),运维人员执行命令SLAVEOF <newMasterIp> <newMasterPort>,让这些从节点开始与新的主节点同步数据。
  • 更新应用连接信息
    • 更新应用程序配置,使其指向新的主节点地址{newMasterIp}:{newMasterPort},确保客户端能够继续正常访问服务。
  • 处理恢复的原主节点
    • 如果原先宕机的主节点恢复正常,运维人员应在其上执行SLAVEOF <newMasterIp> <newMasterPort>命令,使其转变为从节点,加入到新的复制拓扑结构中。

工作原理

Redis Sentinel是Redis提供的 高可用实现方案,在生产环境中对提高系统高可用性非常有帮助。

  • 当主节点出现故障时,哨兵能够自动完成故障的发现和故障的转移,并通知应用方,从而实现真正的高可用.
  • 哨兵最主要的核心功能 就是监控,自动故障转移,通知新的主节点到客户端.
  • Redis Sentinel是一个 分布式架构,其中包含若干个 Sentinel 节点和 Redis 数据节点,每个Sentinel节点会对数据节点和其余 Sentinel节点进行监控,当它发现节点不可达时,会对节点做下线表示。
  • 如果下线的是主节点,它还会和其他的 Sentinel 节点进行协商,当大多数 Sentinel 节点对主节点不可达这个结论达成共识之后,它们会在内部选举出一个领导节点来完成自动故障转移的工作,同时将这个变化实时通知给 Redis 应用方。
  • 整个过程是完全自动的,不需要人工介入。

整体的架构如图所示:

哨兵节点的作用与配置

Redis Sentinel 是独立的 redis-sentinel 进程,系统中通常配置多个哨兵节点来共同监控数据存储节点(包括主节点和从节点)。部署多个哨兵节点的主要目的是为了增强系统的健壮性和可靠性:

  1. 防止哨兵节点自身宕机
    • 如果只有一个哨兵节点,一旦该节点故障,则无法继续监控数据节点的状态。这将导致在数据节点发生故障时,无法自动进行恢复。
  1. 防止误判数据节点故障
    • 单个哨兵节点可能会由于网络抖动、延迟或丢包等问题而误判数据节点故障。多个哨兵节点可以相互验证,减少误判的可能性。
监控与心跳检测
  • 心跳检测机制:哨兵节点通过与数据存储节点建立 TCP长连接,并定期发送心跳包以确保数据节点处于运行状态。
    • 如果从节点挂掉,影响较小,因为可以从主节点重新同步数据。
    • 主节点挂掉则需要哨兵节点介入,启动故障恢复流程。
⭕故障恢复流程

当主节点无响应时,多个哨兵节点之间的交互过程如下:

  1. 共识达成多个哨兵节点向主节点发送心跳包,若主节点持续无响应,则各哨兵节点之间达成“主节点已挂”的共识。
  2. 选举Leader:在这些哨兵节点中,会通过 选举算法(如Raft)选出一个 Leader哨兵节点。
  3. 选择新主节点:由Leader负责 从现有的从节点中挑选一个作为新的主节点。
  4. 执行故障转移
    • Leader控制被选中的节点执行SLAVEOF NO ONE命令,使其成为新的主节点。
    • 控制其他从节点修改其SLAVEOF配置到新的主节点上。

5 . 通知客户端:哨兵节点会自动通知客户端程序有关新的主节点信息,确保后续写操作针对新的 主节点进行。


Docker 部署 Redis Sentinel

场景介绍
  • 在理想情况下,Redis Sentinel 的六个节点应该部署在六台不同的服务器上。然而,在实际操作中,我们可能没有足够的物理服务器资源。
  • 如果我们按照传统的主从复制模式来配置,需要修改每台服务器的端口号、配置文件和数据文件,这不仅配置复杂,而且容易引起端口冲突问题。此外,这种方式与多主机部署存在较大差异。

为了解决这些问题,我们可以 引入Docker 这个非常有用的工具。

Docker 简介

什么是 Docker?

  • 虚拟化技术对比:传统虚拟机通过软件模拟硬件环境,但其对硬件资源消耗较大,这对于资源有限的服务器来说是一个挑战。
  • Docker 特点:Docker可以视为“轻量级”的虚拟机,它提供了类似虚拟机的环境隔离效果,但不会大量占用硬件资源。它使得应用程序可以在几乎任何地方以相同的方式运行。

Docker 核心概念

  • 镜像 (Image):类似于模板或蓝图,包含了应用程序及其所有依赖文件、环境配置等。它是只读的,并且是创建容器的基础。
  • 容器 (Container):基于镜像创建的运行实例,每个容器都是一个独立且隔离的进程空间。镜像与容器 的关系类似于操作系统中的“可执行程序”与“进程”。
Docker 安装

为了简化部署过程并解决资源限制的问题,我们将使用 Docker 和 Docker Compose 来安装和管理 Redis 及其哨兵节点。详情可看博主这两篇前文

[Docker#3] LXC | 详解安装docker | docker的架构与生态

[Docker#11] 容器编排 | .yml | up | 实验: 部署WordPress

以下是安装步骤:

1.安装 Docker 和 Docker Compose

  • Docker 的安装和配置(包括镜像源)相对复杂,建议参考官方文档或相关文章进行详细操作。例如,可以参阅 Docker官方文档 或者其他社区提供的教程。

2.配置 Redis 和 Sentinel

  • 使用 Docker Hub 上现成的 Redis 和 Redis Sentinel 镜像,或者自己构建自定义镜像。
  • 编写 docker-compose.yml 文件来定义服务(如 Redis 主节点、从节点和哨兵节点),并通过 Docker Compose 启动这些服务。

3.启动服务

  • 使用命令 docker-compose up -d 启动所有定义的服务,确保它们在后台以分离模式运行。

4.验证部署

  • 检查各个容器是否正常启动,并验证 Redis 主从复制和哨兵监控功能是否按预期工作。

停止之前的redis主节点和从节点的服务

  • 使用docker获取到redis镜像
    docker pull redis:5.0.9

思考:

yml 和 JSON 都是这种比较直观的键值对结构。

  • JSON 是使用 {} 来表示层级结构,YAML 则是使用缩进来表示。

Docker Compose 编排 Redis 主从及哨兵节点

为了简化 Redis 主从复制和哨兵集群的部署,我们使用 docker-compose.yml 文件来编排容器。该配置文件定义了所有需要创建的容器及其运行参数,允许我们通过一个简单的命令批量启动或停止这些容器。

编排 Redis 主从节点

首先,在 /root/redis/ 目录下创建名为 docker-compose.yml 的文件(注意:文件名必须固定,类似于 Spring 中的 application.yml)。在文件中添加如下内容:

version: '3.7'
services:master:image: 'redis:5.0.9'container_name: redis-masterrestart: alwayscommand: redis-server --appendonly yesports: - 6379:6379slave1:image: 'redis:5.0.9'container_name: redis-slave1restart: alwayscommand: redis-server --appendonly yes --slaveof redis-master 6379ports:- 6380:6379slave2:image: 'redis:5.0.9'container_name: redis-slave2restart: alwayscommand: redis-server --appendonly yes --slaveof redis-master 6379ports:- 6381:6379

字段解释

  • services 下的名称代表每个服务的名字,可以根据需求自定义。
  • ports 字段用于端口映射,如 6380:6379 表示 宿主机的 6380 端口映射到容器内的 6379 端口。
  • command 启动 Redis 的命令行参数,从节点的 --slaveof 参数可以直接使用主节点的服务名,Docker 会自动解析为主节点的 IP 地址。
  • 如果实在是向在后面直接写ip地址的话,也不一定写得上去,这是以为在容器启动之后,会动态分配ip地址,被分配的ip地址是什么,我们自己也不清楚当然,我们可以通过某些手段来配置静态的ip.

该代码完成了三个数据节点的创建,通过命令完成主从关系的配置。执行之前,记得把主机上的redis停止,把637963806381三个端口空出来给docker启动的redis

在目录redis-data中执行:

docker compose up -d

这样就创建好了三个redis服务端,可以通过redis-cli -p 6379redis-cli -p 6380redis-cli -p 6381来验证是否启动成功。

编排 Redis 哨兵节点

为什么要把redis的哨兵和主从节点的配置文件分开创建?

这样做一方面是为了方便观察日志,另一方面是为了确保redis主从节点启动之后再启动哨兵节点,,如果我们把六个容器都配置在一个yml文件中的话,有可能先启动哨兵,日志的执行可能会产生变数,我们分成两组来启动的话,就可以保证上述顺序的正确.

为了便于管理和确保正确的启动顺序,建议将 Redis 哨兵节点的配置与主从节点分开。在 /root/redis-sentinel/ 目录下创建另一个 docker-compose.yml 文件:

version: '3.7'
services:sentinel1:image: 'redis:5.0.9'container_name: redis-sentinel-1restart: alwayscommand: redis-sentinel /etc/redis/sentinel.confvolumes:- ./sentinel1.conf:/etc/redis/sentinel.confports:- 26379:26379networks:- redis-data_defaultsentinel2:image: 'redis:5.0.9'container_name: redis-sentinel-2restart: alwayscommand: redis-sentinel /etc/redis/sentinel.confvolumes:- ./sentinel2.conf:/etc/redis/sentinel.confports:- 26380:26379networks:- redis-data_defaultsentinel3:image: 'redis:5.0.9'container_name: redis-sentinel-3restart: alwayscommand: redis-sentinel /etc/redis/sentinel.confvolumes:- ./sentinel3.conf:/etc/redis/sentinel.confports:- 26381:26379networks:- redis-data_defaultnetworks:default:external:name: redis-data_default

字段解释

  • volumes 用于挂载哨兵配置文件到容器内路径。
  • networks如果没有这个字段,我们在启动redis哨兵的时候,哨兵和数据节点就处于两个局域网中.默认情况下,两个局域网是不互通的.这里我们加入了这个字段,来把redis的数据节点和哨兵节点放入同一个局域网中.
  • 其中我们先需要使用docker network ls查询到redis数据节点的局域网,之后我们把哨兵节点的局域网和数据节点修改成一样的即可.上面我们都修改成了redis-data_default,该节点就是redis数据节点的局域网.


创建哨兵配置文件

在同一目录 (/root/redis-sentinel/) 下创建三个哨兵配置文件 sentinel1.conf, sentinel2.conf, 和 sentinel3.conf,内容相同:

bind 0.0.0.0
port 26379
sentinel monitor redis-master redis-master 6379 2
sentinel down-after-milliseconds redis-master 1000

字段解释

  • bind 0.0.0.0:允许所有网络接口上的连接。
  • port 26379:指定哨兵节点监听的端口号。
  • sentinel monitor redis-master redis-master 6379 2:此行定义了哨兵监控的目标主节点。第一个 redis-master 是哨兵内部使用的名称;第二个 redis-master 是主节点的服务名(Docker会自动解析为主节点的IP地址);6379 是主节点的端口号;2 表示法定票数,即至少需要两个哨兵确认故障才能进行切换。
  • sentinel down-after-milliseconds redis-master 1000:设置哨兵认为主节点不可达的时间阈值为1000毫秒。

启动服务

完成上述配置后,可以通过以下命令启动所有容器:

# 启动Redis主从节点
cd /root/redis/
docker-compose up -d# 启动哨兵节点
cd /root/redis-sentinel/
docker-compose up -d

如果需要停止并删除容器,可以使用 docker-compose down 命令。确保在 docker-compose.yml 文件所在的同级目录中执行这些命令。

启动后,哨兵节点会自动修改配置文件,将其监控的主节点名称解析为实际的 IP 地址,并记录其他哨兵节点的信息。

哨兵节点配置文件的自动修改

启动哨兵节点后,配置文件会被 Docker 自动修改以反映实际运行时的状态。例如,原本的 redis-master 名称被解析为具体的 IP 地址,并添加了其他哨兵节点的信息。修改后的配置文件示例:

可以看到,配置文件中的 redis-master 已经被自动解析成了 IP 地址,并且记录了已知的副本和哨兵节点信息。


问题与解决

从错误信息来看,docker-compose.yml 文件中存在几个问题导致 docker compose up -d 命令无法成功执行。以下是逐步解决这些问题的方法:

1. 更新 Docker Compose 文件格式

警告:version 属性已过时

  • Docker Compose V2(即 docker compose)不再需要 version 字段,因为它会自动使用最新支持的版本。因此,建议移除 version 字段。

警告:networks.default: external.name 已弃用

  • 使用 external: truename 来定义外部网络,而不是 external.name

2. 确保所有服务引用的网络已正确定义

错误:service "sentinel3" refers to undefined network redis-data_default

  • 确保在 docker-compose.yml 中正确地定义了所有服务使用的网络,并且这些网络确实存在于你的环境中。

修改后的 docker-compose.yml 示例

根据上述指导,这里是修改后的 docker-compose.yml 文件示例:

services:sentinel1:image: 'redis:5.0.9'container_name: redis-sentinel-1restart: alwayscommand: redis-sentinel /etc/redis/sentinel.confvolumes:- ./sentinel1.conf:/etc/redis/sentinel.confports:- 26379:26379networks:- redis-data-networksentinel2:image: 'redis:5.0.9'container_name: redis-sentinel-2restart: alwayscommand: redis-sentinel /etc/redis/sentinel.confvolumes:- ./sentinel2.conf:/etc/redis/sentinel.confports:- 26380:26379networks:- redis-data-networksentinel3:image: 'redis:5.0.9'container_name: redis-sentinel-3restart: alwayscommand: redis-sentinel /etc/redis/sentinel.confvolumes:- ./sentinel3.conf:/etc/redis/sentinel.confports:- 26381:26379networks:- redis-data-networknetworks:redis-data-network:external: truename: redis-data_default

验证和创建外部网络

确保外部网络 redis-data_default 已经存在。如果不存在,你可以通过以下命令创建它:

docker network create redis-data_default

检查现有网络

你可以使用以下命令列出所有现有的 Docker 网络,以验证 redis-data_default 是否已经存在:

docker network ls

启动服务

完成以上步骤后,再次尝试启动服务:

docker compose up -d

注意事项

如果你之前有运行过的容器或网络,可能需要先清理它们,以避免冲突。

  • 确保你在正确的目录中执行命令,即包含 docker-compose.yml 文件的目录。
  • 如果仍然遇到问题,请检查 Docker 和 Docker Compose 的日志输出,或者提供更详细的错误信息以便进一步诊断。


选举机制(常考)

——解决监控主机宕机问题

哨兵存在的意义在于能够在 Redis 主从结构出现问题时(如主节点挂掉),自动选举一个新的主节点来代替故障的主节点,从而保证整个 Redis 系统仍然可用。

主节点选举过程

主节点的选举过程可以分为几个关键步骤:

1. 判断 主观下线

  • 哨兵节点通过给 Redis 服务器发送心跳包来判定服务器是否正常工作。
  • 如果心跳包没有得到响应,当前哨兵节点会认为该服务器已挂掉。但此时只是单个哨兵节点的主观判断。

2. 判断客观下线

  • 当 多个 哨兵节点通过投票确认服务器确实挂掉,并且票数 超过了在配置文件中设定的法定票数时,所有哨兵节点达成一致意见,认为服务器确实已宕机。

3. 选取哨兵Leader

  • 多个哨兵节点需要通过 Raft 算法选举出一个 Leader 节点,负责从现有从节点中提拔新的主节点。
  • 简而言之,Raft 算法的核心就是"先下手为强" 谁率先发出了拉票请求,谁就有更大的概率成为 leader,这里的决定因素成了 "网络延时"。

Raft 算法:

  1. 每个哨兵节点都给其他所有哨兵节点发起一个拉票请求"
  2. 收到拉票请求的节点,会回复一个投票响应,当哨兵节点收到多个拉票请求只对第一个节点投票,后续节点都不投票
  3. 一轮投票完成之后,发现得票超过半数的节点,自动成为 leader 如果出现平票的情况,就重新再投一次即可。

因此建议哨兵节点设置成奇数,如果是偶数个,则增大了平票的概率,带来不必要的开销。

最终leader 节点负责挑选一个 slave 成为新的 master 当其他的 sentenal发现新的 master 出现了,就说明选举结束了。

4.Leader 提拔新主节点

  • ⭕提拔原则
    • 优先级:每个 Redis 数据节点在配置文件中都有一个 slave-priority 设置,优先级越高越可能被选中。
    • 数据复制偏移量 (offset):偏移量越大表示该从节点与原主节点的数据同步程度越高,更接近最新的数据状态,因此 优先考虑 offset 较大的节点。
    • runid:如果上述条件相同,则随机挑选一个节点。runid 是每个 Redis 节点启动时自动生成的一串随机数字。

5. 设置新主节点

  • Leader 控制选定的节点执行 SLAVEOF NO ONE 命令,使其成为新的主节点。
  • 接着,Leader 再控制其他从节点执行 SLAVEOF <newMasterIp> <newMasterPort> 命令,让它们跟随新的主节点进行数据同步。

实验

现在通过docker关掉master的容器,来模拟主节点崩溃:

输出:

在日志中,vote-for-leader就是在投票选举leader哨兵。

这是第二个哨兵的日志

  • sdown master:这代表哨兵节点发现了master节点掉线,sdown表示主观认为,也就是说哨兵还不能保证master一定掉线
  • odown master:经过与其它哨兵交流,多个哨兵都认为master节点掉线,odown表示客观认为,#quorum 3/2表示法定票数为2票,目前有三个哨兵都投票认为master掉线
  • switch-master:切换主节点,此时已经有新的节点变成主节点了

进入6380端口的数据节点,输入info replication

可以看到role:master6380成为了新的主节点,当然也有可能是6381

尝试重启redis-master

这个redis-master重启后,就变成了从节点,不再是主节点了。

⭕总结:

  1. 主观下线 sdown:单个哨兵节点认为主节点掉线
  2. 客观下线 odown:投票后客观认为主节点掉线
  3. 选取哨兵leader:依据网络情况,选出一个哨兵成为leader,由leader完成选举master
  4. 选举master:由leader依据优先级,数据同步进度,run id来选出一个节点成为master
  5. 重构主从关系:由leader哨兵,指定数据节点执行指令,重构主从关系
注意事项
  • 哨兵节点数量:建议哨兵节点为奇数个,以避免在投票选举 Leader 时出现平票情况。
  • 哨兵职责:哨兵不负责存储数据,仅用于监控和故障恢复。
  • 数据丢失风险:哨兵模式不能完全防止极端情况下写数据丢失的问题,例如,在数据未完全同步到从节点前主节点就宕机了,这种情况下丢失的数据将无法恢复。
  • 存储容量:哨兵模式不会提高数据的存储容量,它主要关注的是高可用性和故障转移。
  • 哨兵节点 可以使用一些 配置不高的机器来部署

Redis 的主从复制模式可以将主节点的数据改变同步给从节点,这样从节点就可以起到两个作用:

  1. 作为主节点的一个备份,一旦主节点出了故障不可达的情况,从节点可以作为后备,并且保证数据尽量不丢失(主从复制表现为最终一致性)。
  2. 从节点可以分担主节点上的读压力,让主节点只承担写请求的处理,将所有的读请求负载均衡到各个从节点上。

但是主从复制模式并不是万能的,它同样遗留下以下几个问题:

  1. 主节点发生故障时,进行主备切换的过程是复杂的,需要完全的人工参与,导致故障恢复时间无法保障。
  2. 主节点可以将读压力分散出去,但 写压力/存储压力是无法被分担的,还是受到单机的限制。

其中第一个问题是高可用问题,即 Redis 哨兵主要解决的问题。第二个问题是属于存储分布式的问题,留给 Redis 集群去解决,本篇博客集中讨论了第一个问题,下一篇将对第二个问题进行讨论~

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

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

相关文章

网站打开速度测试工具:互联网优化的得力助手

在信息飞速流转的互联网时代&#xff0c;网站如同企业与用户对话的窗口&#xff0c;其打开速度直接关乎用户体验&#xff0c;乃至业务的成败。所幸&#xff0c;一系列专业的网站打开速度测试工具应运而生&#xff0c;它们宛如幕后的技术侦探&#xff0c;精准剖析网站性能&#…

字节高频算法面试题:小于 n 的最大数

问题描述&#xff08;感觉n的位数需要大于等于2&#xff0c;因为n的位数1的话会有点问题&#xff0c;“且无重复”是指nums中存在重复&#xff0c;但是最后返回的小于n最大数是可以重复使用nums中的元素的&#xff09;&#xff1a; 思路&#xff1a; 先对nums倒序排序 暴力回…

基于springboot+vue实现的农场管理平台 (源码+L文+ppt)4-110

第四章 系统设计 4.1 系统总体结构设计 本系统是基于B/S架构的网站系统&#xff0c;分为系统前台和系统后台&#xff0c;前台主要是提供给注册用户和未注册登录的游客使用的&#xff0c;包括网站首页、农业生产资料、农业质量方法、农业种植计划、农业新闻、通知公告、在线咨…

最长最短单词

最长最短单词 C语言实现C实现Java实现Python实现 &#x1f490;The Begin&#x1f490;点点关注&#xff0c;收藏不迷路&#x1f490; 输入1行句子&#xff08;不多于200个单词&#xff0c;每个单词长度不超过100&#xff09;&#xff0c;只包含字母、空格和逗号。单词由至少一…

时频转换 | Matlab梅尔频谱图Mel spectrogram一维数据转二维图像方法

目录 基本介绍程序设计参考资料获取方式 基本介绍 时频转换 | Matlab梅尔频谱图Mel spectrogram一维数据转二维图像方法 程序设计 clear clc % close all load 130.mat % 导入数据 x X130_DE_time; % 本数据只选择5120个点进行分析 x x(1:120000,:); fs 12000 ; % 数据…

蓝牙键鼠无法被电脑识别

起因是我的键鼠是三模的&#xff0c;但是我蓝牙模式我只用过几次&#xff0c;基本一直使用的是有线模式&#xff0c;最近突然要用无线连接&#xff0c;如果使用收发器就显得过于繁琐&#xff0c;还占用usb口&#xff0c;因此想用蓝牙连&#xff0c;但是由于 win10更新了英特尔…

网络命令配置

随笔记录 目录 1. 背景介绍 2. 配置网络命令空间 3 验证 3.1 未网络命令空间外网卡配置IP 3.2 验证配置 3.2.1 在网络命令空间外接口启动iperf3 3.2.2 网络命令空间内启动iperf3 client 1. 背景介绍 2. 配置网络命令空间 1. 配置前[rootlocalhost SDK-V1.10.1.7]# ip…

Megatron 和 deepspeed 大模型训练框架

文章目录 相同点不同点开发团队&#xff1a;专长领域&#xff1a;GPU优化&#xff1a;功能特性&#xff1a;框架支持&#xff1a; 优势比较Megatron优势&#xff1a;DeepSpeed优势&#xff1a;Megatron训练框架最主要的特点、优缺点优点:缺点: 扩展对比深入探究其他训练框架各种…

STM32进阶 定时器3 通用定时器 案例1:LED呼吸灯——PWM脉冲

功能 它有基本定时器所有功能&#xff0c;还增加以下功能 TIM2、TIM3、TIM4、TIM5 多种时钟源&#xff1a; 外部时钟源模式1&#xff1a; 每个定时器有四个输入通道 只有通道1和通道2的信号可以作为时钟信号源 通道1 和通道2 的信号经过输入滤液和边缘检测器 外部时钟源…

详解Vue设计模式

详解 vue 设计模式 ​ Vue.js 作为一个流行的前端框架&#xff0c;拥有许多设计模式&#xff0c;这些设计模式帮助开发者更好地组织和管理代码&#xff0c;提升代码的可维护性、可扩展性和可读性。Vue 设计模式主要体现在以下几个方面&#xff1a; 1. 组件化设计模式 (Compon…

Tomcat使用教程

下载地址&#xff1a;https://tomcat.apache.org/ 配置环境变量 变量名: CATALINA_HOME 变量值: D:\tools\apache-tomcat-9.0.97 Path: %CATALINA_HOME%\bin 启动Tomcat(打开命令提示符) startup.bat 解决乱码问题(打开conf\logging.properties) java.util.logging.Conso…

免押租赁系统助力资源共享新模式开创便捷租赁体验

内容概要 免押租赁系统&#xff0c;听起来是不是很酷&#xff1f;这个新模式不仅仅是为了让你少花点钱&#xff0c;它的到来简直就是个革命&#xff01;以前&#xff0c;租东西时首先想到的就是那个令人心痛的押金&#xff0c;对吧&#xff1f;但现在&#xff0c;免押租赁系统…

17. Threejs案例-Three.js创建多个立方体

17. Threejs案例-Three.js创建多个立方体 实现效果 知识点 WebGLRenderer (WebGL渲染器) WebGLRenderer 是 Three.js 中用于渲染 WebGL 场景的核心类。它负责将场景中的对象渲染到画布上。 构造器 new THREE.WebGLRenderer(parameters) 参数类型描述parametersObject可选…

【kettle】mysql数据抽取至kafka/消费kafka数据存入mysql

目录 一、mysql数据抽取至kafka1、表输入2、json output3、kafka producer4、启动转换&#xff0c;查看是否可以消费 二、消费kafka数据存入mysql1、Kafka consumer2、Get records from stream3、字段选择4、JSON input5、表输出 一、mysql数据抽取至kafka 1、表输入 点击新建…

如何让谷歌外链看起来更真实?

在SEO优化过程中&#xff0c;外链的自然性往往会被忽视&#xff0c;尤其是在一些急于见效的策略中&#xff0c;外链往往集中在高权重的少数几个网站上&#xff0c;导致外链结构单一且缺乏多样性。这样的外链网络容易让搜索引擎怀疑其真实性&#xff0c;进而影响网站排名。如何才…

【Qt移植LVGL】QWidget手搓LVGL软件仿真模拟器(非直接运行图形库)

【Qt移植LVGL】QWidget手搓LVGL软件仿真模拟器&#xff08;非直接运行图形库&#xff09; 打包开源地址&#xff1a; Qt函数库gitee地址 更新以gitee为准 移植后的demo工程&#xff1a; gitee 有些没实现的 后续我会继续优化 文章目录 别碰瓷看清楚&#xff1a;是移植&#…

Spring Data Elasticsearch

简介说明 spring-data-elasticsearch是比较好用的一个elasticsearch客户端&#xff0c;本文介绍如何使用它来操作ES。本文使用spring-boot-starter-data-elasticsearch&#xff0c;它内部会引入spring-data-elasticsearch。 Spring Data ElasticSearch有下边这几种方法操作El…

JavaWeb学习(3)(Servlet详细、Servlet的三种实现方式(面试)、Servlet的生命周期、传统web.xml配置Servlet(了解))

目录 一、Servlet详细。 &#xff08;1&#xff09;基本介绍。 &#xff08;2&#xff09;基本作用。 1、接收客户端请求数据。 2、处理请求。 3、完成响应结果。 二、Servlet的三种实现方式。 &#xff08;1&#xff09;实现javax.servlet.Servlet接口。 1、基本介绍。 2、代码…

如何利用内链策略提升网站的整体权重?

内链是谷歌SEO中常常被低估的部分&#xff0c;实际上&#xff0c;合理的内链策略不仅能帮助提升页面间的关联性&#xff0c;还可以增强网站的整体权重。通过正确的内链布局&#xff0c;用户可以更流畅地浏览你的网站&#xff0c;谷歌爬虫也能更快地抓取到更多页面&#xff0c;有…

jeecg-uniapp 跨域问题解决方法记录

今天折腾这个很恶心的问题,工作需要经验才行,根本没有什么技术难点,都是经验而已 问题在此 发现没有替换掉前缀 :8085/#/pages/login/login:1 Access to XMLHttpRequest at http://192.168.152.32:8194/h5api/api/user/login from origin http://localhost:8085 has been bloc…