【缓存与数据库结合最终方案】伪从技术
实现伪从技术:基于Binlog的Following表变更监听与缓存更新
技术方案概述
要实现一个专门消费者服务作为Following表的伪从,订阅binlog并在数据变更时更新缓存,可以采用以下技术方案:
主要组件
- MySQL Binlog监听:使用开源工具监听MySQL的binlog
- 消息队列:将变更事件发布到消息队列(可选)
- 消费者服务:处理变更事件并更新缓存
- 缓存系统:Redis或其他缓存解决方案
具体实现步骤
1. 配置MySQL Binlog
首先确保MySQL已开启binlog并配置为ROW模式:
-- 检查当前binlog配置
SHOW VARIABLES LIKE 'log_bin';
SHOW VARIABLES LIKE 'binlog_format';-- 修改my.cnf/my.ini文件
[mysqld]
log-bin=mysql-bin
binlog-format=ROW
server-id=1
2. 使用Java实现Binlog监听
可以使用开源的mysql-binlog-connector-java
库:
<!-- pom.xml 依赖 -->
<dependency><groupId>com.github.shyiko</groupId><artifactId>mysql-binlog-connector-java</artifactId><version>0.25.4</version>
</dependency>
3. 消费者服务实现
import com.github.shyiko.mysql.binlog.BinaryLogClient;
import com.github.shyiko.mysql.binlog.event.*;public class FollowingTableBinlogConsumer {private final BinaryLogClient client;private final CacheService cacheService;public FollowingTableBinlogConsumer(String hostname, int port, String username, String password, CacheService cacheService) {this.cacheService = cacheService;this.client = new BinaryLogClient(hostname, port, username, password);client.registerEventListener(event -> {EventData data = event.getData();if (data instanceof TableMapEventData) {// 表映射事件TableMapEventData tableMapEvent = (TableMapEventData) data;if ("your_database".equals(tableMapEvent.getDatabase()) && "Following".equals(tableMapEvent.getTable())) {// 处理Following表的事件}} else if (data instanceof WriteRowsEventData) {// 插入操作processWriteEvent((WriteRowsEventData) data);} else if (data instanceof UpdateRowsEventData) {// 更新操作processUpdateEvent((UpdateRowsEventData) data);} else if (data instanceof DeleteRowsEventData) {// 删除操作processDeleteEvent((DeleteRowsEventData) data);}});}private void processWriteEvent(WriteRowsEventData data) {// 处理新增关注事件for (Serializable[] row : data.getRows()) {Long followerId = (Long) row[0]; // 假设第一列是follower_idLong followeeId = (Long) row[1]; // 假设第二列是followee_idcacheService.addFollowing(followerId, followeeId);}}private void processUpdateEvent(UpdateRowsEventData data) {// 处理更新事件(如果Following表有更新操作)for (Map.Entry<Serializable[], Serializable[]> row : data.getRows()) {Serializable[] before = row.getKey();Serializable[] after = row.getValue();// 根据业务逻辑处理更新}}private void processDeleteEvent(DeleteRowsEventData data) {// 处理取消关注事件for (Serializable[] row : data.getRows()) {Long followerId = (Long) row[0];Long followeeId = (Long) row[1];cacheService.removeFollowing(followerId, followeeId);}}public void start() {try {client.connect();} catch (IOException e) {throw new RuntimeException("Failed to connect to MySQL binlog", e);}}public void stop() {try {client.disconnect();} catch (IOException e) {// 处理异常}}
}
4. 缓存服务实现
public interface CacheService {void addFollowing(Long followerId, Long followeeId);void removeFollowing(Long followerId, Long followeeId);Set<Long> getFollowings(Long followerId);Set<Long> getFollowers(Long followeeId);
}public class RedisCacheService implements CacheService {private final JedisPool jedisPool;public RedisCacheService(JedisPool jedisPool) {this.jedisPool = jedisPool;}@Overridepublic void addFollowing(Long followerId, Long followeeId) {try (Jedis jedis = jedisPool.getResource()) {// 用户关注列表jedis.sadd("user:" + followerId + ":followings", followeeId.toString());// 用户粉丝列表jedis.sadd("user:" + followeeId + ":followers", followerId.toString());}}@Overridepublic void removeFollowing(Long followerId, Long followeeId) {try (Jedis jedis = jedisPool.getResource()) {// 用户关注列表jedis.srem("user:" + followerId + ":followings", followeeId.toString());// 用户粉丝列表jedis.srem("user:" + followeeId + ":followers", followerId.toString());}}@Overridepublic Set<Long> getFollowings(Long followerId) {try (Jedis jedis = jedisPool.getResource()) {Set<String> followings = jedis.smembers("user:" + followerId + ":followings");return followings.stream().map(Long::valueOf).collect(Collectors.toSet());}}@Overridepublic Set<Long> getFollowers(Long followeeId) {try (Jedis jedis = jedisPool.getResource()) {Set<String> followers = jedis.smembers("user:" + followeeId + ":followers");return followers.stream().map(Long::valueOf).collect(Collectors.toSet());}}
}
5. 服务启动
public class Application {public static void main(String[] args) {// 配置Redis连接池JedisPool jedisPool = new JedisPool("localhost", 6379);CacheService cacheService = new RedisCacheService(jedisPool);// 启动binlog消费者FollowingTableBinlogConsumer consumer = new FollowingTableBinlogConsumer("localhost", 3306, "username", "password", cacheService);consumer.start();// 添加关闭钩子Runtime.getRuntime().addShutdownHook(new Thread(() -> {consumer.stop();jedisPool.close();}));}
}
高级优化方案
1. 引入消息队列(如Kafka)
// 在Binlog消费者中,将事件发布到Kafka
public class KafkaEventPublisher {private final Producer<String, String> producer;public KafkaEventPublisher(String bootstrapServers) {Properties props = new Properties();props.put("bootstrap.servers", bootstrapServers);props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");this.producer = new KafkaProducer<>(props);}public void publishFollowingEvent(String eventType, Long followerId, Long followeeId) {String key = followerId + ":" + followeeId;String value = String.format("{\"eventType\":\"%s\",\"followerId\":%d,\"followeeId\":%d}", eventType, followerId, followeeId);producer.send(new ProducerRecord<>("following-events", key, value));}public void close() {producer.close();}
}// 然后有独立的消费者服务从Kafka消费并更新缓存
2. 处理初始数据同步
// 在服务启动时,先全量同步Following表数据到缓存
public void initialSync() {// 从数据库读取所有Following关系List<Following> allFollowings = followingRepository.findAll();// 批量写入缓存try (Jedis jedis = jedisPool.getResource()) {Pipeline pipeline = jedis.pipelined();for (Following following : allFollowings) {pipeline.sadd("user:" + following.getFollowerId() + ":followings", following.getFolloweeId().toString());pipeline.sadd("user:" + following.getFolloweeId() + ":followers", following.getFollowerId().toString());}pipeline.sync();}
}
3. 监控与容错
- 记录binlog位置,以便重启后从正确位置继续
- 实现重试机制处理缓存更新失败
- 添加监控指标跟踪事件处理延迟和错误率
总结
这个方案实现了Following表的伪从技术,通过监听MySQL binlog实时捕获数据变更,并更新Redis缓存。这种架构具有以下优点:
- 低延迟:几乎实时同步数据库变更
- 解耦:消费者服务独立于主业务服务
- 可扩展:可以轻松添加更多消费者处理不同业务逻辑
- 高性能:Redis提供了高效的关系数据存储和查询
根据业务规模,可以选择简单的直接更新缓存方案,或者引入消息队列的更复杂架构。
经过对数据库设计、缓存设计的详细论证,总结并提炼出缓存与数据库结合的最终方案。
伪从方案应用场景如:用户关系服务,关注与取消关注的接口。
- 即接口直接更新数据库Following表即响应用户,后续流程对用户来说是完全异步的。
- Follower表、计数服务、Redis缓存会依赖Following表产生的binlog日志分别更新数据。
关于Binlog监听在服务重启/暂停时的数据丢失问题
Binlog监听在服务重启或暂停时是否会导致数据丢失,取决于具体的实现方式和配置。下面我将详细分析这个问题及解决方案。
关键影响因素
1. Binlog位置记录
- 不记录位置:如果服务没有记录已处理的binlog位置,重启后会从当前最新的binlog位置开始,导致中间变更丢失
- 记录位置:正确记录binlog位置可以确保重启后从断点继续
2. MySQL binlog保留策略
expire_logs_days
参数决定binlog保留天数- 如果binlog被过早清除,而服务长时间停机,可能导致无法恢复
3. 事务完整性
- 部分处理的事务在重启后可能导致不一致
解决方案
1. 持久化binlog位置
修改之前的消费者服务,增加位置记录功能:
public class FollowingTableBinlogConsumer {// 增加binlog位置存储接口private final BinlogPositionStore positionStore;public FollowingTableBinlogConsumer(..., BinlogPositionStore positionStore) {this.positionStore = positionStore;// 设置binlog文件名和位置BinlogPosition position = positionStore.getPosition();if (position != null) {client.setBinlogFilename(position.getFilename());client.setBinlogPosition(position.getPosition());}client.registerEventListener(event -> {// 处理事件...// 记录位置if (event.getHeader().getEventType() == EventType.ROTATE) {RotateEventData rotateEvent = (RotateEventData) event.getData();positionStore.savePosition(new BinlogPosition(rotateEvent.getBinlogFilename(), rotateEvent.getBinlogPosition()));} else if (event.getHeader().getEventType() != EventType.FORMAT_DESCRIPTION) {positionStore.savePosition(new BinlogPosition(client.getBinlogFilename(), event.getHeader().getNextPosition()));}});}
}// Binlog位置存储接口
public interface BinlogPositionStore {void savePosition(BinlogPosition position);BinlogPosition getPosition();
}// 简单的文件存储实现
public class FileBinlogPositionStore implements BinlogPositionStore {private final File positionFile;public FileBinlogPositionStore(String filePath) {this.positionFile = new File(filePath);}@Overridepublic void savePosition(BinlogPosition position) {try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(positionFile))) {out.writeObject(position);} catch (IOException e) {throw new RuntimeException("Failed to save binlog position", e);}}@Overridepublic BinlogPosition getPosition() {if (!positionFile.exists()) return null;try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(positionFile))) {return (BinlogPosition) in.readObject();} catch (Exception e) {throw new RuntimeException("Failed to read binlog position", e);}}
}// Binlog位置对象
public class BinlogPosition implements Serializable {private final String filename;private final long position;// constructor, getters...
}
2. MySQL配置优化
确保MySQL配置合理:
-- 设置足够的binlog保留时间(根据业务需求调整)
SET GLOBAL expire_logs_days = 7;-- 或使用新的变量(MySQL 8.0+)
SET GLOBAL binlog_expire_logs_seconds = 604800; -- 7天
3. 启动时数据校验和修复
服务启动时增加校验逻辑:
public void start() {// 检查binlog位置是否有效BinlogPosition position = positionStore.getPosition();if (position != null) {if (!isBinlogFileExists(position.getFilename())) {// 执行全量同步initialSync();positionStore.clearPosition();}}client.connect();
}private boolean isBinlogFileExists(String filename) {// 实现检查binlog文件是否存在的逻辑// 可以通过SHOW BINARY LOGS命令获取当前存在的binlog文件列表
}
4. 优雅停机处理
确保服务停止时正确处理:
public void stop() {try {// 等待当前事件处理完成client.disconnect();// 确保最后的位置已保存positionStore.flush();} catch (IOException e) {// 处理异常}
}
高级保障方案
1. 引入事务表记录处理状态
创建一张事务记录表:
CREATE TABLE binlog_consumer_state (consumer_id VARCHAR(100) PRIMARY KEY,binlog_filename VARCHAR(100) NOT NULL,binlog_position BIGINT NOT NULL,last_heartbeat TIMESTAMP NOT NULL,processed_checksum VARCHAR(100)
);
2. 定期检查点(checkpoint)
// 每处理N个事件或每隔M秒记录一次完整状态
private void checkpoint(Event event) {// 计算当前已处理数据的校验和String checksum = computeChecksum();// 更新数据库状态jdbcTemplate.update("INSERT INTO binlog_consumer_state VALUES (?, ?, ?, NOW(), ?) " +"ON DUPLICATE KEY UPDATE binlog_filename=?, binlog_position=?, last_heartbeat=NOW(), processed_checksum=?",consumerId, client.getBinlogFilename(), event.getHeader().getNextPosition(), checksum,client.getBinlogFilename(), event.getHeader().getNextPosition(), checksum);
}
3. 数据修复机制
当检测到不一致时:
public void repairIfNeeded() {// 从数据库获取最后处理的状态StateRecord state = getLastStateFromDB();// 从缓存获取最后处理的状态StateRecord cacheState = getLastStateFromCache();if (!state.equals(cacheState)) {// 执行修复逻辑executeRepair(state);}
}
总结
正确实现的Binlog监听服务在重启/暂停时不会丢失数据,但需要:
- 持久化记录binlog位置(文件名+偏移量)
- 配置足够的binlog保留时间
- 实现优雅的停机和恢复机制
- 考虑增加校验和修复逻辑(针对关键业务)
建议的完整方案:
- 使用混合位置存储(本地文件+数据库)
- 定期检查点
- 启动时数据校验
- 足够的binlog保留期
- 监控binlog消费延迟
这样即使在服务重启、暂停甚至长时间停机后,也能保证数据不会丢失,并能从正确的位置恢复处理。
相关文章:
【缓存与数据库结合最终方案】伪从技术
实现伪从技术:基于Binlog的Following表变更监听与缓存更新 技术方案概述 要实现一个专门消费者服务作为Following表的伪从,订阅binlog并在数据变更时更新缓存,可以采用以下技术方案: 主要组件 MySQL Binlog监听:使…...
如何规避矩阵运营中的限流风险及解决方案
在自媒体矩阵化运营中,系统性规避平台限流机制需建立在精准理解算法逻辑的基础上。根据行业实践数据统计,当前矩阵账号触发限流的核心诱因主要集中在两大维度: 首先需要明确的是设备与网络层面的合规性配置。当单台移动设备频繁切换多账号登…...
TensorFlow Keras“安全模式”真的安全吗?绕过 safe_mode 缓解措施,实现任意代码执行
机器学习框架通常依赖序列化和反序列化机制来存储和加载模型,然而模型中不恰当的代码隔离和可执行组件可能会导致严重的安全风险。 TensorFlow 中的 Keras v3 ML 模型结构 对于基于 TensorFlow 的 Keras 模型,存在一个严重的反序列化漏洞,编号为CVE-2024-3660。攻击者可利…...
PostgreSQL-日志管理介绍
概述 1、日志管理器: 日志模块包括事务提交日志CLOG和数据日志XLOG。其中CLOG是系统为整个事务管理流程所建立的日志,主要用于记录事务的状态,同时通过SUBTRANS日志记录事务的嵌套关系。XLOG日志是数据库日志的主体,记录数据库中…...
【Java 数据结构】泛型
目录 一. 什么是泛型 二. 引出泛型 三. 泛型语法 四. 泛型的使用 五. 泛型是如何编译的 5.1 擦除机制 六. 泛型的继承 6.1 泛型类继承非泛型类 6.2 泛型类继承泛型类 6.2.1 父类的同名传递 6.2 2 父类的异名传递 6.2.3 父类固定类型传递 6.2.4 子类添加参数 七. 泛…...
鲲鹏麒麟搭建Docker仓库
Docker Registry简介 Docker Registry是一个开源的镜像仓库工具,用于存储和分发Docker镜像。它是Docker生态系统中的核心组件之一,提供了镜像的推送(push)、拉取(pull)和管理功能。 主要特性: 1、开源免费:Apache 2.0许可证 2、轻…...
Java快速上手之实验4(接口回调)
1.编写接口程序RunTest.java,通过接口回调实现多态性。解释【代码4】和【代码6】的执行结果为何不同? interface Runable{ void run(); } class Cat implements Runable{ public void run(){ System.out.println("猫急上树.."…...
【前端】【业务场景】【面试】在前端开发中,如何实现实时数据更新,比如实时显示服务器推送的消息,并且保证在不同网络环境下的稳定性和性能?
问题:在前端开发中,如何实现实时数据更新,比如实时显示服务器推送的消息,并且保证在不同网络环境下的稳定性和性能? 一、实现实时数据更新的方法 WebSocket: 原理:WebSocket 是一种在单个 TCP …...
redis相关问题整理
Redis 支持多种数据类型: 字符串 示例:存储用户信息 // 假设我们使用 redis-plus-plus 客户端库 auto redis Redis("tcp://127.0.0.1:6379"); redis.set("user:1000", "{name: John Doe, email: john.doeexample.com}"…...
某城乡老旧房屋试点自动化监测服务项目
1. 项目简介 我国是房屋建设增长量最高的国家或地区,但上个世纪末建造的房屋多为砖混结构,使用寿命短且缺乏维护。这些房屋在使用过程中受到地质活动、自然环境和人为改造的影响,其结构强度逐年下降,部分房屋甚至出现墙体裂缝、倾…...
企业为何要求禁用缺省口令?安全风险及应对措施分析
在当今数字化时代,企业网络安全面临着前所未有的挑战。缺省口令的使用是网络安全中的一个重要隐患,许多企业在制定网络安全红线时,明确要求禁用缺省口令。本文将探讨这一要求的原因及其对企业安全的重要性。 引言:一个真实的入侵场…...
在 MySQL 中,索引前缀长度为什么选择为 191
在 MySQL 中,索引前缀长度选择为 191 的常见原因主要与 字符集编码 和 索引长度限制 相关,具体解释如下: 1. 字符集编码的影响 utf8mb4 字符集: MySQL 的 utf8mb4 字符集每个字符最多占用 4 个字节(相比 utf8 的 3 字…...
【Python语言基础】24、并发编程
文章目录 1. 多线程(threading模块)1.1 多线程的实现(threading 模块)1.2 多线程的优缺点1.3 线程同步与锁 2. 多进程(multiprocessing模块)2.1 多进程实现(multiprocessing模块)2.2 多进程的优缺点2.3 进程…...
MySQL-自定义函数
自定义函数 函数的作用 mysql数据库中已经提供了内置的函数,比如:sum,avg,concat等等,方便我们日常的使用,当需要时mysql支持定义自定义的函数,方便与我们对于需用复用的功能进行封装。 基本…...
实时操作系统在服务型机器人中的关键作用
一、服务型机器人的发展现状与需求 近年来,服务型机器人市场呈现出蓬勃发展的态势。据国际机器人联合会(IFR)2024 年度报告显示,全球人形机器人市场规模预计在 2025 年达到 38.7 亿美元,年复合增长率达 19.2%。服务型机…...
智能电网第5期 | 老旧电力设备智能化改造:协议转换与边缘计算
随着电力行业数字化转型加速,大量在役老旧设备面临智能化升级需求。在配电自动化改造过程中,企业面临三大核心挑战: 协议兼容难题:传统设备采用Modbus等老旧协议,无法接入智能电网系统 数据处理瓶颈:设备本…...
【UML建模】starUML工具
一.概述 StarUML是一款UML工具,允许用户创建和管理UML(统一建模语言)模型,广泛应用于软件工程领域。它的主要功能包括创建各种UML图:如用例图、类图、序列图等,支持代码生成与反向工程,以及提供…...
【技术笔记】Cadence实现Orcad与Allegro软件交互式布局设置
【技术笔记】Cadence实现Orcad与Allegro软件交互式布局设置 更多内容见专栏:【硬件设计遇到了不少问题】、【Cadence从原理图到PCB设计】 在做硬件pcb设计的时候,原理图选中一个元器件,希望可以再PCB中可以直接选中。 为了达到原理图和PCB两两…...
第十七届山东省职业院校技能大赛 中职组网络建设与运维赛项
第十七届山东省职业院校技能大赛 中职组网络建设与运维赛项 赛题 B 卷 第十七届山东省职业院校技能大赛中职组网络建设与运维赛项 1 赛题说明 一、竞赛项目简介 “网络建设与运维”竞赛共分为以下三个模块: 网络理论测试; 网络建设与调试…...
深入详解人工智能数学基础——概率论中的KL散度在变分自编码器中的应用
🧑 博主简介:CSDN博客专家、CSDN平台优质创作者,高级开发工程师,数学专业,10年以上C/C++, C#, Java等多种编程语言开发经验,拥有高级工程师证书;擅长C/C++、C#等开发语言,熟悉Java常用开发技术,能熟练应用常用数据库SQL server,Oracle,mysql,postgresql等进行开发应用…...
Docker配置DNS方法详解及快速下载image方法
根据错误信息,Docker 在拉取镜像时遇到网络连接超时(Client.Timeout exceeded),通常与 代理配置错误、DNS 解析失败、镜像源访问受限 或 网络防火墙限制 有关。以下是详细解决方案: 1. 检查并修复代理配置 如果你使用了 HTTP 代理: 确认代理地址是否有效(替换 speed.ip…...
Rundeck 介绍及安装:自动化调度与执行工具
Rundeck介绍 概述:Rundeck 是什么? Rundeck 是一款开源的自动化调度和任务执行工具,专为运维场景设计,帮助工程师通过统一的平台管理和执行跨系统、跨节点的任务。它由 PagerDuty 维护(2016 年收购)&#…...
济南国网数字化培训班学习笔记-第二组-6-输电线路现场教学
输电线路现场教学 杆塔组装 角钢塔 角钢-连扳-螺栓 螺栓(M): 脚钉-螺栓(螺栓头-无扣长-螺纹-螺帽)-垫片-螺帽/防盗帽/防松帽M20*45 表示直径20mm,长度45mm螺栓级别由一个类似浮点数表示,如…...
数据结构——二叉树,堆
目录 1.树 1.1树的概念 1.2树的结构 2.二叉树 2.1二叉树的概念 2.2特殊的二叉树 2.3二叉树的性质 2.4二叉树的存储结构 2.4.1顺序结构 2.4.2链式结构 3.堆 3.1堆的概念 3.2堆的分类 3.3堆的实现 3.3.1初始化 3.3.2堆的构建 3.3.3堆的销毁 3.3.4堆的插入 3.3.5…...
PostgreSQL 分区表——范围分区SQL实践
PostgreSQL 分区表——范围分区SQL实践 1、环境准备1-1、新增原始表1-2、执行脚本新增2400w行1-3、创建pg分区表-分区键为创建时间1-4、创建24年所有分区1-5、设置默认分区(兜底用)1-6、迁移数据1-7、创建分区表索引 2、SQL增删改查测试2-1、查询速度对比…...
第八节:进阶特性高频题-Pinia与Vuex对比
优势:无嵌套模块、Composition API友好、TypeScript原生支持 核心概念:state、getters、actions(移除mutation) 深度对比 Pinia 与 Vuex:新一代状态管理方案的核心差异 一、核心架构设计对比 维度VuexPinia设计目标集…...
路由交换网络专题 | 第七章 | BGP练习 | 次优路径 | Route-Policy | BGP认证
基本部分配置讲解: 配置BGP相关部分: // BGP区域配置: 用作环回口创建BGP对等体// “ipv4-family unicast”是指进入BGP的IPv4单播地址族视图。 // 配置完后仅仅只在IPV4地址簇下建立对等体。* [AR3]bgp 100 [AR3-bgp]peer 1.1.1.1 as-number 100 [AR…...
序论文42 | patch+MLP用于长序列预测
论文标题:Unlocking the Power of Patch: Patch-Based MLP for Long-Term Time Series Forecasting 论文链接:https://arxiv.org/abs/2405.13575v3 代码链接:https://github.com/TangPeiwang/PatchMLP (后台回复“交流”加入讨…...
【mongodb】系统保留的数据库名
目录 1. admin2. config3. local4. test(非严格保留,但常作为默认测试数据库)5. 注意事项6. 其他相关说明 1. admin 1.用途:用于存储数据库的权限和用户管理相关数据。2.特点:该数据库是 MongoDB 的超级用户数据库&am…...
js 的call 和apply方法用处
主要用于ECMAScript与宿主环境(文档对象(DOM)、浏览器对象(BOM))的交互中; 例子:function changeStyle(attr, value){ this.style[attr] value; } …...
济南国网数字化培训班学习笔记-第二组-2节-输电线路施工及质量
输电线路施工及质量 质量管控基本规定 基本规定 项目分类 土石方(测量挖坑)、基础、杆塔、架线、接地、线路防护 检验项目分类原则: 1.主控项目:影响工程性能、强度、安全性和可靠性,且不易修复和处理 2.一般项…...
“Daz to Unreal”将 G8 角色(包括表情)从 daz3d 导入到 UE5。在 UE5 中,我发现使用某个表情并与闭眼混合后,上眼睑出现了问题
1) Bake & Export Corrective Morphs from Daz before you go into UE5 1) 在进入 UE5 之前,从 Daz 烘焙并导出修正型变形 In Daz Studio 在 Daz Studio 中 Load your G8 head, dial in the exact mix (e.g. Smile 1.0 Eyes Closed 1.0). 加载你的 G8 头部&am…...
Linux系统之----进程优先级、调度与切换
在开启本篇文章的学习之前,我们先要熟悉如下两个事 1.概念 进程优先级指的是进程能得到某种资源的先后顺序,要理解好它与权限的关系,优先级是 能,拥有资源的先后顺序,权限是 能还是不能的问题 2.为什么要有优先级…...
Web3钱包开发功能部署设计
Web3钱包开发功能部署设计全景指南(2025技术架构与实战) ——从核心模块到多链生态的完整解决方案 一、核心功能模块设计 1.1 资产管理体系 Web3钱包的核心功能围绕资产存储、交易验证、多链兼容展开: • 密钥管理:…...
【含文档+PPT+源码】基于SpringBoot的开放实验管理平台设计与实现
项目介绍 本课程演示的是一款基于SpringBoot的开放实验管理平台设计与实现,主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的 Java 学习者。 1.包含:项目源码、项目文档、数据库脚本、软件工具等所有资料 2.带你从零开始部署运行本套系统…...
小刚说C语言刷题——1317正多边形每个内角的度数?
1.题目描述 根据多边形内角和定理,正多边形内角和等于:( n-2 ) 180∘ ( n 大于等于 3且 n 为整数) 请根据正多边形的边数,计算该正多边形每个内角的度数。(结果保留1位小数&#x…...
Spring—AOP
AOP是在不惊动原有的代码的基础上对功能进行增强操作 连接点:JoinPoint,可以被AOP控制的方法 通知:Advice,增强的逻辑,共性功能 切入点:PointCut,匹配连接点的条件,表明连接点中哪…...
算法训练营第二天| 209.长度最小的子数组、59.螺旋矩阵II、区间和
209.长度最小的子数组 题目 思路与解法 **第一想法:**无 carl的讲解: 滑动窗口 class Solution:def minSubArrayLen(self, target: int, nums: List[int]) -> int:ij0lens len(nums)sum 0res lens 1while j < lens:# for m in range(i, j1)…...
【C++ 真题】P3456 [POI2007] GRZ-Ridges and Valleys
[POI2007] GRZ-Ridges and Valleys 题面翻译 题目描述 译自 POI 2007 Stage 2. Day 0「Ridges and Valleys」 给定一个 n n n \times n nn 的网格状地图,每个方格 ( i , j ) (i,j) (i,j) 有一个高度 w i j w_{ij} wij。如果两个方格有公共顶点,…...
Vue3 中 computed的详细用法
Vue 3 中 computed 是一个非常重要的响应式 API,它是基于其依赖项的值来计算得出的值,当依赖项发生变化时,计算属性会自动更新 基本用法 在选项式 API 中,computed 通常作为一个选项直接在组件的选项对象中定义。例如 <temp…...
位带和位带别名区
位带区域和位带别名区域 位带区域(Bit-banding)是一种技术, 允许开发者直接访问和修改内存中的单个位。 这种技术在某些微控制器(如ARM Cortex-M系列)中特别有用,因为它可以简化对寄存器位的访问和修改。 …...
DRF凭什么更高效?Django原生API与DRF框架开发对比解析
一、原生 Django 开发 API 的局限性 虽然 Django 可以通过 JsonResponse 和视图函数手动构建 API,但存在以下问题: 手动序列化与反序列化 需要手动将模型实例转换为 JSON,处理复杂数据类型(如嵌套关系)时代码冗长且易…...
Agent智能体应用详解:从理论到实践的技术探索
一、Agent智能体是什么? 1. 核心定义 Agent智能体是能够感知环境、自主决策并执行动作以实现目标的软件实体。其核心特征包括: 自主性:无需外部指令持续运行。 反应性:实时响应环境变化。 目标导向:基于预设或学习…...
Windows下使用 VS Code + g++ 开发 Qt GUI 项目的完整指南
🚀 使用 VS Code g 开发 Qt GUI 项目的完整指南(Windows MSYS2) 本指南帮助你在 Windows 下使用 VS Code g CMake Qt6 快速搭建 Qt GUI 项目,适合熟悉 Visual Studio 的开发者向跨平台 VS Code 工具链迁移。 🛠️…...
arm64适配系列文章-第三章-arm64环境上mariadb的部署
ARM64适配系列文章 第一章 arm64环境上kubesphere和k8s的部署 第二章 arm64环境上nfs-subdir-external-provisioner的部署 第三章 arm64环境上mariadb的部署 第四章 arm64环境上nacos的部署 第五章 arm64环境上redis的部署 第六章 arm64环境上rabbitmq-management的部署 第七章…...
YOLOv8融合CPA-Enhancer【提高恶略天气的退化图像检测】
1.CPA介绍 CPA-Enhancer通过链式思考提示机制实现了对未知退化条件下图像的自适应增强,显著提升了物体检测性能。其插件式设计便于集成到现有检测框架中,并在物体检测及其他视觉任务中设立了新的性能标准,展现了广泛的应用潜力。 关于CPA-E…...
编译 C++ 报错“找不到 g++ 编译器”的终极解决方案(含 Windows/Linux/macOS)
前言 在使用终端编译 C 程序时,报错: 或类似提示,意味着你的系统尚未正确安装或配置 g 编译器。本篇将从零手把手教你在 Windows / Linux / macOS 下安装并配置 g,适用于新手或 C 入门阶段的你。 什么是 g? g 是 GN…...
Spring 过滤器详解:从基础到实战应用
Spring 过滤器详解:从基础到实战应用 引言 在 Spring 框架中,过滤器(Filter)是处理 HTTP 请求和响应的重要组件。它们为开发者提供了一种在请求到达控制器之前或响应返回客户端之前进行操作的机制。本文将深入探讨 Spring 中常见…...
达梦并行收集统计信息
达梦收集统计信息速度如何? 答:1分钟1G 大库收集起来可能比较慢,想并行收集需要一些条件 3个参数先了解一下 我把max_parallel_degree改为16 相关说明可以看一下 对一个3G的表收集 收集方法 DBMS_STATS.GATHER_TABLE_STATS( TEST,T1,…...
AOSP CachedAppOptimizer 冻结方案
背景 Android 一直面临一个核心难题:如何优化进程对有限系统资源(如 CPU、电量)的使用,同时保证用户体验。 当进程进入后台后,它们虽不再贡献用户体验,却仍可能消耗资源。传统的杀后台方案虽然节省资源&a…...