Redis篇-19--运维篇1-主从复制(主从复制,读写分离,配置实现,实战案例)
1、概述
Redis的主从复制(Master-Slave Replication)是一种数据冗余机制,它允许将一台Redis服务器的数据复制到其他Redis服务器。在主从复制中,有一台主服务器(Master)和一个或多个从服务器(Slave)。主服务器负责写操作,而从服务器可以用于读操作,从而实现读写分离,减轻主服务器的负载压力。
示例图:
2、主从复制中的基本概念
- 主服务器(Master):负责处理写操作(如SET、DEL等),并将这些操作同步给从服务器。
- 从服务器(Slave):只读服务器,默认情况下不允许写操作(可以通过配置修改)。从服务器会定期从主服务器获取最新的数据更新,并保持与主服务器的数据一致。
- 数据流向:数据的复制是单向的,只能由主服务器到从服务器。从服务器不能将数据写回主服务器。
3、主从复制的作用
- 数据冗余:通过主从复制,可以在多台服务器上保存相同的数据副本,提供热备份,防止因单点故障导致数据丢失。
- 故障恢复:当主服务器出现问题时,可以从服务器可以接管服务,确保系统的高可用性。
- 负载均衡:通过读写分离,主服务器处理写操作,从服务器处理读操作,分担主服务器的负载,提升系统的并发处理能力。
- 高可用性基础:主从复制是Redis集群和哨兵(Sentinel)系统的基础,支持自动故障转移和高可用性部署。
4、主从复制的工作原理
Redis的主从复制分为两个主要阶段:
初次同步(全量同步)和命令传播(增量同步)。
(1)、初次同步(Full Resynchronization)
初次同步发生条件:
- 第一次建立主从关系:当从服务器首次连接到主服务器时,需要进行全量同步,以确保从服务器拥有与主服务器完全一致的数据集。
- 部分同步失败:如果从服务器与主服务器之间的连接中断时间过长,导致无法通过部分同步恢复数据一致性,也会触发全量同步。
全量同步(初始同步)的过程:
1、从服务器发起请求:从服务器通过配置文件的slaveof(或replicaof)检查自身需要同步的主节点信息。之后通过PSYNC命令携带replid(唯一身份标识符),offset(处理数据的偏移量)参数向主服务器发起数据同步请求。
2、主服务器确认请求:主服务器会校验从服务器的replid是否存在,不存在即表示第一次同步。主服务器会返回replid和offset和从服务器建立连接。
3、主服务器生成RDB文件:同时,主服务器会在后台执行BGSAVE操作,生成一个RDB快照文件。同时,主服务器会开启一个缓冲区,记录从BGSAVE期间的所有写命令。
4、传输RDB文件:BGSAVE完成后,主服务器将生成的RDB文件发送给从服务器。
5、加载RDB文件:从服务器接收到RDB文件后,会清空本地数据,加载RDB文件,重建与主服务器一致的数据集。
6、重放命令:从服务器加载完RDB文件后,主服务器会将缓冲区中的写命令发送给从服务器,确保数据完全一致。
全量过程原理示例如下:
简单总结:
首次同步是从服务发起,之后RDB文件同步,缓冲区写日志同步,都是主服务主动发起给从服务器的。
(2)、命令传播(Partial Resynchronization)
初次同步完成后,主服务器和从服务器之间会进入命令传播阶段。在这个阶段,主服务器会将所有的写命令实时发送给从服务器,确保两者的数据保持一致。
命令传播(增量同步)的过程:
1、主服务器记录命令:每当主服务器执行写命令时,它会将这些命令记录到一个缓冲区中。
2、从服务器请求命令:从服务器会定期向主服务器发送psync命令,告知主服务器它已经处理到的命令的偏移量offset。
3、主服务器发送命令:主服务器根据从服务器的偏移量offset,将未处理的命令发送给从服务器。
4、从服务器执行命令:从服务器接收到命令后,会立即执行这些命令,确保与主服务器的数据保持一致。
简单总结:
命令传播是从服务发起(携带自己身份和偏移量),主服务根据偏移量获取缓冲区写日志记录,发送给从服务器,这个过程是从服务主动发起数据请求的。
(3)、部分同步(Partial Resynchronization)
Redis从2.8版本开始引入了部分同步机制,以减少全量同步的频率。部分同步允许从服务器在与主服务器断开连接后,重新连接时只获取断开期间丢失的命令,而不是重新进行全量同步。其目的是为了优化全量同步的性能问题,减少全量同步的频率。
部分同步的过程:
1、从服务器保留复制偏移量offset:从服务器会记录最后一次成功同步的命令偏移量(offset)以及主服务器的replid(唯一标识符)。
2、从服务器发起部分同步请求:当从服务器重新连接到主服务器时,它会通过PSYNC 命令请求部分同步。
3、主服务器检查缓冲区:主服务器会检查它的复制积压缓冲区(Replication Backlog),判断是否包含从服务器请求的命令。
4、发送命令:如果缓冲区中包含从服务器请求的命令,主服务器会将这些命令发送给从服务器,完成部分同步;否则,主服务器会触发全量同步。
5、复制积压缓冲区(Replication Backlog)
复制积压缓冲区是一个固定大小的循环缓冲区,主服务器会将所有写命令记录到这个缓冲区中。它主要用于支持部分同步机制,确保从服务器在断开连接后能够快速恢复数据一致性。
- 默认大小:1MB(可以通过repl-backlog-size参数调整)。
- 作用:当从服务器与主服务器短暂断开连接时,主服务器可以通过复制积压缓冲区将断开期间的命令发送给从服务器,避免频繁的全量同步。
6、主从复制的优缺点
优点:
- 数据冗余:提供热备份,防止数据丢失。
- 高可用性:支持故障恢复和自动故障转移(结合 Redis Sentinel 使用)。
- 负载均衡:通过读写分离,减轻主服务器的负载,提升系统性能。
- 简单易用:配置简单,易于维护。
缺点:
- 数据一致性问题:由于主从复制是异步的,从服务器可能会存在一定的延迟,导致主从数据不完全一致。
- 单点故障:如果主服务器发生故障且没有及时切换到从服务器,可能会导致服务中断。
- 网络带宽消耗:主服务器需要将写命令实时发送给从服务器,可能会占用较多的网络带宽。
7、主从复制的优化建议
1、启用持久化:为了防止主服务器崩溃后数据丢失,建议为主服务器启用持久化( RDB或AOF),并定期备份数据。
2、合理配置复制积压缓冲区:根据业务需求调整复制积压缓冲区的大小,确保从服务器在断开连接后能够快速恢复。
3、监控主从延迟:定期监控主从服务器之间的延迟,确保从服务器能够及时同步主服务器的数据。
4、使用哨兵系统:结合Redis Sentinel系统,实现自动故障检测和主从切换,提升系统的高可用性。
5、限制从服务器的数量:过多的从服务器可能会增加主服务器的负担,建议根据实际需求合理配置从服务器的数量。
8、配置示例
1、主节点配置
第一步:配置ip和port
第二步:指定配置文件启动redis服务:
启动命令如:
redis-server.exe redis.windows.conf
2、从节点配置
第一步:配置ip和port
第二步:配置密码
如果主服务器设置了密码,从服务需要配置主服务器的密码
masterauth master_password
第三步:配置从节点所属主节点的信息
注意:5.0版本后的redis使用replicaof替代了slaveof。配置和功能是相同的。
第四步:指定配置文件启动从服务redis
如:redis-server.exe redis.windows.conf
启动从节点后,可以在日志中看到主从复制的相关日志,如下图:
3、验证主从复制
如下图:左边为主节点redis-cli,右边为从节点redis-cli。
主节点设置aaa1的key值,从节点没有设置该key。
在从节点redis-cli中,直接查看aaa1的key信息,可以正确访问。
说明主从同步关系配置是正确且正常工作的。
9、代码实现
1、导入依赖
说明下:springboot自带了LettuceConnectionFactory连接工厂,无需再次引入依赖。
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2、配置类,注入工厂
这里直接在配置类中写死了配置,如果真实开发建议把配置放到配置文件中。
需要注入主节点连接工厂(用于写操作)和从节点连接工厂数组(用于读操作)
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;@Configuration
public class RedisConfig {// 主服务器连接工厂@Bean(name = "masterConnectionFactory")public LettuceConnectionFactory masterConnectionFactory() {RedisStandaloneConfiguration config = new RedisStandaloneConfiguration("127.0.0.1", 6379);
// config.setPassword("your_master_password"); // 如果主服务器启用了密码保护return new LettuceConnectionFactory(config);}@Bean(name = "slaveConnectionFactories")public RedisConnectionFactory[] slaveConnectionFactories() {RedisStandaloneConfiguration slave1Config = new RedisStandaloneConfiguration("127.0.0.1", 6380);
// slave1Config.setPassword("your_master_password"); // 如果服务器启用了密码保护RedisStandaloneConfiguration slave2Config = new RedisStandaloneConfiguration("127.0.0.1", 6381);
// slave2Config.setPassword("your_master_password"); // 如果服务器启用了密码保护return new RedisConnectionFactory[]{new LettuceConnectionFactory(slave1Config),new LettuceConnectionFactory(slave2Config)};}
}
3、自定义注解
用于标注redis操作的方法上,指明该方法走写连接还是读连接。
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ReadWrite {boolean read() default true; // 默认为读操作
}
4、定义AOP,实现注解类的功能
AOP用于监听Redis操作方法上的自定义注解内容,将读写的标识保存到线程的ThreadLocal中。之后可以根据这里的标识切换读写连接工厂,从而实现读写分离的效果。
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;@Aspect
@Component
public class ReadWriteAspect {// 线程局部变量,用于存储当前操作是否为读操作private static final ThreadLocal<Boolean> READ_OPERATION = new ThreadLocal<>();@Around("@annotation(ReadWrite)")public Object around(ProceedingJoinPoint joinPoint) throws Throwable {// 获取方法上的 @ReadWrite注解ReadWrite readWrite = ((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotation(ReadWrite.class);try {// 设置线程局部变量,指示当前操作是读还是写setReadOperation(readWrite.read());// 执行方法return joinPoint.proceed();} finally {// 清除线程局部变量setReadOperation(null); // 清除ThreadLocal的值}}// 设置线程局部变量,指示当前操作是读还是写public static void setReadOperation(Boolean read) {READ_OPERATION.set(read); // 保存到ThreadLocal中,用于之后切换数据工厂来源}// 获取线程局部变量,判断当前操作是否为读操作public static Boolean isReadOperation() {return READ_OPERATION.get();}
}
5、读写连接切换实现类
实现RedisConnectionFactory类,并标明@Primary方法,相当于告诉spring容器,在所有容器中的redis连接工厂里,以当前工厂为主。
即:redisTemplate默认使用这个工厂创建redis连接实例,这里我们复写getConnection方法,用于读写连接的自动切换(实现:则是通过ThreadLocal中保存的读写标识)。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Primary;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisClusterConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisSentinelConnection;
import org.springframework.stereotype.Component;
import java.util.Random;@Component
@Primary // 标记为默认的连接工厂
public class ReadWriteSplittingConnectionFactory implements RedisConnectionFactory {@Autowired@Qualifier("masterConnectionFactory")private RedisConnectionFactory masterConnectionFactory; // 主服务器连接工厂@Autowiredprivate RedisConnectionFactory[] slaveConnectionFactories; // 从服务器连接工厂列表private final Random random = new Random();@Overridepublic org.springframework.data.redis.connection.RedisConnection getConnection() {if (isReadOperation()) { // 根据线程局部变量ThreadLocal中判断是读还是写// 在从服务器数组中随机选择一个连接int index = random.nextInt(slaveConnectionFactories.length);return slaveConnectionFactories[index].getConnection();} else {// 写操作使用主服务器连接return masterConnectionFactory.getConnection();}}// 判断当前操作是否为读操作private boolean isReadOperation() {// 获取线程局部变量,指示当前操作是读还是写Boolean isRead = ReadWriteAspect.isReadOperation();return isRead != null && isRead;}@Overridepublic boolean getConvertPipelineAndTxResults() {return masterConnectionFactory.getConvertPipelineAndTxResults();}@Overridepublic DataAccessException translateExceptionIfPossible(RuntimeException ex) {return masterConnectionFactory.translateExceptionIfPossible(ex);}@Overridepublic RedisClusterConnection getClusterConnection() {return null;}@Overridepublic RedisSentinelConnection getSentinelConnection() {return null;}
}
6、定义redis的工具类,使用注解
编写Redis公共方法,使用自定义注解标识读写操作。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;@Service
public class RedisService {@Autowiredprivate RedisTemplate<String, String> redisTemplate;// 写操作@ReadWrite(read = false) // 相当于指定了写的连接工厂创建连接public void set(String key, String value) {redisTemplate.opsForValue().set(key, value);}// 读操作@ReadWrite(read = true) // 相当于指定了读的连接工厂创建连接public String get(String key) {return (String) redisTemplate.opsForValue().get(key);}
}
7、测试类
编写接口,调用Redis的读写方法,验证
import com.zw.base.BaseController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping(value = "redis", method = {RequestMethod.POST, RequestMethod.GET})
public class RedisController extends BaseController {@Autowiredprivate RedisService redisService;@RequestMapping("/set")public String setTest() {redisService.set("aaa3", "zhangsan3");return null;}@RequestMapping("/get")public String getTest() {String aaa2 = redisService.get("aaa2");System.out.println("aaa2:" + aaa2);return aaa2;}}
8、验证结果
测试类中的set和get方法都正常使用。
但是这并不能直接看出读写到底走的那一个redis服务。这里可以断点看一下,当调用set方法时,可以看到走的逻辑是主节点的连接。
当调用get方法,如下可以看到,走的逻辑是从节点中任意一个节点的连接。
如上的验证即可说明,已经达到了读写分离的效果。
学海无涯苦作舟!!!
相关文章:
Redis篇-19--运维篇1-主从复制(主从复制,读写分离,配置实现,实战案例)
1、概述 Redis的主从复制(Master-Slave Replication)是一种数据冗余机制,它允许将一台Redis服务器的数据复制到其他Redis服务器。在主从复制中,有一台主服务器(Master)和一个或多个从服务器(Sl…...
springboot449教学资源共享平台(论文+源码)_kaic
摘 要 如今社会上各行各业,都喜欢用自己行业的专属软件工作,互联网发展到这个时候,人们已经发现离不开了互联网。新技术的产生,往往能解决一些老技术的弊端问题。因为传统教学资源共享平台信息管理难度大,容错率低&am…...
Unbuntu下怎么生成SSL自签证书?
环境: WSL2 Unbuntu 22.04 问题描述: Unbuntu下怎么生成SSL自签证书? 解决方案: 生成自签名SSL证书可以使用OpenSSL工具,这是一个广泛使用的命令行工具,用于创建和管理SSL/TLS证书。以下是生成自签名…...
Ubuntu18.04——换源
一、前提说明 系统自带的源往往下载很慢,通过换源操作后,往往下载/更新 速度大幅提升 每种版本对应的不一样,例如Ubuntu18.04和Ubuntu20.04的有差异,所以换源需要根据不同版本对应的命令 二、操作步骤 0.备份原先的 /etc/apt/sou…...
crictl和ctr与docker的命令的对比
crictl是遵循CRI接口规范的一个命令行工具,通常用它来检查和管理kubelet节点上的容器运行时和镜像 ctr是containerd的一个客户端工具, 接下来就是crictl的的常见命令,其中能完全替代docker命令的参照下列表格 操作crictldocker查看运行容器…...
Java 技术面试常见问题解析
1.说说Mybatis的缓存机制: MyBatis 是一个优秀的持久层框架,它简化了企业应用开发中数据库操作的代码。MyBatis 提供了一级缓存和二级缓存机制来优化对数据库的访问。 一级缓存 (SqlSession级别的缓存) 一级缓存是 MyBatis 中默认开启且无法关闭的缓存机制。它存…...
数据结构,链表的简单使用
任意位置删除: void Any_Del(LinkListPtr h,int a)//任意删 {if(NULLh||a>h->len){printf("删除失败");}LinkListPtr ph;for(int i0;i<a-1;i){pp->next;}LinkListPtr p2p;p2p2->next;p->nextp->next->next;free(p2);p2NULL;h-&g…...
go引用包生成不了vendor的问题
比如我要引入github.com/jinzhu/gorm这个包. 1. 首先获取包 go get github.com/jinzhu/gorm 这时go.mod文件中也有这个包依赖信息了. 2. 然后构建vendor go mod vendor 结果发现vendor目录下没有生成对应的包, 而且modules.txt也注释掉这个包了. 原因是没有其进行引用, go…...
C语言——实现求出最大值
问题描述:利用C语言自定义函数求出一维数组里边最大的数字 //利用函数找最大数#include<stdio.h>int search(int s[9]) //查找函数 {int i , max s[0] , max_xia 0;for(i0;i<9;i){if(s[i] > max){max_xia i;max s[max_xia];}}return max; } in…...
【CSS in Depth 2 精译_081】 13.1:CSS 渐变效果(下)——CSS 径向渐变(13.1.3)+ CSS 锥形渐变(13.1.4)
当前内容所在位置(可进入专栏查看其他译好的章节内容) 第四部分 视觉增强技术 ✔️【第 13 章 渐变、阴影与混合模式】 ✔️ 13.1 渐变 ✔️ 13.1.1 使用多个颜色节点(上)13.1.2 颜色插值方法(中)13.1.3 径…...
【SH】Ubuntu Server 24搭建Web服务器访问Python程序研发笔记
文章目录 说个问题写个方案一、安装Ubuntu Server二、安装Web服务器采用Nginx服务器 三、安装Python及依赖创建项目虚拟环境 四、安装Python Web框架采用Flask框架创建和运行Flask应用(以后的重点) 五、安装WSGI服务器采用Gunicorn 六、配置Nginx七、验证…...
创建项目以及本地仓库和远程仓库并上传项目
创建项目以及本地仓库和远程仓库并上传项目 其详细流程如下: 1、本地创建项目 2、创建本地仓库(若使用idea在创建项目时选择了创建.git本地仓库,则此步骤省略) 进入到你需要上传的项目的目录下,右键找到Git Bah He…...
代码开发相关操作
使用Vue项目管理器创建项目:(vue脚手架安装一次就可以全局使用) windowR打开命令窗口,输入vue ui,进入GUI页面,点击创建-> 设置项目名称,在初始化git下面输入:init project&…...
ElasticSearch系列:利用runtime field实现日期字符串实现日期范围查询
在Elasticsearch中,如果你有一个时间字符串字段,并且你希望在查询时将其转换为date类型以便进行日期范围查询或其他日期相关的操作,你可以使用runtime_fields来实现这一转换。不过,与转换为UNIX时间戳不同,Elasticsear…...
前端:如何在静态目录下显示一张图片
假设已经配置(或默认配置好)public文件夹是静态资源文件夹,public文件夹中的资源会直接映射到根URL。 1. 我的前端图片保存路径是: F:\front\public\icon-favo.png 前端地址是:http://localhost:20002 我想要访问…...
Java设计模式 —— 【结构型模式】桥接模式详解
前言 现在有一个需求,需要创建不同的图形,并且每个图形都有可能会有不同的颜色。 首先我们看看用继承来实现: 我们可以发现有很多的类,假如我们再增加一个形状或再增加一种颜色,就需要创建更多的类。 试想…...
Qt同步读取串口
头文件 #include "InsScpi.h" #include <QObject> #include <QSerialPort>class TestSerial : public QObject {Q_OBJECT public:explicit TestSerial(QObject *parent nullptr);//打开设备bool openDevice(const QString &portName);//关闭设备…...
MySQL高可用
MySQL主从复制的过程是怎么样的 分为3个阶段: 写入binlog:主库修改数据后,会写入binlog日志,从库连接到主库后,主库会创建一个log dump线程,用于发送bin log的内容同步binlog:从库会专门创建一…...
OpenHarmony-3.HDF Display子系统(6)
Display 子系统 1.Display驱动模型介绍 当前操作系统和 SOC 种类繁多,各厂商的显示屏器件也各有不同,随之针对器件的驱动代码也不尽相同,往往是某一款器件驱动,只适用于某单一内核系统或 SOC,如果要迁移到其他内核或者…...
第10章:CSS最佳实践 --[CSS零基础入门]
代码组织 在CSS开发中,良好的代码组织和最佳实践对于项目的可维护性和扩展性至关重要。以下是两个示例,展示了如何遵循CSS最佳实践来组织代码。 示例 1: 使用 BEM(Block Element Modifier)命名法 BEM 是一种用于提高 CSS 可读性…...
备战美赛!2025美赛数学建模C题模拟预测!用于大家练手模拟!
完整的思路代码模型见文末 2025 美赛数学建模 C 题 模拟题:城市交通拥堵指数的预测与管理策略 背景 随着全球城市化进程的加快,交通拥堵问题成为城市发展的重要挑战之一。交通拥堵不仅影响居民出行效率,还增加了能源消耗和碳排放。近年来&…...
ESP8266 Ubuntu 安装
文章参考:https://blog.csdn.net/AUST_129/article/details/119406722文章浏览阅读1.8k次,点赞4次,收藏19次。参考:https://docs.espressif.com/projects/esp8266-rtos-sdk/en/latest/get-started/linux-setup.htmlhttp://aicloud…...
tryhackme-Pre Security-Defensive Security Intro(防御安全简介)
任务一:Introduction to Defensive Security防御安全简介 此room的两个要点: Preventing intrusions from occurring 防止入侵发生Detecting intrusions when they occur and responding properly 检测发生的入侵并正确响应 防御安全还有更多内容。 除上…...
单片机:实现倒计时(附带源码)
使用单片机实现倒计时功能是一个常见的嵌入式应用,它能帮助你更好地理解如何进行时间控制和如何通过定时器实现精确的倒计时。通过该项目,你将学习如何使用单片机的定时器来进行时间计算,并通过LED或LCD显示倒计时的结果。 1. 项目概述 倒计…...
安全防御之可信计算技术
可信计算技术是一种计算机安全体系结构,旨在提高计算机系统在面临各种攻击和威胁时的安全性和保密性。它通过包括硬件加密、受限访问以及计算机系统本身的完整性验证等技术手段,确保计算机系统在各种攻击和威胁下保持高度安全和保密性。 一、可信计算基…...
视频生成缩略图
文章目录 视频生成缩略图使用ffmpeg 视频生成缩略图 最近有个需求,视频上传之后在列表和详情页需要展示缩略图 使用ffmpeg 首先引入jar包 <dependency><groupId>org.bytedeco</groupId><artifactId>javacpp</artifactId><vers…...
PySide6程序框架设计
pyside6有一个优点自动适配高分辨ui pyqt5需要自己写这部分逻辑 1、主程序代码 DINGSHI01Main.py # -*- coding: utf-8 -*- import sys,time,copy from PySide6.QtWidgets import QWidget,QApplication from PySide6.QtCore import Qt from PySide6 import QtCore, QtGui, Q…...
WebSocket入门与结合redis
WebSocket是什么 WebSocket 是一种用于在客户端和服务器之间建立双向通信的协议,它能实现实时、持久的连接。与传统的 HTTP 请求响应模式不同,WebSocket 在建立连接后允许客户端和服务器之间相互发送消息,直到连接关闭。由于 WebSocket 具有…...
锂电池SOH预测 | 基于BiGRU双向门控循环单元的锂电池SOH预测,附锂电池最新文章汇集
锂电池SOH预测 | 基于BiGRU双向门控循环单元的锂电池SOH预测,附锂电池最新文章汇集 目录 锂电池SOH预测 | 基于BiGRU双向门控循环单元的锂电池SOH预测,附锂电池最新文章汇集预测效果基本描述程序设计参考资料 预测效果 基本描述 锂电池SOH预测 | 基于Bi…...
C# 结构体和类
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、类(Class)二、结构体(Struct)示例代码(定义类和结构体)类的继承代码示例(…...
C语言中的内存管理:理解指针、动态内存分配与内存泄漏
在C语言中,内存管理是一个至关重要的主题。与许多高级语言不同,C语言要求程序员显式地管理内存的分配与释放。虽然这种做法提供了更高的灵活性和控制权,但也容易导致内存泄漏、越界访问等问题。正确地管理内存对于编写高效、稳定的C程序至关重…...
web:pc端企业微信登录-vue版
官方文档:developer.work.weixin.qq.com/document/pa… 不需要调用ww.register,直接调用ww.createWWLoginPanel即可创建企业微信登录面板 - 文档 - 企业微信开发者中心 (qq.com) 引入 //通过 npm 引入 npm install wecom/jssdk import * as ww from we…...
GC.2015.四年级
GC.2015.四年级.01.奖励 题目描述 晨晨班主任想奖励班里面的每个学生一只圆珠笔和铅笔,已知每只圆珠笔和铅笔的价格,以及班里面的学生人数n,你能帮助老师算出总价吗? 输入格式 第一行:一个整数n,代表班里…...
一篇文章掌握WebService服务、工作原理、核心组件、主流框架
目录 1、WebService定义 解决问题: 2、WebService的工作原理 2.1 实现一个完整的Web服务包括以下步骤 2.2 调用方式 3、Web Service的核心组件 3.1 XML 3.2 SOAP 3.3 WSDL 3.4 UDDI 4、主流框架 4.1 AXIS(已淘汰) 4.2 XFire 4.3 CXF 5、Soap协议详解…...
中软高科身份证云解码金融(银行)解决方案介绍
多年来,中软高科一直深耕身份证云解码领域,对身份证云解码应用于金融(银行),进行了大量且深入的研究。从长期调研来看,金融(银行)的痛点需求主要有: 传统身份证解码设备…...
Linux NVIDIA GPU linpack 测试
前言 多节点多GPU测试有点坑,这篇文章有解决方法。 环境 操作系统信息 lsb_release -aNo LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 22.04.3 LTS Release: 22.04 Codename: jammycpu 信息 lscpuArchitecture: x86_64CPU op-mod…...
LiteFlow决策系统的策略模式,顺序、最坏、投票、权重
个人博客:无奈何杨(wnhyang) 个人语雀:wnhyang 共享语雀:在线知识共享 Github:wnhyang - Overview 想必大家都有听过或做过职业和性格测试吧,尤其是现在的毕业生,在投了简历之后经…...
“AI换脸”骗过人脸识别?黑产攻击新手段应如何防御?
在著名美剧《权力的游戏》中,有一个神秘的刺客组织叫“无面者”,这个组织中的人可以通过某种神秘手段切换无数种不同的面孔,实现“一人千面”。 电视剧毕竟魔幻。但如今,基于人工智能的深度合成伪造技术正在让“一人千面”成为现…...
面试题整理6----什么是进程最大数、最大线程数、进程打开的文件数,怎么调整
什么是进程最大数、最大线程数、进程打开的文件数,怎么调整 1. 进程最大数1.1 调整方法: 2. 最大线程数2.1 调整方法: 3. 注意事项 #linux 1. 进程最大数 进程最大数是指操作系统允许同时运行的进程数量上限。这个限制通常由内核参数 ulimi…...
android RadioButton + ViewPager+fragment
RadioGroup viewpage fragment 组合显示导航栏 1、首先主界面的布局控件就是RadioGroup viewpage <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:tools…...
Zabbix6.0升级为6.4
为了体验一些新的功能,比如 Webhook 和问题抑制等,升级个小版本。 一、环境信息 1. 版本要求 一定要事先查看官方文档,确认组件要求的版本,否则版本过高或者过低都会出现问题。 2. 升级前后信息 环境升级前升级后操作系统CentOS…...
Unity 根据文本宽度自动移动图像位置
游戏中有时候需要变动的显示一个物品的数量,变化的文本宽度不停的变化,这时候需要将物品的icon随着文本的长度而改变位置。 实现思路:使用Content Size Fitter来动态改变内容的大小。 首先建立一个文本组件,添加Content Size Fi…...
spring @Mapper Converter转换泛型异常
spring Mapper Converter转换泛型异常 需要在每个list类型转换上面加Named 注解,否则会影响page生成的类型转换 比如: import org.mapstruct.Mapper; import org.mapstruct.Named;import com.baomidou.mybatisplus.core.metadata.IPage; import com.b…...
如何设计一个秒杀系统
开局一张图 结局要说清 对于设计一个秒杀系统,结合图片分层结构,根据每一层从访问层,负载层,服务层,业务层,支撑层,数据层,详细说明每一层应该怎么设计。 应该注意那些事项。比如访…...
SPL06 基于stm32F103 HAL库驱动(软件模拟IIC)
talk is cheap, show you my code SPL06.c #include "SPL06.h"//*************全局变量*************// Factor_List* b_list; //存储过采样率对应的系数KP,KT COEF_ValueStruct Coefficient { 0 }; //存储校准系数…...
arcgisPro将面要素转成CAD多段线
1、说明:正常使用【导出为CAD】工具,则导出的是CAD三维多线段,无法进行编辑操作、读取面积等。这是因为要素面中包含Z值,导出则为三维多线段数据。需要利用【复制要素】工具禁用M值和Z值,再导出为CAD,则得到…...
Cocos Creator 试玩广告开发
之前主要是使用Unity,这次刚好项目是试玩游戏的开发,所以临时学了Cocos来开发。所以这篇文章,更加关注从Unity转到Cocos开发的经历以及试玩的基本开发。 首先,我是没有使用过Cocos的,也没有接触过Ts语言,对于Ts的开发开…...
【Linux】解锁文件描述符奥秘,高效缓存区的实战技巧
fd和缓冲区 1. 文件描述符fd1.1. 概念与本质1.2. 打开文件的管理1.3. 一切皆文件的理解1.4. 分配规则1.5. 重定向的本质1.5.1. dup2 2. FILE中的缓冲区2.1. 概念2.2. 存在的原因2.3. 类型(刷新方案)2.4. 存放的位置2.4.1. 代码证明、现象解释 2.5. 模拟C标准库中的方法 1. 文件…...
MySQL基础笔记(五)
在此特别感谢尚硅谷-康师傅的MySQL精品教程 获取更好的阅读体验请前往我的博客主站! 如果本文对你的学习有帮助,请多多点赞、评论、收藏,你们的反馈是我更新最大的动力! 约束 1. 约束(constraint)概述 1.1 为什么需要约束 数据完整性&…...
夯实数字技术,培育创新人才:数据科学与大数据技术专业人才培养实践
近年来,得益于全球各国家和地区对大数据产业的政策扶持以及数字经济的蓬勃发展,大数据市场在全球范围内展现出了迅猛的增长态势。国家层面相继出台了诸如《“数据要素 ” 三年行动计划(2024—2026 年)》《数字中国建设整体布局规划…...