使用Debezium、Postgres和Kafka进行数据实时采集(CDC)
码匠君
9小时前
1. 背景
一直在完善自己的微服务架构,其中包含分布式工作流服务的建设,目前采用的是Camunda工作流引擎。使用Camunda工作流,就会涉及到工作流引擎的用户体系如何与现有用户体系集成的问题(Flowable、Activity也类似)。现有设计中,工作流定位偏重于企业内部流程的流转,因此系统中设计了单位、部门、人员以及人事归属与Camunda工作流用户体系对应。
功能设计完成,就面临另外一个问题,如何解决现有人事体系数据如何【`实时`】同步至Camunda工作流引擎中。如果现有体系数据与工作流数据在同一个库中,相对比较好解决。而微服务架构中,不同服务的数据通常存放在不同数据库中,那么就需要进行数据的同步。采用的方式不同,可以取得的效果也相同。
最初考虑如下两种方案,但是都略感不足:
ETL:使用ETL工具进行数据同步是典型的方式,可以选择工具也比较多。开源的ETL工具增量同步问题解决的并不理想,不使用增量同步数那么数据同步始终存在时间差;商业的ETL工具增量同步解决的比较好,但是庞大且昂贵。
消息队列:消息队列是多系统集成普遍采用的方式,可以很好地解决数据同步的实时问题。但是数据同步的两端都需要自己编写代码,一端写生产代码一端写消费代码,生产端代码还要捆绑现有体系数据所有操作,需要的编写量比较大。
查询对比的大量的资料,最终选择了Debezimu来解决以上问题以及未来更多数据同步的问题。
2. Debezium介绍
RedHat开源的Debezium是一个将多种数据源实时变更数据捕获,形成数据流输出的开源工具。
它是一种CDC(Change Data Capture)工具,工作原理类似大家所熟知的Canal, DataBus, Maxwell等,是通过抽取数据库日志来获取变更的。
官方介绍为:
Debezium is an open source distributed platform for change data capture. Start it up, point it at your databases, and your apps can start responding to all of the inserts, updates, and deletes that other apps commit to your databases. Debezium is durable and fast, so your apps can respond quickly and never miss an event, even when things go wrong
Debezium是一个分布式平台,它将您现有的数据库转换为事件流,因此应用程序可以看到数据库中的每一个行级更改并立即做出响应。Debezium构建在Apache KAFKA之上,并提供Kafka连接兼容的连接器来监视特定的数据库管理系统。
Debezium现在已支持以下数据库:
MySQL
MongoDB
PostgreSQL
Oracle
SQL Server
Db2
Cassandra
Vitess
与ETL不同,Debezimu只支持在生产端连接数据库,消费端不支持连接数据库,而是需要自己编写代码接收Kafka消息数据。分析下来这种方式更加灵活,还可以很好利用现有微服务架构中的Kafka。
3. 快速搭建Debezimu测试环境。
目前,Debezium最新的Stable版本是1.6。 Debezium已经把要用到的Component打包成了Docker的Image,因此,我们只需要安装并启动Docker后就可以按下面的步骤快速搭建测试环境了。
3.1 运行Zookeeper
docker run -it --name zookeeper -p 2181:2181 -p 2888:2888 -p 3888:3888 debezium/zookeeper:1.6
3.2 运行Kafka
docker run -it --name kafka -p 9092:9092 --link zookeeper:zookeeper debezium/kafka:1.6
3.3 运行PostgreSQL
docker run -it --rm --name postgres -p 5432:5432 -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=postgres debezium/example-postgres:1.6
上面代码中使用的是:
debezium/example-postgres:1.6,查看Debezimu官方文档以及其它示例都是这个。实际上Debezimu对postgresql 9~13都进行了Docker封装,可以根据自己的需要在Docker Hub中选择相应的PostgreSQL版本。
debezium/postgres很小,使用也比较方便,而且也进行了必要的设置,无须再进行额外的配置就可以直接使用。
3.4 运行Debezimu Connect
docker run -it --rm --name connect -p 8083:8083 -e GROUP_ID=1 -e CONFIG_STORAGE_TOPIC=my_connect_configs -e OFFSET_STORAGE_TOPIC=my_connect_offsets -e STATUS_STORAGE_TOPIC=my_connect_statuses --link zookeeper:zookeeper --link kafka:kafka --link postgres:postgres debezium/connect:1.6
Debezium的container启动时需要传入如下环境变量:
GROUP_ID: 分组ID,若需要启动多个Debezium的实例组成集群,那么它们的GROUP_ID必须被设置为一样
CONFIG_STORAGE_TOPIC:下面需要调用Debezium提供的RestFUL API管理connector,connector的信息就是保存在CONFIG_STORAGE_TOPIC指定的kafka topic下。
OFFSET_STORAGE_TOPIC: connector监控数据流的offset,若我们使用的是PostgreSQL Connector,那么OFFSET_STORAGE_TOPIC指定的topic中存的就是PostgreSQL的lsn。
3.5 创建Connector
经过上面4个步骤后,Debezium的测试环境就搭建好了,现在需要调用Debezium提供的API创建connector,使Debezium与数据库之间建立关系。我们把下面的payload POST到`http://:8083/connectors/`。
{
"name": "fulfillment-connector",
"config": {
"connector.class": "io.debezium.connector.postgresql.PostgresConnector",
"database.hostname": "192.168.99.100",
"database.port": "5432",
"database.user": "postgres",
"database.password": "postgres",
"database.dbname" : "postgres",
"database.server.name": "fulfillment",
"table.include.list": "public.inventory"
}
}
"name":注册到Kafka Connect服务的Connector名称
"connector.class":PostgreSQL connector class名称
"database.hostname":PostgreSQL 数据库地址
"database.port":PostgreSQL 数据库端口
"database.user":PostgreSQL 数据库用户名
"database.password":PostgreSQL数据密码
"database.dbname":连接的PostgreSQL数据库
"database.server.name":虚拟的数据库Server名称,可以根据实际需求定义,消费Kafka数据时要使用该值
"table.include.list":监听的数据表列表,以","分割。PostgreSQL要将表名写全,格式"."。如果没有特定的Schema,那么就是默认的`public`
下面为完成的curl命令:
curl -i -X POST -H "Accept:application/json" -H "Content-Type:application/json" localhost:8083/connectors/ -d '{"name": "fulfillment-connector", "config": {"connector.class": "io.debezium.connector.postgresql.PostgresConnector", "database.hostname": "192.168.99.100", "database.port": "5432", "database.user": "postgres", "database.password": "postgres", "database.dbname" : "postgres", "database.server.name": "fulfillment", "table.include.list": "public.inventory" }}'
上面是示例,因为使用的是Windows,个人觉得curl不方便,换用postman:
3.6 Docker Compose 配置
为了方便使用,将以上Docker命令整合为Docker Compose配置,具体如下:
version: "3"
services:
postgres:
image: debezium/postgres:13
container_name: postgres
hostname: postgres
environment:
POSTGRES_USER: herodotus
POSTGRES_PASSWORD: herodotus
ports:
- 5432:5432
zookeeper:
image: debezium/zookeeper:1.6
container_name: zookeeper
restart: always
ports:
- 2181:2181
- 2888:2888
- 3888:3888
kafka:
image: debezium/kafka:1.6
container_name: kafka
restart: always
ports:
- 9092:9092
environment:
ZOOKEEPER_CONNECT: zookeeper:2181
BOOTSTRAP_SERVERS: kafka:9092
depends_on:
- zookeeper
connect:
image: debezium/connect:1.6
container_name: connect
restart: always
ports:
- 8083:8083
environment:
GROUP_ID: 1
CONFIG_STORAGE_TOPIC: herodotus_connect_configs
OFFSET_STORAGE_TOPIC: herodotus_connect_offsets
STATUS_STORAGE_TOPIC: herodotus_connect_statuses
BOOTSTRAP_SERVERS: kafka:9092
depends_on:
- kafka
4. 外部数据库配置
上一章节,介绍了Debezimu测试环境的方式,其中使用的debezium/postgres是已经进行过配置的,所以使用起来比较方便。在实际使用过程中,很多时候是使用独立搭建PostgreSQL,那么就需要对PostgreSQL进行配置。
4.1 以Docker的方式运行基础组件
本章节主要介绍Debezimu与独立的PostgreSQL数据库连接,因此除了PostgreSQL以外,Zookeeper、Kafka、Debezimu Connect仍旧使用Docker方式部署。具体部署的Docker Compose配置如下:
version: "3"
services:
zookeeper:
image: debezium/zookeeper:1.6
container_name: zookeeper
hostname: zookeeper
environment:
ZOOKEEPER_SERVER_ID: 1
ports:
- 2181:2181
- 2888:2888
- 3888:3888
kafka:
image: debezium/kafka:1.6
container_name: kafka
hostname: kafka
ports:
- 9092:9092
environment:
BROKER_ID: 1
ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_LISTENERS: LISTENER_INNER://kafka:29092,LISTENER_OUTER://0.0.0.0:9092
KAFKA_ADVERTISED_LISTENERS: LISTENER_INNER://kafka:29092,LISTENER_OUTER://192.168.101.10:9092
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: LISTENER_INNER:PLAINTEXT,LISTENER_OUTER:PLAINTEXT
KAFKA_INTER_BROKER_LISTENER_NAME: LISTENER_INNER
KAFKA_ALLOW_PLAINTEXT_LISTENER: 'yes'
KAFKA_AUTO_CREATE_TOPICS_ENABLE: 'true'
depends_on:
- zookeeper
connect:
image: debezium/connect:1.6
container_name: connect
hostname: connect
ports:
- 8083:8083
environment:
GROUP_ID: 1
CONFIG_STORAGE_TOPIC: herodotus_connect_configs
OFFSET_STORAGE_TOPIC: herodotus_connect_offsets
STATUS_STORAGE_TOPIC: herodotus_connect_statuses
BOOTSTRAP_SERVERS: kafka:9092
depends_on:
- kafka
其中Kafka Listener相关的配置,是为了解决Spring Kafka连接Kafka会出现:`Connection to node -1 could not be established. Broker may not be available.`问题。
4.2 修改PostgreSQL配置
Logical Decoding功能是PostgreSQL在9.4加入的,它是一种机制,允许提取提交到事务日志的更改,并在输出插件的帮助下以用户友好的方式处理这些更改。输出插件使客户机能够使用更改。
PostgreSQL connector 读取和处理数据库变化主要包含两个部分:
Logical Decoding 输出插件:根据选择可能需要安装输出插件。运行PostgreSQL服务之前,必须配置`replication slot `来启用你所选择的输出插件,有以下几个输出插件供选择:
decoderbufs: 是基于`Protobuf`的,目前由Debezimu社区维护
wal2json :是基于`JSON`的,目前由wal2json社区维护
pgoutput:在PostgreSQL 10及以上版本中是标准的Logical Decoding 输出插件。是由PostgreSQL社区维护,由PostgreSQL自己用于Logical Replication。这个插件是内置安装的,所以不需要额外安装。
Java代码(就是连接Kafka Connect的代码):负责读取由Logical Decoding 输出插件产生的数据。
Logical Decoding 输出插件不支持DDL变更,这意味着Connector不能把DDL变更事件发送给消费者
Logical Decoding Replicaiton Slots支持数据库的`primary`服务器。因此如果是PostgreSQL服务的集群,Connector只能在`primary`服务器激活。如果`primary`服务器出现问题,那么connector就会停掉。
4.2.1 修改PostgreSQL配置
在${PostgreSQL_HOME}/13/data目录下,找到postgresql.conf。
修改以下配置:
wal_level=logical
max_wal_senders=1
max_replication_slots=1
wal_level:通知数据库使用 logical decoding 读取预写日志
max_wal_senders: 通知数据库独立处理WAL变更的独立进程数量
max_replication_slots: 通知数据库处理WAL变更流所允许最大replication slots数目
配置完成后记得重启数据库
4.2.2 设置数据库权限
需要给PostgreSQL 用户分配replication权限。定义一个PostgreSQL role,至少分配REPLICATION和LOGION两项权限,示例代码如下:
CREATE ROLE REPLICATION LOGIN;
具体操作可以参考以下脚本:
-- pg新建用户
CREATE USER user WITH PASSWORD 'pwd';
-- 给用户复制流权限
ALTER ROLE user replication;
-- 给用户登录数据库权限
grant CONNECT ON DATABASE test to user;
-- 把当前库public下所有表查询权限赋给用户
GRANT SELECT ON ALL TABLES IN SCHEMA public TO user;
4.3 创建Connector
把下面的payload POST到http://:8083/connectors/
{
"name": "herodotus-connector",
"config": {
"connector.class": "io.debezium.connector.postgresql.PostgresConnector",
"database.hostname": "192.168.101.10",
"database.port": "15432",
"database.user": "athena",
"database.password": "athena",
"database.dbname" : "athena",
"database.server.name": "herodotus",
"slot.name": "herodotus_slot",
"table.include.list": "public.sys_organization",
"publication.name": "herodotus_public_connector",
"publication.autocreate.mode": "filtered",
"plugin.name": "pgoutput"
}
}
postman 界面操作如下图:
下面结合本例子中connector的配置信息对几个重点属性进行进一步说明:
Slot.name
按照上例Debezium会在PostgreSQL创建一个名为`herodotus_slot`的复制槽,本例中创建的connector需要通过该复制槽获取数据变更的信息。
可以通过以下sql查看复制槽的信息:
select * from pg_replication_slots;
上图中,active_pid为14200,即进程ID为14200的wal_sender进程已经在使用该复制槽与Debezium交互了
database.server.name和table.include.list
当connector获取到数据变更的信息后,会把该信息转化为统一的数据格式,并发布到Kafka的topic中。Debezium规定一个表对应一个topic,topic的名字的格式为 ..,本例中的表的数据变更消息将保存到Kafka的topic
herodotus.public.sys_organization中。
可以通过以下代码查看接收到的信息:
@KafkaListener(topics = {"herodotus.public.sys_organization"}, groupId = "herodotus.debezium")
public void received(String message) {
log.info("[Herodotus] |- Recived message from Debezium : [{}]", message);
}
5. 运行测试
现在,可以基于以上环境的配置,进行Debezium捕获数据效果的测试。可以进入到Kafka容器中,使用使用Kafka提供的kafka-console-consumer.sh查看Topic接收到的数据。具体命令如下:
bin/kafka-console-consumer.sh --bootstrap-server 192.168.101.10:9092 --topic herodotus.public.sys_organization
5.1 Insert 测试
在数据库sys_organization 表中插入一条数据
Kafka的消费者命令行工具收到了来自Debezium发布的数据变更消息:
格式化后的消息体如下,其中schema字段在此先忽略,重点放payload.before,payload.after及payload.op字段上:
{
"schema": {
...
},
"payload": {
"before": null,
"after": {
"organization_id": "4",
"create_time": null,
"ranking": null,
"update_time": null,
"description": null,
"is_reserved": null,
"reversion": null,
"status": 1,
"a4_biz_org_id": null,
"biz_org_code": null,
"biz_org_desc": null,
"biz_org_id": null,
"biz_org_name": null,
"biz_org_type": null,
"organization_name": "AAAAA",
"parent_id": null,
"partition_code": null,
"short_name": null
},
"source": {
"version": "1.6.0.Final",
"connector": "postgresql",
"name": "herodotus",
"ts_ms": 1626594964405,
"snapshot": "false",
"db": "athena",
"sequence": "[\"63461608\",\"63461608\"]",
"schema": "public",
"table": "sys_organization",
"txId": 2460,
"lsn": 63461896,
"xmin": null
},
"op": "c",
"ts_ms": 1626594964846,
"transaction": null
}
}
由于是insert操作,所以op为c (create),before为null,after为我们插入的数据。
5.2 Update 测试
在数据库sys_organization表中修改一条数据
Kafka的消费者命令行工具收到了来自Debezium发布的数据变更消息:
格式化后的消息体如下:
{
"schema": {
...
},
"payload": {
"before": null,
"after": {
"organization_id": "4",
"create_time": null,
"ranking": null,
"update_time": null,
"description": null,
"is_reserved": null,
"reversion": null,
"status": 1,
"a4_biz_org_id": null,
"biz_org_code": null,
"biz_org_desc": null,
"biz_org_id": null,
"biz_org_name": null,
"biz_org_type": null,
"organization_name": "BBBBB",
"parent_id": null,
"partition_code": null,
"short_name": null
},
"source": {
"version": "1.6.0.Final",
"connector": "postgresql",
"name": "herodotus",
"ts_ms": 1626595173601,
"snapshot": "false",
"db": "athena",
"sequence": "[\"63466888\",\"63466888\"]",
"schema": "public",
"table": "sys_organization",
"txId": 2461,
"lsn": 63467176,
"xmin": null
},
"op": "u",
"ts_ms": 1626595173825,
"transaction": null
}
}
进行更新产品信息的操作后,consumer将收到一条op为u (update)的信息,after为修改后的数据。
5.3 Delete测试
在数据库sys_organization表中删除一条数据
Kafka的消费者命令行工具收到了来自Debezium发布的数据变更消息:
格式化后的消息体如下:
{
"schema": {
...
},
"payload": {
"before": {
"organization_id": "3",
"create_time": null,
"ranking": null,
"update_time": null,
"description": null,
"is_reserved": null,
"reversion": null,
"status": null,
"a4_biz_org_id": null,
"biz_org_code": null,
"biz_org_desc": null,
"biz_org_id": null,
"biz_org_name": null,
"biz_org_type": null,
"organization_name": null,
"parent_id": null,
"partition_code": null,
"short_name": null
},
"after": null,
"source": {
"version": "1.6.0.Final",
"connector": "postgresql",
"name": "herodotus",
"ts_ms": 1626594566933,
"snapshot": "false",
"db": "athena",
"sequence": "[\"63461120\",\"63461120\"]",
"schema": "public",
"table": "sys_organization",
"txId": 2458,
"lsn": 63461176,
"xmin": null
},
"op": "d",
"ts_ms": 1626594567136,
"transaction": null
}
}
进行删除产品信息的操作后,consumer将收到一条op为d (delete)的信息,before为删除前的数据,after为null。
6.总结
通过Debezimu进行数据同步,不仅解决了传统ETL时效性不高的问题,还解决了基于消息队列需要两端编写代码的工程量,而且基于容器的方式更适合微服务架构的使用,使用Kafka进行消费端的整合,使得整合方式更加灵活便捷、终端类型更加丰富。
示例代码地址:
[Gitee](https://gitee.com/herodotus/eurynome-cloud)
[Github](https://github.com/herodotus-cloud/eurynome-cloud)
搜索
你可能感兴趣的:(数据库数据变动实时监听)
如何区分MongoDB和关系型数据库?思维导图 代码示例(java 架构)
用心去追梦
数据库 mongodb java
MongoDB和关系型数据库(RDBMS,如MySQL、PostgreSQL)是两种不同类型的数据库管理系统,它们在数据模型、查询语言、扩展性和性能等方面存在显著差异。理解这些差异有助于选择适合特定应用场景的数据库类型。以下是关于如何区分MongoDB和关系型数据库的详细指南:区分MongoDB和关系型数据库数据模型MongoDB:文档模型:使用BSON格式存储数据,每个记录都是一个自描述的文档,
使用WebSocket、MySQL、Go语言的Gin框架和GORM库来实现一个用户实时统计大屏概览
云梦优选
Go websocket mysql golang
为了使用WebSocket、MySQL、Go的Gin框架和GORM实现用户实时统计大屏概览,以下是分步指南:1.项目结构与依赖1.1初始化项目mkdirrealtime-dashboard&&cdrealtime-dashboardgomodinitrealtime-dashboard1.2安装依赖goget-ugithub.com/gin-gonic/gingoget-ugorm.io/gorm
Cypress测试框架详解-----轻松实现端到端自动化测试
王大傻0928
自动化测试 自动化 javascript node.js
Cypress是一个功能强大、易于使用的自动化测试工具,适用于现代Web应用的端到端测试。它的自动化处理、实时反馈、调试功能和易于集成的特性,使得它成为现在测试人员的热门测试框架选择。什么是Cypress框架?Cypress是一款开源的JavaScript自动化测试框架,是基于NodeJS的现代自动化工具,专为端到端测试设计,用于简化Web应用的测试自动化。支持使用JavaScript或TypeS
jmeter工具功能界面布局
一一一一一一一一一一
测试 jmeter介绍
一、使用jmeter进行接口测试1.1问题:执行100次50个请求同时请求1.2使用jmeter的解决方案(1)添加【测试计划】(2)基于添加的测试计划添加【线程组】,循环次数设置为100次(3)在【取样器】中基于线程组添加HTTP请求(4)在【监听器】基于线程组添加【察看结果树】(5)在监听器基于线程组添加【聚合报告】二、TestPlan(测试计划)2.1独立运行每个线程组(1)进程:每个正在运
redis.conf配置及哨兵sentinel.conf配置详解
姜源Jerry
DataBase 数据库 redis linux
Redis配置及哨兵Sentinel配置详解一、redis.conf配置项说明如下:Redis默认不是以守护进程的方式运行,可以通过该配置项修改,使用yes启用守护进程daemonizeno当Redis以守护进程方式运行时,Redis默认会把pid写入/var/run/redis.pid文件,可以通过pidfile指定pidfile/var/run/redis.pid指定Redis监听端口,默认端
【SpringAop实现切片注解】
壹佰大多
java android 数据库
文章目录AOP的目的AOP代码实现导包:aop实现注解实现异步监听AOP的目的SpringAOP(Aspect-OrientedProgramming)是Spring框架中的一项功能,旨在通过切面(Aspect)将横切关注点(Cross-CuttingConcerns)与业务逻辑解耦,从而使代码更加模块化和易维护。以下是SpringAOP的主要目的和应用场景:解耦横切关注点横切关注点是指多个模块中
深度学习模型在汽车自动驾驶领域的应用
eso1983
深度学习 汽车 自动驾驶
汽车自动驾驶是一个高度复杂的系统,深度学习和计算技术在其中扮演核心角色。今天简单介绍一下自动驾驶领域常用的深度学习模型及其计算原理的解析。1.深度学习模型分类及应用场景1.1视觉感知模型CNN(卷积神经网络)应用:图像分类、物体检测(车辆、行人、交通标志)、语义分割(道路、车道线)。典型模型:YOLO:实时目标检测,低延迟特性适合自动驾驶。MaskR-CNN:结合检测与像素级分割,用于精确场景理解
缓存的几种不同的实现方法?
ducode
一、1、文件缓存所谓文件缓存,就是根据逻辑判断,一段时间内某个asp的特定执行将不会很大的变动,因因而将内容以静态html的形式存放,然后以web的重定向技术让客户端访问静态文件,以达到减少CPU、数据库资源等的需求。这样的应用很多,譬如很多论坛就是在回复帖子的时候将整个帖子重新生成一个静态文件,然后进行重定向的,例如DONEWS,COM的论坛。该成静态还有一个副作用(好处)可以很容易被googl
TDengine 做为 FLINK 数据源技术参考手册
TDengine (老段)
tdengine flink 大数据 涛思数据 时序数据库 数据库
ApacheFlink是一款由Apache软件基金会支持的开源分布式流批一体化处理框架,可用于流处理、批处理、复杂事件处理、实时数据仓库构建及为机器学习提供实时数据支持等诸多大数据处理场景。与此同时,Flink拥有丰富的连接器与各类工具,可对接众多不同类型的数据源实现数据的读取与写入。在数据处理的过程中,Flink还提供了一系列可靠的容错机制,有力保障任务即便遭遇意外状况,依然能稳定、持续运行。借
JavaScript网页设计案例:响应式动态购物车
学不完了是吧
js javascript
在现代网页开发中,购物车是电子商务网站的重要功能之一。通过JavaScript,我们可以实现一个响应式动态购物车,提供用户友好的体验,并展示前端开发的核心能力。案例需求我们的购物车需要实现以下功能:动态添加商品:用户可以从商品列表中选择并添加商品到购物车。实时更新:购物车的商品数量、价格和总金额自动更新。修改商品数量:用户可以调整购物车中商品的数量。移除商品:用户可以从购物车中移除商品。结算功能:
Hadoop HA 架构
weixin_30569033
shell 大数据
为什么要用集群?企业里面,多台机器伪分布式每一个角色都是一个进程HDFS:NNSNNDNYARN:RMNM大数据所有组件,都是主从架构master-slaveHDFS读写请求都是先到NN节点,但是,HBase读写请求不是经过master,建表和删除表是需要经过masterNN节点挂了,就不能提供对外服务(-put,-get)需要配置两个NN节点(实时的,任何时刻只有一台active对外,另外一台是
如何在 Typecho 中实现 Joe 编辑器标签自动填充
6v6博客
编辑器 android
如何在Typecho中实现Joe编辑器标签自动填充在Typecho的文章编辑过程中,如果你使用Joe编辑器,可能会希望输入#标签后能自动提取并填充到文章的标签输入框中,以提高工作效率。接下来,我们将详细介绍如何通过开发一个Typecho插件来实现这一功能。6v6博客地址:6v6.ren一、功能实现原理这个功能的实现依赖于JavaScript来监听Joe编辑器中的输入事件,通过正则表达式提取出#开头
如何获取视频地址的某一帧?
场景需要用视频的某一帧作为预览图思路创建video对象,加载视频元数据,然后用canvas绘制video的画面。实现细节1创建video对象,加载元数据,然后监听必要事件constgetVideoFirstFrame=(videoUrl:string)=>{constvideo=document.createElement("video")video.preload="metadata"video
分布式系统架构7:本地缓存
快乐非自愿
架构 缓存
1.引入缓存的影响我们在开发时,用到缓存的情况,无非就是为了减少客户端对相同资源的重复请求,降低服务器的负载压力。引入缓存后,既有好处也有坏处引入缓存负面影响:开发角度,增加了系统复杂度,需考虑缓存失效、更新、一致性问题运维角度,缓存会掩盖一些缺陷问题安全角度,缓存可能泄密某些保密数据引入缓存的理由:为了缓解CPU压力,将实时计算运行结果存储起来,节省CPU压力为了缓解I/O压力,将原本对网络、磁
ajax实现动态及时刷新表格数据_如何利用Python3和PyQt5来实现控件数据动态刷新...
weixin_39904116
最近笔者在做一个pyqt5的界面,由于在日常生活中,一些实际运用的场合都需要对数据进行实时的刷新,例如对某个数值的监控,水温,室温的监控等等,都需要实时的刷新控件显示的数据。对于实现这样的一种功能,pyqt5在面板生成的同时就固定住了UI中的数据,例如我们产生一个QLineEdit控件,然后布局在面板上,但是控件中的数据是固定的,如果这个数据是实时更新的,想要改变空间中的数据时,就要去刷新面板,p
【产品经理修炼之道】-品牌如何进行数字化建设规划?
xiaoli8748_软件开发
产品经理 产品经理 大数据
随着数字化时代的到来,今后仅靠爆品无法真正触动“粉丝”和广大用户,利用数字化手段,让用户多维度、全方位、深浸式直接接触品牌而形成的独特感受和体验,能够更好地启动品牌能量。那么,如何做好品牌数字化建设?看完这篇文章,也许能够获得启发。(I)整体目标身处已经迈入绝对数字化时代的中国市场,数字化为品牌建设提供了最大的“确定性”——在全面的实时数据和精准营销的支持下,通过科学的洞察、度量与优化,品牌不仅能
Django:ORM,mysql,django中多数据库操作
叫我DPT
mysql 数据库 python django
目录读写分离1.构造表结构2.对数据库数据的读取操作简单版基于router的改进版按app划分1.构造表结构2.对数据库数据的读取操作简单版基于router的改进版单app中的分库操作1.构造表结构2.对数据库数据的读写操作简单版基于router的改进版最后总结一下router读写分离读写分离是让数据库的读写操作被分配到不同的数据库服务器上,从而提高可用性。这种分库方式是,要各数据库的表结构要一致
【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】1.25 视觉风暴:NumPy驱动数据可视化
精通代码大仙
numpy python numpy python 信息可视化
1.25视觉风暴:NumPy驱动数据可视化目录视觉风暴:NumPy驱动数据可视化百万级点云实时渲染优化CT医学影像三维重建实战交互式数据分析看板开发地理空间数据可视化进阶WebAssembly前端渲染融合1.25.1百万级点云实时渲染优化1.25.2CT医学影像三维重建实战1.25.3交互式数据分析看板开发1.25.4地理空间数据可视化进阶1.25.5WebAssembly前端渲染融合视觉风暴:N
使用异步任务队列与事件驱动架构提升Serverless应用的实时处理能力与资源利用率的技术详解
瑕疵
热点资讯
博客主页:瑕疵的CSDN主页Gitee主页:瑕疵的gitee主页⏩文章专栏:《热点资讯》使用异步任务队列与事件驱动架构提升Serverless应用的实时处理能力与资源利用率的技术详解使用异步任务队列与事件驱动架构提升Serverless应用的实时处理能力与资源利用率的技术详解使用异步任务队列与事件驱动架构提升Serverless应用的实时处理能力与资源利用率的技术详解引言异步任务队列概述定义与特点
【Unity 渲染插件】GPU Instancer 基于 GPU 实例化技术,旨在解决 Unity 中大量重复对象的渲染瓶颈问题,显著提升游戏性能
Unity游戏资源学习屋
Unity插件
GPUInstancer是一款专注于高性能渲染的Unity插件,基于GPU实例化技术,旨在解决Unity中大量重复对象的渲染瓶颈问题,显著提升游戏性能。通过减少CPU到GPU的数据传输和批处理开销,该插件特别适合渲染复杂的开放世界场景、自然环境、城市布局等需要大量重复物体的场景。核心功能解析实时GPU实例化GPUInstancer能够自动检测和实例化场景中的重复网格对象,将它们的渲染交给GPU实现
java 监控车辆位置_基于Spring Boot的实时运行车辆位置模拟和监控系统
天蓝草
java 监控车辆位置
SpringCarLocationServiceThisisareal-timerunningvehiclelocationsimulationandmonitoringsystemusingJava,Spring,SpringBoot,SpringData,SpringCloud,NetflixOSS,Maven,JPA,Tomcat,RabbitMQ,MongoDB,MySQLandDocke
【方法论】ChatGPT与DeepSeek的联合应用,提升工作效率的新解决方案
神经美学茂森
chatgpt 人工智能
标题:ChatGPT与DeepSeek的联合应用,提升工作效率的新解决方案【表格】ChatGPT与DeepSeek联合应用流程阶段工具主要任务优势备注初稿生成ChatGPT基于用户输入生成初步内容高效、快速生成内容,适应多种主题适合生成长篇文章、报告、分析等验证与修正DeepSeek对生成的内容进行实时联网验证,查找并修正错误提供最新的文献资源,保证内容准确性适合需要精确数据和最新研究支持的内容内
Doris实战——特步集团零售数据仓库项目实践
吵吵叭火
# Doris 大数据 大数据 数据仓库
目录一、背景二、总体架构三、ETL实践3.1批量数据的导入3.2实时数据接入3.3数据加工3.4BI查询四、实时需求响应五、其他经验5.1DorisBE内存溢出5.2SQL任务超时5.3删除语句不支持表达式5.4Drop表闪回六、未来展望原文大佬的这篇Doris数仓建设案例有借鉴意义,这里摘抄下来用作学习和知识沉淀。如有侵权等告知~一、背景特步集团有限公司是中国领先的体育用品企业之一,为了提高特步
wifi模块 服务器通讯协议,模块之间通信协议
高杉峻
wifi模块 服务器通讯协议
模块之间通信协议内容精选换一换IEC61499是分布式工业测量,控制和监控系统的功能块标准,既然它是面向工业测量和控制的系统,对系统的确定性(Deterministic)要求必然也比较高。确定性又是安全性的前提。保证系统的确定性的两个重要措施是保证系统的实时性和同步性。分布式系统结构又进一步增加了实现确定性的难来自:博客网络编程一、网络编程基础python的网络编程模块主要支持两种Internet
wordpress外贸独立站常用询盘软件
wodrpress资源分享
独立站 独立站
LiveChatLiveChat是一家提供实时聊天软件的公司,帮助企业通过其平台与客户进行即时通讯,提高客户满意度和忠诚度。他们的产品允许企业在网站、应用程序或电子邮件等多个渠道与客户互动,从而提升客户体验并促进销售增长。LiveChat的软件特点包括:实时聊天窗口:允许客服人员与客户进行即时对话,解决疑问或提供信息。自动化问候与响应:设置自动弹出的问候消息,以及根据预设规则自动回复常见问题的功能
面向算网的数字孪生关键技术研究及应用探讨
罗伯特之技术屋
大数据与数字化的设计应用专栏 网络 大数据
摘要为了解决算网运营中面临的感知实时精度高、融合管控智能程度高、系统场景复杂度高、新技术部署难度高等问题,从宏观政策、行业标准化及运营商实践等方面对数字孪生网络发展现状进行分析,提出面向算网的数字孪生网络体系架构,对数字孪生网络关键能力进行深入研究,同时对数字孪生网络在提升算网业务感知、赋能算网智能运营的典型应用进行探讨。01概述数字孪生被业界视为物理世界和数字世界之间的桥梁。通过数字孪生技术建立
备战美赛!2025美赛数学建模C题模拟预测!用于大家练手模拟!
灿灿数模
数学建模
完整的思路代码模型见文末2025美赛数学建模C题模拟题:城市交通拥堵指数的预测与管理策略背景随着全球城市化进程的加快,交通拥堵问题成为城市发展的重要挑战之一。交通拥堵不仅影响居民出行效率,还增加了能源消耗和碳排放。近年来,各大城市开始尝试通过实时数据监控和人工智能技术对交通拥堵进行预测和管理。然而,由于城市交通系统的复杂性,现有方法在实际应用中仍面临诸多挑战。任务作为一名数据分析专家,你的任务是基
『OpenCV-Python』Trackbar控件的用法
点赞+关注+收藏=学会了推荐关注《OpenCV-Python专栏》在OpenCV中,Trackbar控件(滑块)是一个非常常用的GUI组件,用于在图像处理和计算机视觉任务中进行交互式调整参数。比如说,加载一个图片,通过一个滑块调整图片的亮度,这样便于我们用肉眼观察图片的变化。Trackbar允许用户通过拖动滑块来调整参数的值,并且会实时更新显示结果。比如上图这个例子,创建了3个Trackbar控件
『OpenCV-Python』鼠标事件
opencv
点赞+关注+收藏=学会了在使用OpenCV进行图像处理时,有时需要与图像进行交互,例如选择感兴趣区域(ROI)、标注关键点、调整参数、获取图片指定位置的颜色值等。OpenCV提供了鼠标事件支持,可以在图像窗口中通过鼠标实现丰富的交互功能。推荐《OpenCV专栏》用到的方法是cv2.setMouseCallback(window_name,on_mouse,param=None),用这个方法监听鼠标
『OpenCV-Python』视频的读取和保存
点赞+关注+收藏=学会了推荐关注《OpenCV-Python专栏》上一讲介绍了OpenCV的读取图片的方法,这一讲简单聊聊OpenCV读取和保存视频。视频的来源主要有2种,一种是本地视频文件,另一种是实时视频流,比如手机和电脑的摄像头。要读取这两种视频的方法都是一样的,只是传的参数不同而已。读取摄像头视频读取摄像头的内容并显示出来需要几步获取摄像头内容逐帧渲染importcv2cap=cv2.Vi
枚举的构造函数中抛出异常会怎样
bylijinnan
java enum 单例
首先从使用enum实现单例说起。
为什么要用enum来实现单例?
这篇文章(
http://javarevisited.blogspot.sg/2012/07/why-enum-singleton-are-better-in-java.html)阐述了三个理由:
1.enum单例简单、容易,只需几行代码:
public enum Singleton {
INSTANCE;
CMake 教程
aigo
C++
转自:http://xiang.lf.blog.163.com/blog/static/127733322201481114456136/
CMake是一个跨平台的程序构建工具,比如起自己编写Makefile方便很多。
介绍:http://baike.baidu.com/view/1126160.htm
本文件不介绍CMake的基本语法,下面是篇不错的入门教程:
http:
cvc-complex-type.2.3: Element 'beans' cannot have character
Cb123456
spring Webgis
cvc-complex-type.2.3: Element 'beans' cannot have character
Line 33 in XML document from ServletContext resource [/WEB-INF/backend-servlet.xml] is i
jquery实例:随页面滚动条滚动而自动加载内容
120153216
jquery
<script language="javascript">
$(function (){
var i = 4;$(window).bind("scroll", function (event){
//滚动条到网页头部的 高度,兼容ie,ff,chrome
var top = document.documentElement.s
将数据库中的数据转换成dbs文件
何必如此
sql dbs
旗正规则引擎通过数据库配置器(DataBuilder)来管理数据库,无论是Oracle,还是其他主流的数据都支持,操作方式是一样的。旗正规则引擎的数据库配置器是用于编辑数据库结构信息以及管理数据库表数据,并且可以执行SQL 语句,主要功能如下。
1)数据库生成表结构信息:
主要生成数据库配置文件(.conf文
在IBATIS中配置SQL语句的IN方式
357029540
ibatis
在使用IBATIS进行SQL语句配置查询时,我们一定会遇到通过IN查询的地方,在使用IN查询时我们可以有两种方式进行配置参数:String和List。具体使用方式如下:
1.String:定义一个String的参数userIds,把这个参数传入IBATIS的sql配置文件,sql语句就可以这样写:
<select id="getForms" param
Spring3 MVC 笔记(一)
7454103
spring mvc bean REST JSF
自从 MVC 这个概念提出来之后 struts1.X struts2.X jsf 。。。。。
这个view 层的技术一个接一个! 都用过!不敢说哪个绝对的强悍!
要看业务,和整体的设计!
最近公司要求开发个新系统!
Timer与Spring Quartz 定时执行程序
darkranger
spring bean 工作 quartz
有时候需要定时触发某一项任务。其实在jdk1.3,java sdk就通过java.util.Timer提供相应的功能。一个简单的例子说明如何使用,很简单: 1、第一步,我们需要建立一项任务,我们的任务需要继承java.util.TimerTask package com.test; import java.text.SimpleDateFormat; import java.util.Date;
大端小端转换,le32_to_cpu 和cpu_to_le32
aijuans
C语言相关
大端小端转换,le32_to_cpu 和cpu_to_le32 字节序
http://oss.org.cn/kernel-book/ldd3/ch11s04.html
小心不要假设字节序. PC 存储多字节值是低字节为先(小端为先, 因此是小端), 一些高级的平台以另一种方式(大端)
Nginx负载均衡配置实例详解
avords
[导读] 负载均衡是我们大流量网站要做的一个东西,下面我来给大家介绍在Nginx服务器上进行负载均衡配置方法,希望对有需要的同学有所帮助哦。负载均衡先来简单了解一下什么是负载均衡,单从字面上的意思来理解就可以解 负载均衡是我们大流量网站要做的一个东西,下面我来给大家介绍在Nginx服务器上进行负载均衡配置方法,希望对有需要的同学有所帮助哦。
负载均衡
先来简单了解一下什么是负载均衡
乱说的
houxinyou
框架 敏捷开发 软件测试
从很久以前,大家就研究框架,开发方法,软件工程,好多!反正我是搞不明白!
这两天看好多人研究敏捷模型,瀑布模型!也没太搞明白.
不过感觉和程序开发语言差不多,
瀑布就是顺序,敏捷就是循环.
瀑布就是需求、分析、设计、编码、测试一步一步走下来。而敏捷就是按摸块或者说迭代做个循环,第个循环中也一样是需求、分析、设计、编码、测试一步一步走下来。
也可以把软件开发理
欣赏的价值——一个小故事
bijian1013
有效辅导 欣赏 欣赏的价值
第一次参加家长会,幼儿园的老师说:"您的儿子有多动症,在板凳上连三分钟都坐不了,你最好带他去医院看一看。" 回家的路上,儿子问她老师都说了些什么,她鼻子一酸,差点流下泪来。因为全班30位小朋友,惟有他表现最差;惟有对他,老师表现出不屑,然而她还在告诉她的儿子:"老师表扬你了,说宝宝原来在板凳上坐不了一分钟,现在能坐三分钟。其他妈妈都非常羡慕妈妈,因为全班只有宝宝
包冲突问题的解决方法
bingyingao
eclipse maven exclusions 包冲突
包冲突是开发过程中很常见的问题:
其表现有:
1.明明在eclipse中能够索引到某个类,运行时却报出找不到类。
2.明明在eclipse中能够索引到某个类的方法,运行时却报出找不到方法。
3.类及方法都有,以正确编译成了.class文件,在本机跑的好好的,发到测试或者正式环境就
抛如下异常:
java.lang.NoClassDefFoundError: Could not in
【Spark七十五】Spark Streaming整合Flume-NG三之接入log4j
bit1129
Stream
先来一段废话:
实际工作中,业务系统的日志基本上是使用Log4j写入到日志文件中的,问题的关键之处在于业务日志的格式混乱,这给对日志文件中的日志进行统计分析带来了极大的困难,或者说,基本上无法进行分析,每个人写日志的习惯不同,导致日志行的格式五花八门,最后只能通过grep来查找特定的关键词缩小范围,但是在集群环境下,每个机器去grep一遍,分析一遍,这个效率如何可想之二,大好光阴都浪费在这上面了
sudoku solver in Haskell
bookjovi
sudoku haskell
这几天没太多的事做,想着用函数式语言来写点实用的程序,像fib和prime之类的就不想提了(就一行代码的事),写什么程序呢?在网上闲逛时发现sudoku游戏,sudoku十几年前就知道了,学生生涯时也想过用C/Java来实现个智能求解,但到最后往往没写成,主要是用C/Java写的话会很麻烦。
现在写程序,本人总是有一种思维惯性,总是想把程序写的更紧凑,更精致,代码行数最少,所以现
java apache ftpClient
bro_feng
java
最近使用apache的ftpclient插件实现ftp下载,遇见几个问题,做如下总结。
1. 上传阻塞,一连串的上传,其中一个就阻塞了,或是用storeFile上传时返回false。查了点资料,说是FTP有主动模式和被动模式。将传出模式修改为被动模式ftp.enterLocalPassiveMode();然后就好了。
看了网上相关介绍,对主动模式和被动模式区别还是比较的模糊,不太了解被动模
读《研磨设计模式》-代码笔记-工厂方法模式
bylijinnan
java 设计模式
声明: 本文只为方便我个人查阅和理解,详细的分析以及源代码请移步 原作者的博客http://chjavach.iteye.com/
package design.pattern;
/*
* 工厂方法模式:使一个类的实例化延迟到子类
* 某次,我在工作不知不觉中就用到了工厂方法模式(称为模板方法模式更恰当。2012-10-29):
* 有很多不同的产品,它
面试记录语
chenyu19891124
招聘
或许真的在一个平台上成长成什么样,都必须靠自己去努力。有了好的平台让自己展示,就该好好努力。今天是自己单独一次去面试别人,感觉有点小紧张,说话有点打结。在面试完后写面试情况表,下笔真的好难,尤其是要对面试人的情况说明真的好难。
今天面试的是自己同事的同事,现在的这个同事要离职了,介绍了我现在这位同事以前的同事来面试。今天这位求职者面试的是配置管理,期初看了简历觉得应该很适合做配置管理,但是今天面
Fire Workflow 1.0正式版终于发布了
comsci
工作 workflow Google
Fire Workflow 是国内另外一款开源工作流,作者是著名的非也同志,哈哈....
官方网站是 http://www.fireflow.org
经过大家努力,Fire Workflow 1.0正式版终于发布了
正式版主要变化:
1、增加IWorkItem.jumpToEx(...)方法,取消了当前环节和目标环节必须在同一条执行线的限制,使得自由流更加自由
2、增加IT
Python向脚本传参
daizj
python 脚本 传参
如果想对python脚本传参数,python中对应的argc, argv(c语言的命令行参数)是什么呢?
需要模块:sys
参数个数:len(sys.argv)
脚本名: sys.argv[0]
参数1: sys.argv[1]
参数2: sys.argv[
管理用户分组的命令gpasswd
dongwei_6688
passwd
NAME: gpasswd - administer the /etc/group file
SYNOPSIS:
gpasswd group
gpasswd -a user group
gpasswd -d user group
gpasswd -R group
gpasswd -r group
gpasswd [-A user,...] [-M user,...] g
郝斌老师数据结构课程笔记
dcj3sjt126com
数据结构与算法
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
yii2 cgridview加上选择框进行操作
dcj3sjt126com
GridView
页面代码
<?=Html::beginForm(['controller/bulk'],'post');?>
<?=Html::dropDownList('action','',[''=>'Mark selected as: ','c'=>'Confirmed','nc'=>'No Confirmed'],['class'=>'dropdown',])
linux mysql
fypop
linux
enquiry mysql version in centos linux
yum list installed | grep mysql
yum -y remove mysql-libs.x86_64
enquiry mysql version in yum repositoryyum list | grep mysql oryum -y list mysql*
install mysq
Scramble String
hcx2013
String
Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrings recursively.
Below is one possible representation of s1 = "great":
跟我学Shiro目录贴
jinnianshilongnian
跟我学shiro
历经三个月左右时间,《跟我学Shiro》系列教程已经完结,暂时没有需要补充的内容,因此生成PDF版供大家下载。最近项目比较紧,没有时间解答一些疑问,暂时无法回复一些问题,很抱歉,不过可以加群(334194438/348194195)一起讨论问题。
----广告-----------------------------------------------------
nginx日志切割并使用flume-ng收集日志
liyonghui160com
nginx的日志文件没有rotate功能。如果你不处理,日志文件将变得越来越大,还好我们可以写一个nginx日志切割脚本来自动切割日志文件。第一步就是重命名日志文件,不用担心重命名后nginx找不到日志文件而丢失日志。在你未重新打开原名字的日志文件前,nginx还是会向你重命名的文件写日志,linux是靠文件描述符而不是文件名定位文件。第二步向nginx主
Oracle死锁解决方法
pda158
oracle
select p.spid,c.object_name,b.session_id,b.oracle_username,b.os_user_name from v$process p,v$session a, v$locked_object b,all_objects c where p.addr=a.paddr and a.process=b.process and c.object_id=b.
java之List排序
shiguanghui
list排序
在Java Collection Framework中定义的List实现有Vector,ArrayList和LinkedList。这些集合提供了对对象组的索引访问。他们提供了元素的添加与删除支持。然而,它们并没有内置的元素排序支持。 你能够使用java.util.Collections类中的sort()方法对List元素进行排序。你既可以给方法传递
servlet单例多线程
utopialxw
单例 多线程 servlet
转自http://www.cnblogs.com/yjhrem/articles/3160864.html
和 http://blog.chinaunix.net/uid-7374279-id-3687149.html
Servlet 单例多线程
Servlet如何处理多个请求访问?Servlet容器默认是采用单实例多线程的方式处理多个请求的:1.当web服务器启动的