Redis 7.x哨兵模式如何实现?基于Spring Boot 3.x版
大家好,我是袁庭新。
在Redis主从复制模式中,因为系统不具备自动恢复的功能,所以当主服务器(master)宕机后,需要手动把一台从服务器(slave)切换为主服务器。在这个过程中,不仅需要人为干预,而且还会造成一段时间内服务器处于不可用状态,同时数据安全性也得不到保障,因此主从模式的可用性较低,不适用于线上生产环境。
为了解决这一问题,Redis引入了哨兵模式。就是为了让它更靠谱、不容易出问题。你想啊,如果Redis的主服务器突然挂了,那整个服务不就断了嘛?但有了哨兵模式,就相当于有了个小管家,它会时刻盯着Redis服务器们,看谁不对劲儿。下面就来给大家系统的介绍Redis的哨兵模式。
1 哨兵模式介绍
Sentinel是Redis的高可用性的解决方案。由一个或多个Sentinel实例组成的Sentinel系统可以监视任意多个主服务器,以及所有从服务器,并在被监视的主服务器进入下线状态时,Sentinel会自动将下线主服务器属下的某个从服务器升级为新的主服务器,然后由新的主服务器代替已下线的主服务器继续处理命令请求。
Redis哨兵模式是一种特殊的模式,Redis为其提供了专属的哨兵命令,它是一个独立的进程,能够独立运行。哨兵模式的结构如下图所示。
Redis哨兵模式的作用如下:
- 监控:哨兵节点会以每30秒一次的频率对每个Redis节点发送PING命令,并通过Redis节点的回复来判断其运行状态。
- 自动故障恢复:当哨兵监测到主服务器发生故障时,会自动在从节点中选择一台机器,并将其提升为主服务器,当故障实例恢复后也以新的master为主。
- 通知:Sentinel充当Redis客户端的服务发现来源,当集群发生故障转移(Failover)时,会将最新信息通过PubSub发布订阅模式推送给Redis的客户端以及其他的从节点。
2 哨兵模式原理
2.1 集群监控原理
Sentinel基于心跳机制监测服务状态,每隔30秒向集群的每个实例发送PING命令。
2.1.1 主观下线
主观下线,适用于主服务器和从服务器。如果在规定的时间内(配置参数down-after-milliseconds),Sentinel节点没有收到目标服务器的有效回复(Sentinel基于心跳机制监测服务状态),则判定该服务器为“主观下线”。例如Sentinel-1向主服务发送PING命令,在规定时间内没收到主服务器PONG回复,则Sentinel-1判定主服务器为“主观下线”。
2.1.2 客观下线
客观下线,只适用于主服务器。Sentinel-1发现主服务器出现了故障,它会通过相应的命令,询问其它Sentinel节点对主服务器的状态判断。如果超过指定数量(配置参数quorum)的Sentinel节点认为主服务器down掉(主观下线),则Sentinel-1节点判定主服务为“客观下线”。quorum值最好超过Sentinel实例数量的一半。
2.2 集群故障恢复原理
投票选举(底层使用的是Raft算法),所有Sentinel节点会通过投票机制,按照谁发现谁去处理的原则,例如是由Sentinel-1发现的,则选举Sentinel-1为领头节点去做Failover(故障转移)操作;Sentinel-1节点则按照一定的规则在所有从节点中选择一个最优的作为主服务器,然后通过发布订功能通知其余的从节点(slave)更改配置文件,跟随新上任的主服务器(master)。至此就完成了主从切换的操作。
一旦发现master故障,Sentinel需要在salve中选择一个作为新的master。选择依据见下:
- 首先会判断slave节点与master节点断开时间长短,如果超过指定值(down-after-milliseconds * 10)则会排除该slave节点。
- 然后判断slave节点的slave-priority值,越小优先级越高,如果是0则永不参与选举。
- 如果slave-prority一样,则判断slave节点的offset值,越大说明数据越新,优先级越高。
- 最后是判断slave节点的运行id大小,越小优先级越高。
当选出一个新的master后(假设选举的是salve1节点),该如何实现切换呢?流程如下:
- Sentinel给备选的slave1节点发送"REPLICAOF NO ONE"命令,让该节点成为master。
- Sentinel给所有其它slave节点发送"REPLICAOF 192.168.230.132 6379"命令,让这些slave成为新master的从节点,开始从新的master上同步数据。
- 最后,Sentinel将故障节点标记为slave,当故障节点恢复后会自动成为新的master的slave节点。
对上述过程可简要概述为,Sentinel负责监控主从节点的“健康”状态。当主节点挂掉时,自动选择一个最优的从节点切换为主节点。客户端来连接Redis集群时,会首先连接Sentinel,通过Sentinel来查询主节点的地址,然后再去连接主节点进行数据交互。当主节点发生故障时,客户端会重新向Sentinel要地址,Sentinel会将最新的主节点地址告诉客户端。因此应用程序无需重启即可自动完成主从节点切换。
3 搭建哨兵模式集群
这里我们搭建一个三节点形成的Sentinel哨兵模式集群,来监控之前的Redis主从复制模式集群。
Redis哨兵模式集群搭建设计,信息如下表所示。
主机名 | IP地址 | Redis服务/Sentinel服务 | 角色 |
node1 | 192.168.230.131 | 192.168.230.131:6379 | master |
node2 | 192.168.230.132 | 192.168.230.132:6379 | slave |
node3 | 192.168.230.133 | 192.168.230.133:6379 | slave |
node1 | 192.168.230.131 | 192.168.230.131:26379 | sentinel |
node2 | 192.168.230.132 | 192.168.230.132:26379 | sentinel |
node3 | 192.168.230.133 | 192.168.230.133:26379 | sentinel |
在Redis的安装目录下(/usr/local/src/redis-7.2.5),有一个sentinel.conf配置文件,该文件专门用于配置哨兵模式的相关参数信息。文件中用于配置Redis哨兵模式最核心的一个参数是monitor,其语法格式见下。
# 默认值:sentinel monitor mymaster 127.0.0.1 6379 2
sentinel monitor <master-name> <ip> <redis-port> <quorum>
上述语句的含义是,让Sentinel去监控一个地址为ip:redis-port的主服务器。对该命令中涉及到的几个参数做如下的说明。
参数 | 作用 |
master-name | 被监控主机名,被监控主机名的命名由开发者进行自定义。主名称不应包含特殊字符或空格。 |
ip | 主节点Redis服务IP地址。 |
redis-port | 主节点Redis服务端口。 |
quorum | 票数,只有在至少quorum个Sentinel同意的情况下才将其视为O_DOWN(Objectively DOWN)状态。即表示当有多少个Sentinel认为主服务器宕机时,它才算真正的宕机掉,通常数量为半数或半数以上才会认为主机已经宕机,quorum需要根据Sentinel的数量设置。 |
3.1 搭建主从复制模式
接下来,我们在三台虚拟机中使用主从复制模式搭建一个拥有三台服务器的Redis集群,具体操作步骤见下。
1.将三台Redis服务器的redis.conf配置文件(/usr/local/src/redis-7.2.5/redis.conf)做以下参数的配置。
# 允许访问的地址,默认是“bind 127.0.0.1 -::1”,会导致只能在本地访问。修改为“bind 0.0.0.0 -::1”则可以在任意IP访问,生产环境不要设置为“bind 0.0.0.0 -::1”
bind 0.0.0.0 -::1
# 守护进程,修改为yes后即可后台运行,默认值为no
daemonize yes
# 保护模式,no表示关闭保护模式,默认值为yes
protected-mode no
# 密码,设置后redis-cli访问必须输入密码,默认没有配置密码
requirepass 123456
2.在mater主机和两个slave从机的redis.conf配置文件,添加复制同步的密码参数配置,即master主机的requirepass参数的取值。该配置项必须添加,否则主机将拒绝从机请求。
# 配置复制同步密码(即master主机的requirepass参数的取值)
masterauth 123456
3.按照顺序逐一启动三台Redis服务器,并通过客户端连接到Redis服务。
# 检测6379端口是否在监听
$ netstat -lntp | grep 6379
# 进入Redis安装目录
$ cd /usr/local/src/redis-7.2.5
# 指定配置文件启动redis服务
$ redis-server redis.conf
$ redis-cli -h 127.0.0.1 -p 6379 -a 123456
4.依次查看三台Redis服务器的信息,发现三台Redis服务器的角色都是master。
127.0.0.1:6379> info replication
5.然后将第二台和第三台Redis服务器设置成192.168.230.131的从服务器。
127.0.0.1:6379> REPLICAOF 192.168.230.131 6379
OK
6.查看master主机的信息,发现此时有两台slave从机连接在master主机上,日志信息如下所示。
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.230.132,port=6379,state=online,offset=14,lag=1
slave1:ip=192.168.230.133,port=6379,state=online,offset=14,lag=1
master_failover_state:no-failover
master_replid:8d667e34232c22c8a145bfa36eea058e876b5f6a
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:14
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:14
3.2 配置Sentinel哨兵模式
1.实际开发当中,不要直接修改sentinel.conf文件,在三台主机上我们先将这个配置文件备份一份。
$ cp sentinel.conf sentinel.conf.backup
2.分别在三台Redis服务器的sentinel.conf文件中,添加下面的配置内容。
# 守护进程,修改为yes后即可后台运行,默认值为no
daemonize yes
# 让Sentinel去监控一个地址为ip:port的主服务器
sentinel monitor mymaster 192.168.230.131 6379 2
# 若主服务器设置了密码,则哨兵必须也配置密码,否则哨兵无法对主从服务器进行监控,该密码与主服务器密码相同
sentinel auth-pass mymaster 123456
auth-pass命令用于设置用于与master主服务器和slave从服务器进行身份验证的密码。需要注意的是,master密码也用于slave,因此如果你想使用Sentinel监视这些实例,则无法在master实例和slave实例中设置不同的密码。
默认情况下,Redis Sentinel不作为守护进程运行。如果需要,请使用“yes”。请注意,Redis在守护进程化时会在/var/run/Redis-sentinel.pid中写入一个pid文件。
3.3 启动Sentinel哨兵模式
1.在三台服务器上,按照顺序逐一启动Sentinel哨兵,命令见下。
$ redis-sentinel sentinel.conf
2.在第一台Redis机器(192.168.230.131)上执行添加字符串操作并查看键的值。
127.0.0.1:6379> SET city xian
OK
127.0.0.1:6379> GET city
"xian"
3.然后在第二台和第三台Redis机器上,查看对应city键的值便可获取到,如下所示。
127.0.0.1:6379> GET city
"xian"
至此,Redis Sentinel哨兵模式的集群搭建完毕,同时启动了Sentinel哨兵集群。此时,就算主服务器挂了,该集群仍然可以正常运转。
3.4 停止主服务器服务
下面模拟主服务意外宕机的情况,首先直接将主服务器的Redis服务终止,然后查看从服务器是否被提升为了主服务器。具体操纵演示步骤见下。
1.关闭Redis主服务器master(192.168.230.131),执行以下命令。
127.0.0.1:6379> SHUTDOWN
(0.75s)
not connected> EXIT
2.在192.168.230.132机器上,查看Redis主从复制的集群信息。通过查询结果发现,该从服务器将192.168.230.133服务器做为master连接。
127.0.0.1:6379> info replication
Error: Server closed the connectionnot connected> info replication
# Replication
role:slave
master_host:192.168.230.133
master_port:6379
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_read_repl_offset:109506
slave_repl_offset:109506
slave_priority:100
slave_read_only:1
replica_announced:1
connected_slaves:0
master_failover_state:no-failover
master_replid:5719a81cea24fba3fad543bbbe4467a5ba7abcd4
master_replid2:f3b539f424774450b26de565fb92502737f108b4
master_repl_offset:109506
second_repl_offset:105831
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:15
repl_backlog_histlen:109492
3.在192.168.230.133机器上,查看Redis主从复制的集群信息。通过查询结果发现,才服务器的角色从原来的slave变成了master,且192.168.230.132变成了它的的从服务器。
127.0.0.1:6379> info replication
Error: Server closed the connectionnot connected> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=192.168.230.132,port=6379,state=online,offset=113435,lag=1
master_failover_state:no-failover
master_replid:5719a81cea24fba3fad543bbbe4467a5ba7abcd4
master_replid2:f3b539f424774450b26de565fb92502737f108b4
master_repl_offset:113435
second_repl_offset:105831
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:15
repl_backlog_histlen:113421
在Redis集群中开启哨兵模式后,如果主服务器master宕机,此时所有的从服务器slave在后台会自动发起激烈的投票,重新选出新的主服务器master。这就是开启哨兵模式后所发挥的作用。
思考问题:假设此时192.168.230.131机器(原来的主服务器)恢复正常运行状态,那么集群环境的状态将会怎样?
4.重新启动192.168.230.131机器的Redis服务。
[root@node1 redis-7.2.5]# redis-server redis.conf
[root@node1 redis-7.2.5]# redis-cli -h 127.0.0.1 -p 6379 -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> KEYS *
Error: Server closed the connection
not connected> KEYS *
1) "city"
5.查看192.168.230.131机器的Redis信息并观察日志的输入内容。
- 重新归来的Redis服务启动成功后,立刻查看此台机器的Redis服务信息,发现角色为master。
- 几秒后再次查看当前机器的Redis服务信息,此时发现角色变成slave。原因是在Redis集群中开启了哨兵模式,哨兵检测到有新的Redis服务器被启动,立刻将该Redis服务拉入到现有的集群中以从服务器的身份加入。
127.0.0.1:6379> info replication
# Replication
role:slave
master_host:192.168.230.133
master_port:6379
master_link_status:up
master_last_io_seconds_ago:0
master_sync_in_progress:0
slave_read_repl_offset:182056
slave_repl_offset:182056
slave_priority:100
slave_read_only:1
replica_announced:1
connected_slaves:0
master_failover_state:no-failover
master_replid:5719a81cea24fba3fad543bbbe4467a5ba7abcd4
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:182056
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:168030
repl_backlog_histlen:14027
哨兵模式也是有缺点的,由于所有的写操作都是在master上完成的,然后再同步到slave上,因此两台机器之间通信会有延迟。当系统很繁忙的时候,延迟问题会加重;slave机器数量增加,问题也会加重。
4 RedisTemplate连接Sentinel
在Sentinel集群监管下的Redis主从集群,其节点会因为自动故障转移而发生变化,Redis的客户端必须感知这种变化,及时更新连接信息。Spring的RedisTemplate底层利用Lettuce实现了节点的感知和自动切换。
下面我们通过一个测试示例来实现RedisTemplate集成Sentinel哨兵机制,具体实现步骤见下。
4.1 基础环境搭建
1.创建Spring Boot项目。使用Spring Initializr方式创建一个名为springboot-cache-demo的Spring Boot项目,效果如下图所示。
2.引入相关依赖。在项目的pom.xml文件中添加Web模块中的Spring Data Redis依赖启动器、Spring Web依赖、Lombok依赖,以及Spring Boot单元测试依赖,示例代码如下。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.2.8</version><relativePath/></parent><groupId>com.ytx</groupId><artifactId>redis-advanced-demo</artifactId><version>0.0.1-SNAPSHOT</version><name>redis-advanced-demo</name><description>redis-advanced-demo</description><url/><licenses><license/></licenses><developers><developer/></developers><scm><connection/><developerConnection/><tag/><url/></scm><properties><java.version>21</java.version></properties><dependencies><!-- Spring Data Redis依赖启动器 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build>
</project>
3.在项目的resources目录下新建全局配置文件application.yml,并编写对应的日志级别的配置。
logging:level:io.lettuce.core: debugpattern:dateformat: MM-dd HH:mm:ss:SSS
4.编写Web访问层类。在项目中创建名为com.ytx.controller的包,并在该包下创建一个名为HelloRedisController的控制器类。
package com.ytx.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;@RestController
public class HelloRedisController {@Autowiredprivate StringRedisTemplate redisTemplate;@GetMapping("/set/{key}/{value}")public String hi(@PathVariable String key, @PathVariable String value) {redisTemplate.opsForValue().set(key, value);return "success";}@GetMapping("/get/{key}")public String hi(@PathVariable String key) {return redisTemplate.opsForValue().get(key);}
}
4.2 配置Sentinel
1.配置Redis Sentinel的连接信息。在项目的全局配置文件application.yml中添加Redis数据库服务器的连接配置,示例代码如下。
spring:data:redis:sentinel:master: mymasternodes: # 指定Redis的Sentinel哨兵集群相关信息- 192.168.230.131:26379- 192.168.230.132:26379- 192.168.230.133:26379password: 123456 # Redis密码
2.接下来我们在项目中创建名为com.ytx.config的包,在该包下创建一个Redis自定义配置类RedisConfig,示例代码如下。
package com.ytx.config;
import io.lettuce.core.ReadFrom;
import org.springframework.boot.autoconfigure.data.redis.LettuceClientConfigurationBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/** 定义一个Redis配置类 */
@Configuration
public class RedisConfig {/** 配置读写分离 */@Beanpublic LettuceClientConfigurationBuilderCustomizer clientConfigurationBuilderCustomizer() {return clientConfigurationBuilder -> clientConfigurationBuilder.readFrom(ReadFrom.REPLICA_PREFERRED);}
}
在上述代码中,使用了io.lettuce.core.ReadFrom类,该类中提供了对Redis的读写策略,具体介绍见下表。
属性 | 作用 |
MASTER | 从主节点读取。 |
MASTER_PREFERRED | 优先从master节点读取,master不可用才读取replica。 |
REPLICA | 从slave(replica)节点读取。 |
REPLICA _PREFERRED | 优先从slave(replica)节点读取,所有的slave都不可用才读取master。 |
3.启动项目,项目启动成功后,通过浏览器访问http://localhost:8080/set/country/China向Redis数据库中插入一条数据,结果如下图所示。
4.然后在通过浏览器访问http://localhost:8080/get/country查询key为country的数据,结果如下图所示。
5 总结
Redis哨兵模式是一种提高其高可用性的解决方案。在Redis主从复制模式中,主服务器宕机需要手动切换从服务器,导致服务不可用和数据安全风险。哨兵模式通过引入哨兵节点来自动监控和管理Redis集群。
哨兵节点会定期向Redis节点发送PING命令,判断其运行状态。当主服务器出现故障时,哨兵节点会自动选择一个从服务器升级为新的主服务器,并通知其他节点更新配置,实现自动故障转移。这个过程包括投票选举最优从服务器、发送命令让其成为新主服务器,并调整其他从服务器的配置。
哨兵模式还具备通知功能,当发生故障转移时,会将最新信息推送给Redis客户端和其他从节点。这种模式简化了系统管理,降低了人为干预的风险,提升了Redis集群的可靠性和稳定性。总的来说,Redis哨兵模式让Redis服务更加可靠和稳定,保障了业务的连续性。
相关文章:

