当前位置: 首页 > news >正文

Debezium Engine监听binlog实现缓存更新与业务解耦

飞书文档

解决缓存与数据源数据不一致的方案有很多, 各有优缺点;
1.0、旁路缓存策略, 直接同步更新
读取流程:

  1. 查询缓存。如果缓存命中,则直接返回结果。
  2. 如果缓存未命中,则查询数据库。
  3. 将数据库查询到的数据写入缓存,并设置一个过期时间。
    写入流程:
  4. 更新数据库中的数据。
  5. 删除缓存中的数据缓存。
    缺点:
  • 缓存穿透 (高并发情况下如果缓存未命中,需要查询数据库并回写缓存,这可能在高并发下场景增加数据库的负载)

  • 高并发环境下可能导致数据不一致,因为在删除Redis时,如果有其他请求线程已经读取了MySQL旧数据,然后缓存进去, 就会出现脏数据问题。
    伪代码:
    vodi updateData(id, newData) {
    // 更新MySQL
    mysql.update(“UPDATE table SET data = ? WHERE id = ?”, newData, id);

    // 更新Redis
    redis.del(“data:” + id);
    }
    2.0、延迟双删策略
    读取流程:

  1. 查询缓存。如果缓存命中,则直接返回结果。
  2. 如果缓存未命中,则查询数据库。
  3. 将数据库查询到的数据写入缓存,并设置一个过期时间。
    写入流程:
  4. 删除缓存中的数据缓存。
  5. 更新数据库中的数据。
  6. 延迟1~3S再删除缓存中的数据缓存。
    缺点:
  • 短时间的数据不一致, 但最终实现的效果是最终数据一致性, 不适合对实时性要求极高的场景。

  • 延迟删除不保证成功 (如需保证测需要重试策略)
    伪代码:
    void updateData(id, newData) {
    // 删除Redis缓存
    redis.delete(“data:” + id);

    // 更新MySQL
    mysql.update(“UPDATE table SET data = ? WHERE id = ?”, newData, id);

    // 延时任务,延时后再次删除Redis缓存
    scheduleTask(() => {
    redis.delete(“data:” + id);
    }, delayTime); // delayTime为延迟时间,例如1000毫秒
    }
    3.0、定时+增量更新策略
    读取流程:

  1. 查询缓存。如果缓存命中,则直接返回结果。
  2. 如果缓存未命中,则查询数据库。
  3. 将数据库查询到的数据写入缓存,并设置一个过期时间。
    缓存写入流程:
  4. 固定时间去拉取增量数据, 比如比标记时间大的数据。
  5. 更新进缓存里
    优点:
  • 减少负载:相比实时同步,定时+增量更新可以减少对数据库和缓存的压力,因为它不会在每次数据变更时立即进行同步。

  • 灵活性高:可以根据业务需求调整定时任务的频率和增量更新的策略。
    缺点:

  • 根据配置定时时间长短造成时间的数据不一致, 但最终实现的效果是最终数据一致性, 不适合对实时性要求极高的场景。

  • 需要针对不同的业务实现一套不同的定时+增量更新策略
    伪代码:
    void syncCache() {
    // 获取上次同步的时间戳
    Timestamp lastSyncTime = getLastSyncTime();

    // 查询自上次同步以来有变更的数据
    List updatedData = mysql.query(
    “SELECT * FROM table WHERE update_time > ?”, lastSyncTime);

    // 更新缓存
    for (Data data : updatedData) {
    redis.set(“data:” + data.id, data);
    }

    // 更新最后同步时间
    updateLastSyncTime(currentTime());
    }
    4.0、锁机制更新策略
    读取流程:

  1. 查询缓存。如果缓存命中,则直接返回结果。
  2. 如果缓存未命中, 向Redis上读锁。
  3. 查询数据库。
  4. 将数据库查询到的数据写入缓存,并设置一个过期时间 & 释放读锁。
    写入流程:
  5. 向Redis上写锁。
  6. 更新数据库中的数据。
  7. 删除缓存中的数据缓存。
  8. 释放写锁
    优点:
  • 数据强一致性。
    缺点:

  • 性能比其他方式差。
    伪代码:
    void save() {
    // 获取写锁
    RedissonClient client = RedissonClientUtil.getClient(“”);
    RReadWriteLock readWriteLock = client.getReadWriteLock(“myLock”);
    RLock writeLock = readWriteLock.writeLock();
    // 加锁
    writeLock.lock();
    // 查询自上次同步以来有变更的数据
    List updatedData = mysql.query(
    “SELECT * FROM table WHERE update_time > ?”, lastSyncTime);
    // 删除缓存
    redis.del(“data:” + data.id);

    // 最后释放锁
    writeLock.unlock();
    }
    5.0、异步更新策略
    Binlog 订阅方式, 这种策略已经和业务解耦开;
    读取流程:

  1. 查询缓存。如果缓存命中,则直接返回结果。
  2. 缓存未命中查询数据库。
  3. 将数据库查询到的数据写入缓存,并设置一个过期时间
    数据源写入流程:
  4. 更新数据库中的数据。
    缓存处理中间件:
    接收Binlog 订阅发送过来的数据;
    进行缓存的处理 (可以更新也可以删除)
    优点:
  • 数据最终一致性。
  • 和业务解耦, 业务代码不用再考虑数据源数据更新后缓存怎么更新。
    缺点:
  • 有延迟情况;
  • 实现成本与维护成本大
    大概流程如下图
    [图片]
    但是基础组件并不满足于公司复杂多变的业务场景, 需要基于基础组件实现定制化的异步更新策略;
    基于异步更新策略的架构设计方案
    CDC (Change data capture)
    [图片]
    不想引入mq?试试debezium小型项目当中,没有引入消息中间件,也不想引入,但需要解耦异步,那怎么办呢?CDC组件是 - 掘金
    从选项来看, Flink CDC 太重量级; sqoop,kettle,datax之类的工具,属于前大数据时代的产物,地位类似于web领域的structs2。而且,它们基于查询而非binlog日志,其实不属于CDC。首先排除, canal只能对MYSQL进行CDC监控。有很大的局限性。
    综上所述 debezium 较为合适;
    Debezium 介绍
    Debezium 构建在Apache Kafka的基础之上,并提供了一套与Kafka Connect兼容的连接器。每个连接器都与特定的数据库管理系统(DBMS)协同工作。连接器通过检测发生的变化来记录 DBMS 中数据变化的历史,并将每个变化事件的记录流式传输到 Kafka 主题。然后,消费应用程序可以从 Kafka 主题中读取由此产生的事件记录;
    通过利用 Kafka 可靠的流平台,Debezium 使应用程序能够正确、完整地消费数据库中发生的变化。即使应用程序意外停止或失去连接,也不会错过中断期间发生的事件。应用程序重新启动后,会从中断的位置继续读取主题。
    使用 Debezium 需要三个独立的服务:ZooKeeper、Kafka 和 Debezium 连接器服务,
    但是同时Debezium也支持并非每个应用程序都需要这种级别的容错性和可靠性,它们可能不希望依赖外部的 Kafka 代理集群和 Kafka 连接服务。相反,有些应用程序更愿意将 Debezium 连接器直接嵌入应用程序空间。它们仍然需要相同的数据变更事件,但更希望连接器能直接将其发送到应用程序,而不是在 Kafka 内持久化
    对应文档说明: Debezium Engine
    下面采用轻量级方式集成
    Debezium 连接器直接嵌入应用程序空间
    1.0、依赖关系
    Springboot 2.7.5, jdk8版本
    [图片]
    [图片]
    从上图看 debezium从1.6版本开始就需要 >= jdk11了; 那么我们只能使用1.5版本

