当前位置: 首页 > 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平台介绍。 发明…...

MATLAB —— 机械臂工作空间分析

系列文章目录 前言 本示例展示了如何使用可操作性指数对不同类型的机械手进行工作空间分析。工作空间分析是一种有用的工具&#xff0c;可用于确定机器人工作空间中最容易改变末端效应器位置和方向的区域。本示例的重点是利用不同的可操控性指数类型来分析各种机械手的工作空间…...

向日葵连接xrdp虚拟桌面

x2go的虚拟性没有那么好。而xrdp&#xff0c;可以实现较好的配置&#xff0c;并且能适应本机电脑的分辨率&#xff0c;非常方便。 配置xrdp可以参考这个&#xff1a; https://blog.csdn.net/weixin_54227557/article/details/143303803 然后就是重启相关服务了。 sudo pkill…...

AI智算-正式上架GPU资源监控概览 Grafana Dashboard

下载链接 https://grafana.com/grafana/dashboards/22424-ai-gpu-20241127/...

goframe框架bug-记录

implement not found for interface ICompany, forgot register? 错误解决检查&#xff1a; 1.有没有init 2. 注入问题 3. 注入问题...

对偶分解算法详解及其Python实现

目录 对偶分解算法详解及其实现第一部分:对偶分解算法概述1.1 什么是对偶分解算法1.2 应用场景1.3 算法优点第二部分:对偶分解算法的数学推导2.1 问题形式2.2 对偶问题2.3 算法框架第三部分:对偶分解算法的Python实现第四部分:案例1——支持向量机中的对偶分解(策略模式)…...

C# WinForm怎么使用COM组件

首先在右边自己的项目上右键→添加→引用 然后在 引用管理器 的 COM 分页下选择自己要添加的COM组件&#xff0c;当然前提是你已经用 regsvr32 命令注册过了此COM组件到注册表&#xff0c;如果还没有注册在这个列表里是看不到的。 选择好后点确定&#xff0c;就会在右边你的工程…...

【Python】深入理解Python的字符串处理与正则表达式:文本处理的核心技能

《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 字符串处理和正则表达式是数据清洗和文本分析中的重要工具,广泛应用于自然语言处理、数据爬取和格式化输出等领域。本文章详细讲解Python中的字符串操作技巧,以及如何高效使用正则表达式完成复杂文本匹配…...

【开源项目】2024最新PHP在线客服系统源码/带预知消息/带搭建教程

简介 随着人工智能技术的飞速发展&#xff0c;AI驱动的在线客服系统已经成为企业提升客户服务质量和效率的重要工具。本文将探讨AI在线客服系统的理论基础&#xff0c;并展示如何使用PHP语言实现一个简单的AI客服系统。源码仓库地址&#xff1a;ym.fzapp.top 在线客服系统的…...

OpenCV从入门到精通实战(五)——dnn加载深度学习模型

从指定路径读取图像文件、利用OpenCV进行图像处理&#xff0c;以及使用Caffe框架进行深度学习预测的过程。 下面是程序的主要步骤和对应的实现代码总结&#xff1a; 1. 导入必要的工具包和模型 程序开始先导入需要的库os、numpy、cv2&#xff0c;同时导入utils_paths模块&…...

【Leetcode Top 100】142. 环形链表 II

问题背景 给定一个链表的头节点 h e a d head head&#xff0c;返回链表开始入环的第一个节点。 如果链表无环&#xff0c;则返回 n u l l null null。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 n e x t next next 指针再次到达&#xff0c;则链表中存在环。 为了…...

游戏私服发布网站怎么做/小程序商城制作一个需要多少钱

uedtior errorhandler 配置文件加载失败 这个uedtior太扯淡了&#xff0c;在本地idea和tomcat上各种没问题&#xff0c;一上线就不能上传图片&#xff0c;我试过了网上说的各种方法都不管用。最后我用一个十分扯淡的方式解决了。 我的框架是springboot 在后端有ueditor包&…...

济南做网站优化价格/seo好seo

一、背景 记录一下&#xff0c;密码学中的常用背景知识&#xff1a;双线性映射。下面两篇文章的背景知识都有「双线性映射」 第一幅图中3.1 Composite Order Bilinear Map翻译过来是「合数阶双线性映射」 这里直接搬运刘巍然大佬博客的文章&#xff0c;vJava密码学原型算法实…...

wordpress 高亮代码/seo指的是什么意思

引言互联网时代&#xff0c;信息传输的基础媒介是比特流&#xff0c;即承载着各种有效信息的01串。换句话说&#xff0c;我们在手机上或者电脑上看到的各类媒体信息&#xff0c;例如文字信息、图片信息亦或是视频信息&#xff0c;其根源上都是一些由二进制的0和1组成的比特流。…...

洛阳市伊滨区建设局网站/球队世界排名榜

令牌桶算法 令牌桶算法(Token Bucket)和 Leaky Bucket 效果一样但方向相反的算法,更加容易理解.随着时间流逝,系统会按恒定1/QPS时间间隔(如果QPS100,则间隔是10ms)往桶里加入Token(想象和漏洞漏水相反,有个水龙头在不断的加水),如果桶已经满了就不再加了.新请求来临时,会各自拿…...

wordpress posts_nav_link/湖南专业seo优化

我执行了一个impdp&#xff0c;但它没有完成&#xff0c;因为表空间中没有空间。我停止了impdb&#xff0c;现在我需要删除新建用户及其下的对象&#xff1a;SQL> drop user TEST cascade;drop user TGK_EXOR_IFIL_008_432 cascade*ERROR at line 1:ORA-00604: error occurr…...

杭州建德网站建设/万物识别扫一扫

在前几次的Server2008实验里面&#xff0c;我们向服务器FS01、FS02分别添加了一个磁盘分区E盘。但是没有介绍我们是如何通过VMWare Workstation来实现的。今天就让我们来一起利用VMWare Workstation来向虚拟主机添加一块新的硬盘并启用。利用虚拟机做实验&#xff0c;添加硬件&…...