Redis 7.x哨兵模式如何实现?基于Spring Boot 3.x版
大家好,我是袁庭新。 在Redis主从复制模式中,因为系统不具备自动恢复的功能,所以当主服务器(master)宕机后,需要手动把一台从服务器(slave)切换为主服务器。在这个过程中࿰…...

解决QTCreator在Debug时无法显示std::string类型的问题
环境: 操作系统:Ubuntu 20.04.6 LTS QT版本:Qt Creator 4.11.0 问题: Debug时,无法显示std::string类型的值,如下图: 解决方法: 修改/usr/share/qtcreator/debugger/stdtypes.py…...

leetcode 面试经典 150 题:无重复字符的最长子串
链接无重复字符的最长子串题序号3类型字符串解题方法滑动窗口难度中等 题目 给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。 示例 1: 输入: s “abcabcbb” 输出: 3 解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。 …...

0101多级nginx代理websocket配置-nginx-web服务器
1. 前言 项目一些信息需要通过站内信主动推动给用户,使用websocket。web服务器选用nginx,但是域名是以前通过阿里云申请的,解析ip也是阿里云的服务器,甲方不希望更换域名。新的系统需要部署在内网服务器,简单拓扑图如…...

【前端】Jquery拍照,通过PHP将base64编码数据转换成PNG格式,并保存图像到本地
目录 一、需求 二、开发语言 三、效果 四、业务逻辑: 五、web端调用摄像头 六、示例代码 1、前端 2、后端 一、需求 web端使用jquery调用摄像头拍照,并使用PHP把base64编码转换成png格式图片,下载到本地。 由于js不能指定图片存储的…...