[图片]
使用 1.5.4.Final jdk8支持的最新版本
<version.debezium>1.5.4.Final</version.debezium>

io.debezium debezium-api ${version.debezium} io.debezium debezium-embedded ${version.debezium} io.debezium debezium-connector-mysql ${version.debezium} 2.0 简单demo 暂时无法在飞书文档外展示此内容 在MySQL5.6与MySQL5.7版本上运行是正常的 3.0、架构设计图 暂时无法在飞书文档外展示此内容 3.1、整个架构分为 四 部分 1. Debezium Engine连接器管理应用 2. Debezium Engine连接器应用 3. Debezium 消息重试应用 4. Debezium Engine连接器消费应用 3.2、Debezium Engine连接器管理应用 (web页面可以先不做) 主体功能: 对外web服务, 用于管理连接器, 将连接器数据可视化等; > 和Debezium Engine连接器应用交互 管理连接器: (新增并启动连接器、删除并停止连接器(也会删除连接器相关offset文件)) 可视化的数据: (连接器相关信息、连接器运行状态 连接器已处理事件数量、失败数量、待重试数量、等) 3.3、Debezium Engine连接器应用 主体功能分为: 1. 连接器的启动/运行/停止 (分为项目启动时候 / 接收管理应用请求的的时候) 2. 事件的数据解析/发送下游 3. 监控指标收集 4. 异常事件重试&记录&告警 CREATE DATABASE debezium_config_manage; 相关的表: debezium_connect CREATE TABLE `debezium_connect_base_info` ( `id` bigint(20) unsigned NOT NULL COMMENT '不用自增(使用顺序雪花)', `business_describe` varchar(255) NOT NULL DEFAULT '' COMMENT '连接器业务描述', `connect_db_type` varchar(30) NOT NULL DEFAULT '' COMMENT '连接DB类型(MySQL数据库:MySQL)', `connect_name` varchar(255) NOT NULL DEFAULT '' COMMENT '连接器名称', `connect_status` varchar(20) NOT NULL DEFAULT 'wait' COMMENT '连接器状态(run:运行中、wait:待运行、stop:停止)', `current_finish_num` bigint(20) unsigned NOT NULL DEFAULT 0 COMMENT '当前完成数 (非实时)', `total_finish_num` bigint(20) unsigned NOT NULL DEFAULT 0 COMMENT '总完成数 (非实时)', `wait_finish_retry_num` bigint(20) unsigned NOT NULL DEFAULT 0 COMMENT '待完成重试数 (实时)', `total_finish_retry_num` bigint(20) unsigned NOT NULL DEFAULT 0 COMMENT '总完成重试数 (实时)', `is_delete` tinyint(1) NOT NULL DEFAULT 0 COMMENT '删除状态(1:删除,0:未删除)', `last_operator_id` bigint(20) unsigned NOT NULL DEFAULT 0 COMMENT '最后操作人ID', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `version` bigint(20) unsigned NOT NULL DEFAULT 0 COMMENT '版本号', `remark` varchar(255) NOT NULL DEFAULT '' COMMENT '备注', PRIMARY KEY (`id`), CONSTRAINT UNIQUE KEY `idx_connect_name_connect_db_type` (`connect_name`,`connect_db_type`), KEY `idx_create_time` (`create_time`), KEY `idx_update_time` (`update_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='连接器基础信息表'; debezium_connect_param CREATE TABLE `debezium_connect_param` ( `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID', `connect_base_info_id` bigint unsigned NOT NULL DEFAULT '0' COMMENT '连接器基础表ID', `database_table_list` text COMMENT '监控的多个的数据库和表 (account.user)格式 , 逗号分隔', `database_history_file_filename` varchar(100) NOT NULL DEFAULT '' COMMENT 'dbhistory文件名称 (唯一值), 不包含路径(x.txt)', `offset_storage_file_filename` varchar(100) NOT NULL DEFAULT '' COMMENT 'offset文件名称 (唯一值), 不包含路径(x.dat)', `database_server_id` bigint unsigned NOT NULL DEFAULT '0' COMMENT '连接Debezium 服务的 id(唯一值)', `connect_param_json` text COMMENT '剩余连接器JSON参数', `is_delete` tinyint(1) NOT NULL DEFAULT '0' COMMENT '删除状态(1:删除0:未删除)', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `remark` varchar(255) NOT NULL DEFAULT '' COMMENT '备注', PRIMARY KEY (`id`), UNIQUE KEY `idx_database_history_file_filename` (`database_history_file_filename`), UNIQUE KEY `idx_database_server_id` (`database_server_id`), UNIQUE KEY `idx_offset_storage_file_filename` (`offset_storage_file_filename`), KEY `idx_connect_base_info_id` (`connect_base_info_id`), KEY `idx_create_time` (`create_time`), KEY `idx_update_time` (`update_time`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='连接器参数表'; debezium_message_invoke CREATE TABLE `debezium_message_invoke` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `connect_base_info_id` bigint(20) unsigned NOT NULL DEFAULT 0 COMMENT '连接器基础表ID', `invoke_type` varchar(50) NOT NULL DEFAULT '' COMMENT '调用方式 (http、MQ)', `http_invoke_address` varchar(255) NOT NULL DEFAULT '' COMMENT 'http的调用地址', `mq_invoke_address` varchar(255) NOT NULL DEFAULT '' COMMENT 'mq的调用route、topic (JSON方式)', `invoke_extra_mark` varchar(255) NOT NULL DEFAULT '' COMMENT '调用额外带上的标识', `message_max_retry` int(20) unsigned NOT NULL DEFAULT 0 COMMENT '消息最大重试次数', `message_retry_interval` int(20) unsigned NOT NULL DEFAULT 0 COMMENT '消息重试间隔(单位分钟)', `is_delete` tinyint(1) NOT NULL DEFAULT 0 COMMENT '删除状态(1:删除0:未删除)', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `remark` varchar(255) NOT NULL DEFAULT '' COMMENT '备注', CONSTRAINT PRIMARY KEY (`id`), KEY `idx_connect_base_info_id` (`connect_base_info_id`), KEY `idx_create_time` (`create_time`), KEY `idx_update_time` (`update_time`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='连接器消息调用方式'; debezium_connect_operation_record CREATE TABLE `debezium_connect_operation_record` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `connect_base_info_id` bigint(20) unsigned NOT NULL DEFAULT 0 COMMENT '连接器基础表ID', `operator_id` bigint(20) unsigned NOT NULL DEFAULT 0 COMMENT '操作人ID', `operator_type` varchar(50) NOT NULL DEFAULT '' COMMENT '操作人类型 (user:用户, system:系统)', `operation_type` varchar(50) NOT NULL DEFAULT '' COMMENT '操作类型 (add:添加连接器, update:修改连接器、del:删除连接器, updateCount:更新统计信息)', `operation_content` TINYTEXT COMMENT '操作JSON参数', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `remark` varchar(255) NOT NULL DEFAULT '' COMMENT '备注', CONSTRAINT PRIMARY KEY (`id`), KEY `idx_connect_base_info_id` (`connect_base_info_id`), KEY `idx_operator_id_operator_type` (`operator_id`,`operator_type`), KEY `idx_create_time` (`create_time`), KEY `idx_update_time` (`update_time`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='连接器操作记录表'; debezium_connect_message_retry CREATE TABLE `debezium_connect_message_retry` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `connect_base_info_id` bigint(20) unsigned NOT NULL DEFAULT 0 COMMENT '连接器基础表ID', `operator_content` TINYTEXT COMMENT '需重试的JSON参数', `next_retry_time` datetime NOT NULL COMMENT '下一次重试时间', `message_current_retry` int(20) unsigned NOT NULL DEFAULT 0 COMMENT '消息当前重试次数', `message_status` varchar(255) NOT NULL DEFAULT 'wait' COMMENT '消息状态(wait:待执行, run:执行中, finish:执行完成)' `message_retry_status` varchar(255) NOT NULL DEFAULT '' COMMENT '消息重试状态(success:成功, fail:失败)' `is_delete` tinyint(1) NOT NULL DEFAULT 0 COMMENT '删除状态(1:删除0:未删除)', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `remark` varchar(255) NOT NULL DEFAULT '' COMMENT '备注' CONSTRAINT PRIMARY KEY (`id`), KEY `idx_connect_base_info_id` (`connect_base_info_id`), KEY `idx_next_retry_time` (`next_retry_time`), KEY `idx_create_time` (`create_time`), KEY `idx_update_time` (`update_time`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='连接器消息重试表'; 无人为介入流程是: 项目启动 > 从数据库拉取所有未删除的连接器 > 进行启动 > 并启动一个间隔一分钟统计一次数据的监控指标线程 监控binlog信息 > 解析成为可读的请求消息 > 根据连接器调用方式进行调用下游 当消息调用失败, 则进行简单重试 3次 > 继续失败后 > 构建重试对象插入到重试表 (让重试服务进行拉取重试) 项目停止 > 停止所有的连接器 从Debezium Engine连接器管理应用来的请求流程大概是: 接收请求 > 校验请求合法性 > 校验请求参数合法性 > 根据类型做启动/停止对应连接器; PS: 在上面的各个重点操作节点 (都会进行机器人告警/日志打印) 日志级别是可动态调整的; [图片] 3.4、Debezium 消息重试应用 该应用主体功能就是 做多次失败的消息的重试; 项目启动之后, 启动一个线程池 + 一个线程组, 不断间隔定时循环 > 拉取debezium_connect_message_retry 表中未删除的数据, 进行关联查询相关信息, 进行消息重试; [图片] 3.5、Debezium Engine连接器消费应用 主要功能是: 接收连接器上游的调用, 解析统一的调用参数; 然后做自己的业务, 比如说是 做Redis的缓存更新, 如果进行Redis的处理失败了则进行简单的重试; 比如接收下面图片的参数 [图片] [图片] [图片] [图片] 4.0、剩余待解决的问题 (会议上记录) 4.1、Debezium Engine连接器高可用 (无需考虑高可用) 如果要实现连接器高可用情况, 多节点部署, 就需要考虑解决消息只消费一次的情况与性能情况; 4.2、多个 Debezium Engine连接器 对数据库的性能影响 (无影响) Debezium does not impact source database performance [图片] Debezium 官方不推荐对同一个数据源使用多个连接器,建议通过调整连接器配置来满足需求; 但是存在如果声音一个engine的情况, 监听延迟会变长; 4.2、 (会议上补充) 做成2个应用 [图片] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~end~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4.3、(会议上补充) 消费应用增加 表 与 Redis keys的 映射关系 CREATE TABLE `auto_handle_redis_mapping` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `handle_table` varchar(255) NOT NULL DEFAULT '' COMMENT '处理的表名称', `handle_key` varchar(2555) NOT NULL DEFAULT '' COMMENT '处理的Redis_key集, 逗号分隔(例如:device_cache_id_{#deviceId})', `extra_groovy_script_file_path` TINYTEXT COMMENT '额外groovy脚本执行文件', `is_delete` tinyint(1) NOT NULL DEFAULT 0 COMMENT '删除状态(1:删除0:未删除)', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `remark` varchar(255) NOT NULL DEFAULT '' COMMENT '备注' CONSTRAINT PRIMARY KEY (`id`), KEY `idx_message_handle_table` (`handle_table`,`handle_key`), KEY `idx_create_time` (`create_time`), KEY `idx_update_time` (`update_time`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='自动处理Redis删除逻辑表与keys映射'; 4.4、(会议上补充) 消费服务增加延迟双删除 4.5、 (会议上补充) 业务的缓存处理 5.0、Redis容量估算 集成demo遇到的错误: 启动失败 [图片] 检索后和尝试发现是MySQL连接版本不对, 默认的版本是 8.0.31 降级为8.0.27还是不行, 最终降级为8.0.21正常! io.debezium debezium-connector-mysql ${version.debezium} mysql mysql-connector-java mysql mysql-connector-java 8.0.21 Interrupted while emitting initial DROP TABLE events [图片] 原因被主线程关闭了, 解决方法开启新线程 debezium # offset 文件不生成 参考的Spring boot 整合demo https://juejin.cn/post/7348003004122939429 原因有个坑, GitHub源码没有调用该方法, 少了下图标记调用的方法, offset文件就不会生成! [图片]

应用到生产的源码:
(加密)
暂时无法在飞书文档外展示此内容
暂时无法在飞书文档外展示此内容
采用kafka方式 (暂不研究):
ZooKeeper服务, 目前我们已经在使用, 如果要独立出来, 可以单独配置一台 (生产 : 1核心1GB内存配置)
Kafka服务 (生产集群, 配置4核心8G内存配置, 硬盘SSD)
Debezium连接器服务 (生产集群, 配置4核心8G内存配置, 硬盘SSD)
测试环境 (可以将 三个服务部署在同一台机子, 只需要2核心4G)
运行启动步骤:
MySQL启用binlog
1、启动ZK
2、启动kafka
3、启动Debezium连接器

1

相关文章:

Debezium Engine监听binlog实现缓存更新与业务解耦

飞书文档 解决缓存与数据源数据不一致的方案有很多, 各有优缺点; 1.0、旁路缓存策略, 直接同步更新 读取流程&#xff1a; 查询缓存。如果缓存命中&#xff0c;则直接返回结果。如果缓存未命中&#xff0c;则查询数据库。将数据库查询到的数据写入缓存&#xff0c;并设置一个…...

docker搭建socks5代理

准备工作 VPS安全组/策略放行相应端口如启用了防火墙&#xff0c;放行相应端口 实际操作 我们选用“历史悠久”的Dante socks5 代理服务器&#xff0c;轻量、稳定。Github也有对dante进行进一步精简的镜像&#xff0c;更为适宜。github项目地址如下&#xff1a; https://gi…...

scanf函数和printf函数的格式化输入输出

#include<stdio.h> int main() {int a;double b;char c;scanf("a%d,b%lf:c%c",&a,&b,&c); //float型输入时使用%f占位&#xff0c;double型使用%lf占位&#xff1b;输出时二者相同都是%f即可。if(a>0)printf("a%-10d,b%20.3lf,c%c",a…...

Day31 贪心算法 part05

56. 合并区间 本题也是重叠区间问题&#xff0c;如果昨天三道都吸收的话&#xff0c;本题就容易理解了。 代码随想录 class Solution {public int[][] merge(int[][] intervals) {Arrays.sort(intervals, (a,b) -> Integer.compare(a[0], b[0]));List<int[]> result …...

uniapp连接mqtt频繁断开原因和解决方法

mqtt参考文档&#xff1a;MQTT.js 入门教程 | EMQ、MQTT.js 入门教程 - EMQX - 博客园 uniapp引用MQTT频繁断开的问题可能由于以下几个原因导致&#xff1a; 网络不稳定&#xff1a;频繁断开可能是由于网络不稳定导致的&#xff0c;可以尝试优化网络连接。 心跳机制问题&…...

【数据结构-队列】力扣641. 设计循环双端队列

设计实现双端队列。 实现 MyCircularDeque 类: MyCircularDeque(int k) &#xff1a;构造函数,双端队列最大为 k 。 boolean insertFront()&#xff1a;将一个元素添加到双端队列头部。 如果操作成功返回 true &#xff0c;否则返回 false 。 boolean insertLast() &#xff1…...

leetcode3250. 单调数组对的数目 I,仅需1s

题目&#xff1a; https://leetcode.cn/problems/find-the-count-of-monotonic-pairs-i/description/ 不为别的&#xff0c;只是记录下这个超过100%&#xff0c;而且比原先最快的快了一个量级 不知道咋分析&#xff0c;反正得出结论就是&#xff0c;变大不变&#xff0c;变小…...

安全基线检查

一、安全基线检测基础知识 安全基线的定义 安全基线检查的内容 安全基线检查的操作 二、MySQL的安全基线检查 版本加固 弱口令 不存在匿名账户 合理设置权限 合理设置文件权限 日志审核 运行账号 可信ip地址控制 连接数限制 更严格的基线要求 1、禁止远程连接数据库 2、修改…...

C#读取本地图像的方法总结

前言&#xff1a; 大家好&#xff0c;我是上位机马工&#xff0c;硕士毕业4年年入40万&#xff0c;目前在一家自动化公司担任软件经理&#xff0c;从事C#上位机软件开发8年以上&#xff01;我们在C#开发C#程序的时候&#xff0c;有时候需要读取本地图像&#xff0c;下面进行详…...

力扣81:搜索旋转排序数组II

已知存在一个按非降序排列的整数数组 nums &#xff0c;数组中的值不必互不相同。 在传递给函数之前&#xff0c;nums 在预先未知的某个下标 k&#xff08;0 < k < nums.length&#xff09;上进行了 旋转 &#xff0c;使数组变为 [nums[k], nums[k1], ..., nums[n-1], n…...

信息系统项目管理-论文写作方法之背景二

为响应国家政务服务“一网、一门、一次”改革&#xff0c;打破“信息孤岛”现象&#xff0c;打造线上线下相融合、多级联动的政务服务一体化平台。XX市行政审批局欲整合市局及下属13镇区、500多个村居委会政务服务中心业务&#xff0c;梳理人社、民政、卫计委、公积金、交通等多…...

使用ffmpeg命令实现视频文件间隔提取帧图片

将视频按每隔五秒从视频中提取一张图片 使用 ffmpeg 工具&#xff0c;通过设置 -vf&#xff08;视频过滤器&#xff09;和 -vsync 选项 命令格式 ffmpeg -i input_video.mp4 -vf "fps1/5" output_%03d.png 解释&#xff1a; -i input_video.mp4&#xff1a;指定输…...

我们项目要升级到flutter架构的几点原因

一、探索 Flutter打造卓越移动应用的新时代框架 在移动应用开发的世界里&#xff0c;Flutter已经成为了一个炙手可热的话题。诞生于Google的怀抱&#xff0c;Flutter以其独特的优势和理念&#xff0c;正在引领一场全球范围内的应用开发 ** 。本文将深入探讨Flutter项目的特点、…...

【简单好抄保姆级教学】javascript调用本地exe程序(谷歌,edge,百度,主流浏览器都可以使用....)

javascript调用本地exe程序 详细操作步骤结果 详细操作步骤 在本地创建一个txt文件依次输入 1.指明所使用注册表编程器版本 Windows Registry Editor Version 5.00这是脚本的第一行&#xff0c;指明了所使用的注册表编辑器版本。这是必需的&#xff0c;以确保脚本能够被正确解…...

ElasticSearch为什么不能在query阶段直接返回_id,从而避免fetch?

整理自Github的一个issue,也正好解答了我的疑惑 https://github.com/elastic/elasticsearch/issues/17159 提问 是否可以避免搜索的fetch阶段并仅返回文档ID&#xff1f;查询阶段结束时是否有_id&#xff0c;这样当我只需要_id时&#xff0c;fetch就多余了&#xff1f;可以通过…...

网安瞭望台第5期 :7zip出现严重漏洞、识别网络钓鱼诈骗的方法分享

国内外要闻 7 - Zip存在高危漏洞&#xff0c;请立刻更新 2024 年 11 月 24 日&#xff0c;do son 报道了 7 - Zip 中存在的一个高严重性漏洞 CVE - 2024 - 11477。7 - Zip 是一款广受欢迎的文件压缩软件&#xff0c;而这个漏洞可能会让攻击者在存在漏洞的系统中执行恶意代码。…...

获 2023 年度浙江省科学技术进步奖一等奖 | 网易数智日报

11 月 22 日&#xff0c;加快建设创新浙江因地制宜发展新质生产力动员部署会暨全省科学技术奖励大会在杭州隆重召开。浙江大学、网易数智等单位联合研发的“大规模结构化数据智能计算平台及产业化”项目获得 2023 年度浙江省科学技术进步奖一等奖。 加快建设创新浙江因地制宜发…...

SQL基础入门 —— SQL概述

目录 1. 什么是SQL及其应用场景 SQL的应用场景 2. SQL数据库与NoSQL数据库的区别 2.1 数据模型 2.2 查询语言 2.3 扩展性 2.4 一致性与事务 2.5 使用场景 2.6 性能与扩展性 总结 3. 常见的SQL数据库管理系统&#xff08;MySQL, PostgreSQL, SQLite等&#xff09; 3.…...

【附录】Rust国内镜像设置

目录 前言 &#xff08;1&#xff09;设置环境变量 &#xff08;2&#xff09;安装Rust &#xff08;3&#xff09;设置crates镜像 前言 本节课来介绍下如何在国内高速下载安装Rust和Rust依赖&#xff0c;由于网络原因&#xff0c;我们在安装Rust和下载项目依赖时都很慢&am…...

量化交易系统开发-实时行情自动化交易-8.2.发明者FMZ平台

19年创业做过一年的量化交易但没有成功&#xff0c;作为交易系统的开发人员积累了一些经验&#xff0c;最近想重新研究交易系统&#xff0c;一边整理一边写出来一些思考供大家参考&#xff0c;也希望跟做量化的朋友有更多的交流和合作。 接下来会对于发明者FMZ平台介绍。 发明…...

【配置 YOLOX 用于按目录分类的图片数据集】

现在的图标点选越来越多&#xff0c;如何一步解决&#xff0c;采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集&#xff08;每个目录代表一个类别&#xff0c;目录下是该类别的所有图片&#xff09;&#xff0c;你需要进行以下配置步骤&#x…...

ios苹果系统,js 滑动屏幕、锚定无效

现象&#xff1a;window.addEventListener监听touch无效&#xff0c;划不动屏幕&#xff0c;但是代码逻辑都有执行到。 scrollIntoView也无效。 原因&#xff1a;这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作&#xff0c;从而会影响…...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。

1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj&#xff0c;再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...

【生成模型】视频生成论文调研

工作清单 上游应用方向&#xff1a;控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

Rust 开发环境搭建

环境搭建 1、开发工具RustRover 或者vs code 2、Cygwin64 安装 https://cygwin.com/install.html 在工具终端执行&#xff1a; rustup toolchain install stable-x86_64-pc-windows-gnu rustup default stable-x86_64-pc-windows-gnu ​ 2、Hello World fn main() { println…...

Python实现简单音频数据压缩与解压算法

Python实现简单音频数据压缩与解压算法 引言 在音频数据处理中&#xff0c;压缩算法是降低存储成本和传输效率的关键技术。Python作为一门灵活且功能强大的编程语言&#xff0c;提供了丰富的库和工具来实现音频数据的压缩与解压。本文将通过一个简单的音频数据压缩与解压算法…...

Python 高级应用10:在python 大型项目中 FastAPI 和 Django 的相互配合

无论是python&#xff0c;或者java 的大型项目中&#xff0c;都会涉及到 自身平台微服务之间的相互调用&#xff0c;以及和第三发平台的 接口对接&#xff0c;那在python 中是怎么实现的呢&#xff1f; 在 Python Web 开发中&#xff0c;FastAPI 和 Django 是两个重要但定位不…...

FTXUI::Dom 模块

DOM 模块定义了分层的 FTXUI::Element 树&#xff0c;可用于构建复杂的终端界面&#xff0c;支持响应终端尺寸变化。 namespace ftxui {...// 定义文档 定义布局盒子 Element document vbox({// 设置文本 设置加粗 设置文本颜色text("The window") | bold | color(…...

Python爬虫(四):PyQuery 框架

PyQuery 框架详解与对比 BeautifulSoup 第一部分&#xff1a;PyQuery 框架介绍 1. PyQuery 是什么&#xff1f; PyQuery 是一个 Python 的 HTML/XML 解析库&#xff0c;它采用了 jQuery 的语法风格&#xff0c;让开发者能够用类似前端 jQuery 的方式处理文档解析。它的核心特…...