websocket再项目中的使用
WebSocket在项目中的使用主要包括以下几个方面: WebSocket的基本概念和原理: 定义:WebSocket是一种基于TCP的协议,实现了浏览器与服务器之间的全双工通信。它通过HTTP/1.1协议的101状态码进行握手,建立连接…...

ajax同步执行async:false无效的解决方法
无效的情况: function ManHourCheck() {var StartDate $("#StartDate").val();//日报日期var EndDate $("#EndDate").val();//完成日期var UserID $("#UserID").val();//员工ID$.ajax({async: false,//加了这一行也没用!!!!!!!!!!…...

基于Qt的登陆界面设计
目标 自由发挥登录界面的应用场景,实现一个登录窗口的界面。 要求:每行代码都要有注释 代码 // 设置窗口大小为600x400像素 this->resize(600,400); // 设置窗口标题为"TheWitcher 巫师3:狂猎" this->setWindowTitle(&qu…...

HarmonyOS 输入框组件:TextInput 和 TextArea 深度解析
输入框组件是移动端开发中最常见的组件之一,常用于响应用户的输入操作,比如评论区的文本输入、聊天框的消息输入、表单内容填写等场景。在 HarmonyOS 中,TextInput 和 TextArea 分别用于单行和多行输入操作。除此之外,它们还可以与…...

【Golang】 Go 语言中的 Struct、JSON 和 Map 互转:详细指南
Go 语言中的 Struct、JSON 和 Map 互转:详细指南 在 Go 语言中,处理 JSON 数据、结构体类型和映射(map)是与 API、配置或数据库交互时非常常见的任务。理解如何在这些数据类型之间无缝转换对于高效的 Go 编程至关重要。以下是如何将 Go 结构体转换为 JSON、将 JSON 转换为…...

Azure Function流式返回
最近用azure function做了一个api和llm交互,需要流式返回。但是默认不支持流返回,搜索了一下。记录。 官方文档:https://techcommunity.microsoft.com/blog/azurecompute/azure-functions-support-for-http-streams-in-python-is-now-in-prev…...

智能座舱进阶-应用框架层-Jetpack主要组件
Jetpack的分类 1. DataBinding:以声明方式将可观察数据绑定到界面元素,通常和ViewModel配合使用。 2. Lifecycle:用于管理Activity和Fragment的生命周期,可帮助开发者生成更易于维护的轻量级代码。 3. LiveData: 在底层数据库更…...

GitLab分支管理策略和最佳实践
分支管理是 Git 和 GitLab 中非常重要的部分,合理的分支管理可以帮助团队更高效地协作和开发。以下是一些细化的分支管理策略和最佳实践: 1. 分支命名规范 • 主分支:通常命名为 main 或 master,用于存放稳定版本的代码。 • …...

【Unity】【VR开发】实现VR屏幕共享应用的几个重要插件和参考资料分享
【背景】 做了一个可以在局域网远程屏幕的VR应用,如果有相同兴趣的朋友也可以参考下我用的几个插件。 【使用或相关的关键插件】 piping server:这个是最基底的插件,基于它实现的信令通信。 https://github.com/nwtgck/piping-server/blob…...

数据结构---------二叉树前序遍历中序遍历后序遍历
以下是用C语言实现二叉树的前序遍历、中序遍历和后序遍历的代码示例,包括递归和非递归(借助栈实现)两种方式: 1. 二叉树节点结构体定义 #include <stdio.h> #include <stdlib.h>// 二叉树节点结构体 typedef struct…...

浏览器引入elasticsearch-head插件
elasticsearch-head插件下载: 链接: https://pan.baidu.com/s/1Dz3aU42HZCNg45iJoDOsMg?pwduvhg 提取码: uvhg 1、打开浏览器设置 2、选择拓展程序 3、选择elasticsearch-head插件下载 4、打开es-head插件 5、修改ip 6、登录...

【ELK】Filebeat采集Docker容器日志
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 介绍filebeat是如何工作的 使用部署filebeat 介绍 Filebeat 是一个用于转发和集中日志数据的轻量级传送器。 Filebeat 作为agent安装在服务器上,监视指…...

异步线程池与CountDownLatch
异步线程池 顾名思义,一个专门用来处理异步任务的线程池。可以避免线程的开销以及非阻塞的执行任务。 CountDownLatch 一个同步工具类,用于 让一个或多个线程等待一组操作完成。 业务场景 支付订单时,用户可以使用多张优惠劵,…...

在图像上显示掩码、框和点的通用函数
在图像上显示掩码、框和点的通用函数 背景介绍函数实现与用途1. 显示掩码函数:`show_mask`2. 显示边界框函数:`show_box`3. 在图像上显示点函数:`show_points`4. 综合显示框和点函数:`show_points_and_boxes_on_image`5. 显示掩码并返回图像函数:`show_mask_on_image`6. 显…...

基于Matlab的变压器仿真模型建模方法(11):三相三绕组换流变压器的建模仿真
1.概述 换流变压器是直流输电系统中的关键设备,主要负责连接交流和直流系统,并实现电能的转换与传输。换流变压器在直流输电系统中的主要用途包括:传送电力:将电能从交流系统传输到直流系统或从直流系统传输到交流系统;电压变换:把交流系统电压变换到换流器所需的换相电压…...

代码随想录算法训练营day46|动态规划part12
今天就结束动态规划章节了,以后还要多加练习。 今天的两道题都很有难度,647回文子串的思路非常巧妙,因为用一维dp数组比较难表示子串的起点和终点,所以需要用二维dp数组表示,dp[i][j]表示以i为起点,j为终点…...

【C语言】头文件
所有学习过C语言的朋友都熟悉这样一段代码: #include <stdio.h>int main(int argc, char *argv[]) {return 0; }那么,你真的了解 <stdio.h> 吗? <stdio…...

蓝桥杯——竞赛省赛国赛题分享
目录 一.[蓝桥杯 2013 省 AB] 错误票据 代码如下: 二.[蓝桥杯 2024 省 Java B] 报数游戏 代码如下: 讲解: 三.[蓝桥杯 2014 国 C] 拼接平方数 代码如下: 四.三步问题(递归,上台阶) 代码…...

企业内训|阅读行业产品运营实战训练营-某运营商数字娱乐公司
近日,TsingtaoAI公司为某运营商旗下数字娱乐公司组织的“阅读行业产品运营实战训练营”在杭州落下帷幕。此次训练营由TsingtaoAI资深互联网产品专家程靖主持。该公司的业务骨干——来自内容、市场、业务、产品与技术等跨部门核心岗位、拥有8-10年实战经验的中坚力量…...

低空无人机产教融合技术详解
低空无人机产教融合技术是将无人机技术与教育、产业深度融合的一种新型教育模式,旨在培养既具备理论知识又具备实践能力的无人机专业人才。以下是对这一技术的详细解析: 一、产教融合的背景与意义 1. 背景: 随着无人机技术的快速发展&#…...

springboot中Controller内文件上传到本地以及阿里云
上传文件的基本操作 <form action"/upload" method"post" enctype"multipart/form-data"> <h1>登录</h1> 姓名:<input type"text" name"username" required><br> 年龄…...

Chrome 132 版本开发者工具(DevTools)更新内容
Chrome 132 版本开发者工具(DevTools)更新内容 一、使用 Gemini 调试 Network、Source 和 Performance Chrome 131 可以使用 Gemini 调试 CSS,现在可以调试更多模块了 与元素面板中的右键菜单类似,要打开 AI 辅助面板并开始与 …...

使用Python从阿里云物联网平台获取STM32温度数据
在物联网(IoT)应用中,设备数据的采集与监控至关重要。本文将详细介绍如何使用Python从阿里云物联网平台获取STM32设备的温度数据。我们将从已有的Java代码出发,逐步将其转换为Python,并处理在过程中遇到的问题…...

Spring Boot 声明式事务
Spring Boot中的声明式事务管理主要通过Transactional注解来实现。以下是Transactional注解的一些关键用法和特性: 1. 启用事务管理 在Spring Boot应用中使用Transactional注解之前,需要在启动类或者配置类上添加EnableTransactionManagement注解来启用事…...

websocket 局域网 webrtc 一对一 多对多 视频通话 的示例
基本介绍 WebRTC(Web Real-Time Communications)是一项实时通讯技术,它允许网络应用或者站点,在不借助中间媒介的情况下,建立浏览器之间点对点(Peer-to-Peer)的连接,实现视频流和&am…...