源码分析 | ClickHouse和他的朋友们(9)MySQL实时复制与实现

Clickhouse数据复制的原理与实践 作者:俊达。 阅读详情

本文转自我司大神 BohuTANG的博客 。

很多人看到标题还以为自己走错了夜场,其实没有。

ClickHouse 可以挂载为 MySQL 的一个从库 ,先全量再增量的实时同步 MySQL 数据,这个功能可以说是今年最亮眼、最刚需的功能,基于它我们可以轻松的打造一套企业级解决方案,让 OLTP 和 OLAP 的融合从此不再头疼。

目前支持 MySQL 5.6/5.7/8.0 版本,兼容 Delete/Update 语句,及大部分常用的 DDL 操作。
代码已经合并到 upstream master 分支,预计在20.8版本作为experimental 功能发布。

毕竟是两个异构生态的融合,仍然有不少的工作要做,同时也期待着社区用户的反馈,以加速迭代。

代码获取

获取 clickhouse/master 代码编译即可,方法见 ClickHouse和他的朋友们(1)编译、开发、测试…

MySQL Master

我们需要一个开启 binlog 的 MySQL 作为 master:

docker run -d -e MYSQL_ROOT_PASSWORD=123 mysql:5.7 mysqld --datadir=/var/lib/mysql --server-id=1 --log-bin=/var/lib/mysql/mysql-bin.log --gtid-mode=ON --enforce-gtid-consistency

创建数据库和表,并写入数据:

mysql> create database ckdb;
mysql> use ckdb;
mysql> create table t1(a int not null primary key, b int);
mysql> insert into t1 values(1,1),(2,2);
mysql> select * from t1;
+---+------+
| a | b    |
+---+------+
| 1 |    1 |
| 2 |    2 |
+---+------+
2 rows in set (0.00 sec)

ClickHouse Slave

目前以 database 为单位进行复制,不同的 database 可以来自不同的 MySQL master,这样就可以实现多个 MySQL 源数据同步到一个 ClickHouse 做 OLAP 分析功能。

首先开启体验开关:

clickhouse :) SET allow_experimental_database_materialize_mysql=1;

创建一个复制通道:

clickhouse :) CREATE DATABASE ckdb ENGINE = MaterializeMySQL('172.17.0.2:3306', 'ckdb', 'root', '123');
clickhouse :) use ckdb;
clickhouse :) show tables;
┌─name─┐
│ t1   │
└──────┘
clickhouse :) select * from t1;
┌─a─┬─b─┐
│ 1 │ 1 │
└───┴───┘
┌─a─┬─b─┐
│ 2 │ 2 │
└───┴───┘

2 rows in set. Elapsed: 0.017 sec.

看下 ClickHouse 的同步位点:
cat ckdatas/metadata/ckdb/.metadata

Version:	1
Binlog File:	mysql-bin.000001
Binlog Position:	913
Data Version:	0

Delete

首先在 MySQL Master 上执行一个删除操作:

mysql> delete from t1 where a=1;
Query OK, 1 row affected (0.01 sec)

然后在 ClickHouse Slave 侧查看记录:

clickhouse :) select * from t1;

SELECT *
FROM t1

┌─a─┬─b─┐
│ 2 │ 2 │
└───┴───┘

1 rows in set. Elapsed: 0.032 sec.

此时的 metadata 里 Data Version 已经递增到 2:

cat ckdatas/metadata/ckdb/.metadata 
Version:	1
Binlog File:	mysql-bin.000001
Binlog Position:	1171
Data Version:	2

Update

MySQL Master:

mysql> select * from t1;
+---+------+
| a | b    |
+---+------+
| 2 |    2 |
+---+------+
1 row in set (0.00 sec)

mysql> update t1 set b=b+1;

mysql> select * from t1;
+---+------+
| a | b    |
+---+------+
| 2 |    3 |
+---+------+
1 row in set (0.00 sec)

ClickHouse Slave:

clickhouse :) select * from t1;

SELECT *
FROM t1

┌─a─┬─b─┐
│ 2 │ 3 │
└───┴───┘

1 rows in set. Elapsed: 0.023 sec.

性能测试

测试环境
MySQL          8C16G 云主机, 192.168.0.3,基础数据 10188183 条记录
ClickHouse     8C16G 云主机, 192.168.0.4
benchyou       8C8G  云主机,  192.168.0.5, 256并发写, https://github.com/xelabs/benchyou

性能测试跟硬件环境有较大关系,这里使用的是云主机模式,数据供参考。

全量性能
8c16G-vm :) create database sbtest engine=MaterializeMySQL('192.168.0.3:3306', 'sbtest', 'test', '123');

8c16G-vm :) watch lv1;

WATCH lv1

┌─count()─┬───────────────now()─┬─_version─┐
│       0 │ 2020-07-29 06:36:04 │        1 │
└─────────┴─────────────────────┴──────────┘
┌─count()─┬───────────────now()─┬─_version─┐
│ 1113585 │ 2020-07-29 06:36:05 │        2 │
└─────────┴─────────────────────┴──────────┘
┌─count()─┬───────────────now()─┬─_version─┐
│ 2227170 │ 2020-07-29 06:36:07 │        3 │
└─────────┴─────────────────────┴──────────┘
┌─count()─┬───────────────now()─┬─_version─┐
│ 3340755 │ 2020-07-29 06:36:10 │        4 │
└─────────┴─────────────────────┴──────────┘
┌─count()─┬───────────────now()─┬─_version─┐
│ 4454340 │ 2020-07-29 06:36:13 │        5 │
└─────────┴─────────────────────┴──────────┘
┌─count()─┬───────────────now()─┬─_version─┐
│ 5567925 │ 2020-07-29 06:36:16 │        6 │
└─────────┴─────────────────────┴──────────┘
┌─count()─┬───────────────now()─┬─_version─┐
│ 6681510 │ 2020-07-29 06:36:18 │        7 │
└─────────┴─────────────────────┴──────────┘
┌─count()─┬───────────────now()─┬─_version─┐
│ 7795095 │ 2020-07-29 06:36:22 │        8 │
└─────────┴─────────────────────┴──────────┘
┌─count()─┬───────────────now()─┬─_version─┐
│ 8908680 │ 2020-07-29 06:36:25 │        9 │
└─────────┴─────────────────────┴──────────┘
┌──count()─┬───────────────now()─┬─_version─┐
│ 10022265 │ 2020-07-29 06:36:28 │       10 │
└──────────┴─────────────────────┴──────────┘
┌──count()─┬───────────────now()─┬─_version─┐
│ 10188183 │ 2020-07-29 06:36:28 │       11 │
└──────────┴─────────────────────┴──────────┘
← Progress: 11.00 rows, 220.00 B (0.16 rows/s., 3.17 B/s.)

在这个硬件环境下,全量同步性能大概是 424507/s,42w 事务每秒。
因为全量的数据之间没有依赖关系,可以进一步优化成并行,加速同步。
全量的性能直接决定 ClickHouse slave 坏掉后重建的速度,如果你的 MySQL 有 10 亿条数据,大概 40 分钟就可以重建完成。

增量性能(实时同步)

在当前配置下,ClickHouse slave 单线程回放消费能力大于 MySQL master 256 并发下生产能力,通过测试可以看到它们保持实时同步。

benchyou 压测数据,2.1w 事务/秒(MySQL 在当前环境下TPS上不去):

./bin/benchyou --mysql-host=192.168.0.3 --mysql-user=test --mysql-password=123 --oltp-tables-count=1 --write-threads=256 --read-threads=0

time            thds               tps     wtps    rtps
[13s]        [r:0,w:256,u:0,d:0]  19962    19962   0    

time            thds               tps     wtps    rtps
[14s]        [r:0,w:256,u:0,d:0]  20415    20415   0 

time            thds               tps     wtps    rtps
[15s]        [r:0,w:256,u:0,d:0]  21131    21131   0

time            thds               tps     wtps    rtps
[16s]        [r:0,w:256,u:0,d:0]  21606    21606   0

time            thds               tps     wtps    rtps
[17s]        [r:0,w:256,u:0,d:0]  22505    22505   0

ClickHouse 侧单线程回放能力,2.1w 事务/秒,实时同步:

┌─count()─┬───────────────now()─┬─_version─┐
│  150732 │ 2020-07-30 05:17:15 │       17 │
└─────────┴─────────────────────┴──────────┘
┌─count()─┬───────────────now()─┬─_version─┐
│  155477 │ 2020-07-30 05:17:16 │       18 │
└─────────┴─────────────────────┴──────────┘
┌─count()─┬───────────────now()─┬─_version─┐
│  160222 │ 2020-07-30 05:17:16 │       19 │
└─────────┴─────────────────────┴──────────┘
┌─count()─┬───────────────now()─┬─_version─┐
│  164967 │ 2020-07-30 05:17:16 │       20 │
└─────────┴─────────────────────┴──────────┘
┌─count()─┬───────────────now()─┬─_version─┐
│  169712 │ 2020-07-30 05:17:16 │       21 │
└─────────┴─────────────────────┴──────────┘
┌─count()─┬───────────────now()─┬─_version─┐
│  174457 │ 2020-07-30 05:17:16 │       22 │
└─────────┴─────────────────────┴──────────┘
┌─count()─┬───────────────now()─┬─_version─┐
│  179202 │ 2020-07-30 05:17:17 │       23 │
└─────────┴─────────────────────┴──────────┘
┌─count()─┬───────────────now()─┬─_version─┐
│  183947 │ 2020-07-30 05:17:17 │       24 │
└─────────┴─────────────────────┴──────────┘
┌─count()─┬───────────────now()─┬─_version─┐
│  188692 │ 2020-07-30 05:17:17 │       25 │
└─────────┴─────────────────────┴──────────┘
┌─count()─┬───────────────now()─┬─_version─┐
│  193437 │ 2020-07-30 05:17:17 │       26 │
└─────────┴─────────────────────┴──────────┘
┌─count()─┬───────────────now()─┬─_version─┐
│  198182 │ 2020-07-30 05:17:17 │       27 │
└─────────┴─────────────────────┴──────────┘

实现机制

在探讨机制之前,首先需要了解下 MySQL 的 binlog event ,主要有以下几种类型:

1. MYSQL_QUERY_EVENT    -- DDL
2. MYSQL_WRITE_ROWS_EVENT -- insert数据
3. MYSQL_UPDATE_ROWS_EVENT -- update数据
4. MYSQL_DELETE_ROWS_EVENT -- delete数据

当一个事务提交后,MySQL 会把执行的 SQL 处理成相应的 binlog event,并持久化到 binlog 文件。

binlog 是 MySQL 对外输出的重要途径,只要你实现 MySQL Replication Protocol,就可以流式的消费MySQL 生产的 binlog event,具体协议见 Replication Protocol。

由于历史原因,协议繁琐而诡异,这不是本文重点。

对于 ClickHouse 消费 MySQL binlog 来说,主要有以下3个难点:

  • DDL 兼容
  • Delete/Update 支持
  • Query 过滤
DDL

DDL 兼容花费了大量的代码去实现。

首先,我们看看 MySQL 的表复制到 ClickHouse 后会变成什么样子。

MySQL master:

mysql> show create table t1\G;
*************************** 1. row ***************************
       Table: t1
Create Table: CREATE TABLE `t1` (
  `a` int(11) NOT NULL,
  `b` int(11) DEFAULT NULL,
  PRIMARY KEY (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

ClickHouse slave:

ATTACH TABLE t1
(
    `a` Int32,
    `b` Nullable(Int32),
    `_sign` Int8,
    `_version` UInt64
)
ENGINE = ReplacingMergeTree(_version)
PARTITION BY intDiv(a, 4294967)
ORDER BY tuple(a)
SETTINGS index_granularity = 8192

可以看到:

  • 默认增加了 2 个隐藏字段:_sign(-1删除, 1写入) 和 _version(数据版本)
  • 引擎转换成了 ReplacingMergeTree,以 _version 作为 column version
  • 原主键字段 a 作为排序和分区键

这只是一个表的复制,其他还有非常多的DDL处理,比如增加列、索引等,感兴趣可以观摩 Parsers/MySQL 下代码。

Update和Delete

当我们在 MySQL master 执行:

mysql> delete from t1 where a=1;
mysql> update t1 set b=b+1;

ClickHouse t1数据(把 _sign 和 _version 一并查询):

clickhouse :) select a,b,_sign, _version from t1;

SELECT 
    a,
    b,
    _sign,
    _version
FROM t1

┌─a─┬─b─┬─_sign─┬─_version─┐
│ 1 │ 1 │     1 │        1 │
│ 2 │ 2 │     1 │        1 │
└───┴───┴───────┴──────────┘
┌─a─┬─b─┬─_sign─┬─_version─┐
│ 1 │ 1 │    -1 │        2 │
└───┴───┴───────┴──────────┘
┌─a─┬─b─┬─_sign─┬─_version─┐
│ 2 │ 3 │     1 │        3 │
└───┴───┴───────┴──────────┘

根据返回结果,可以看到是由 3 个 part 组成。

part1 由 mysql> insert into t1 values(1,1),(2,2) 生成:

┌─a─┬─b─┬─_sign─┬─_version─┐
│ 1 │ 1 │     1 │        1 │
│ 2 │ 2 │     1 │        1 │
└───┴───┴───────┴──────────┘

part2 由 mysql> delete from t1 where a=1 生成:

┌─a─┬─b─┬─_sign─┬─_version─┐
│ 1 │ 1 │    -1 │        2 │
└───┴───┴───────┴──────────┘
说明:
_sign = -1表明处于删除状态

part3 由 update t1 set b=b+1 生成:

┌─a─┬─b─┬─_sign─┬─_version─┐
│ 2 │ 3 │     1 │        3 │
└───┴───┴───────┴──────────┘

使用 final 查询:

clickhouse :) select a,b,_sign,_version from t1 final;

SELECT 
    a,
    b,
    _sign,
    _version
FROM t1
FINAL

┌─a─┬─b─┬─_sign─┬─_version─┐
│ 1 │ 1 │    -1 │        2 │
└───┴───┴───────┴──────────┘
┌─a─┬─b─┬─_sign─┬─_version─┐
│ 2 │ 3 │     1 │        3 │
└───┴───┴───────┴──────────┘

2 rows in set. Elapsed: 0.016 sec.

可以看到 ReplacingMergeTree 已经根据 _version 和 OrderBy 对记录进行去重。

Query

MySQL master:

mysql> select * from t1;
+---+------+
| a | b    |
+---+------+
| 2 |    3 |
+---+------+
1 row in set (0.00 sec)

ClickHouse slave:

clickhouse :) select * from t1;

SELECT *
FROM t1

┌─a─┬─b─┐
│ 2 │ 3 │
└───┴───┘

clickhouse :) select *,_sign,_version from t1;

SELECT 
    *,
    _sign,
    _version
FROM t1

┌─a─┬─b─┬─_sign─┬─_version─┐
│ 1 │ 1 │    -1 │        2 │
│ 2 │ 3 │     1 │        3 │
└───┴───┴───────┴──────────┘
说明:这里还有一条删除记录,_sign为-1

MaterializeMySQL 被定义成一种存储引擎,所以在读取的时候,会根据 _sign 状态进行判断,如果是-1则是已经删除,进行过滤。

并行回放

为什么 MySQL 需要并行回放?

假设 MySQL master 有 1024 个并发同时写入、更新数据,瞬间产生大量的 binlog event ,MySQL slave 上只有一个线程一个 event 接着一个 event 式回放,于是 MySQL 实现了并行回放功能!

那么,MySQL slave 回放时能否完全(或接近)模拟出 master 当时的 1024 并发行为呢?

要想并行首先要解决的就是依赖问题:我们需要 master 标记出哪些 event 可以并行,哪些 event 有先后关系,因为它是第一现场。

MySQL 通过在 binlog 里增加:

  • last_committed,相同则可以并行
  • sequece_number,较小先执行,描述先后依赖
last_committed=3   sequece_number=4   -- event1
last_committed=4   sequece_number=5   -- event2
last_committed=4   sequece_number=6   -- event3
last_committed=5   sequece_number=7   -- event4

event2 和 event3 则可以并行,event4 需要等待前面 event 完成才可以回放。
以上只是一个大体原理,目前 MySQL 有3种并行模式可以选择:

  1. 基于 database 并行
  2. 基于 group commit 并行
  3. 基于主键不冲突的 write set 并行

最大程度上让 MySQL slave加速回放,整套机制还是异常复杂的。

回到 ClickHouse slave 问题,我们采用的单线程回放,延迟已经不是主要问题,这是由它们的机制决定的:
MySQL slave 回放时,需要把 binlog event 转换成 SQL,然后模拟 master 的写入,这种逻辑复制是导致性能低下的最重要原因。
而 ClickHouse 在回放上,直接把 binlog event 转换成 底层 block 结构,然后直接写入底层的存储引擎,接近于物理复制,可以理解为把 binlog event 直接回放到 InnoDB 的 page。

读取最新

虽然 ClickHouse slave 回放非常快,接近于实时,如何在ClickHouse slave上总是读取到最新的数据呢?

其实非常简单,借助 MySQL binlog GTID 特性,每次读的时候,我们跟 master 做一次 executed_gtid 同步,然后等待这些 executed_gtid 回放完毕即可。

数据一致性

对一致性要求较高的场景,我们怎么验证 MySQL master 的数据和 ClickHouse slave 的数据一致性呢?

这块初步想法是提供一个兼容 MySQL checksum 算法的函数,我们只需对比两边的 checksum 值即可。

总结

ClickHouse 实时复制同步 MySQL 数据是 upstream 2020 的一个 roadmap,在整体构架上比较有挑战一直无人接单,挑战主要来自两方面:

  • 对 MySQL 复制通道与协议非常熟悉
  • 对 ClickHouse 整体机制非常熟悉

这样,在两个本来有点遥远的山头中间架起了一座高速,这条 10851号 高速由 zhang1024(ClickHouse侧) 和 BohuTANG(MySQL复制) 两个修路工联合承建,目前已经合并到 upstream 分支。

关于同步 MySQL 的数据,目前大家的方案基本都是在中间安置一个 binlog 消费工具,这个工具对 event 进行解析,然后再转换成 ClickHouse 的 SQL 语句,写到 ClickHouse server,链路较长,性能损耗较大。

10851号 高速是在 ClickHouse 内部实现一套 binlog 消费方案,然后根据 event 解析成 ClickHouse 内部的 block 结构,再直接回写到底层存储引擎,几乎是最高效的一种实现方式,实现与 MySQL 实时同步的能力,让分析更接近现实。

基于 database 级的复制,实现了多源复制的功能,如果复制通道坏掉,我们只需在 ClickHouse 侧删掉 database 再重建一次即可,非常快速、方便,OLTP+OLAP 就是这么简单!

要想富,先修路!


欢迎关注我的微信公众号【数据库内核】:分享主流开源数据库和存储引擎相关技术。

标题网址
GitHubhttps://dbkernel.github.io
知乎https://www.zhihu.com/people/…
思否(SegmentFault)https://segmentfault.com/u/db…
掘金https://juejin.im/user/5e9d3e…
开源中国(oschina)https://my.oschina.net/dbkernel
博客园(cnblogs)https://www.cnblogs.com/dbkernel
MySQL 备份之 mysqldump 源码分析 mysqldump 分析1. 前言2. 源码分析2.1 源码版本2.3 分析2.3.1. get_options2.3.2. dbConnect2.3.3. FTWRL2.3.4. start_transaction2.3.5. Refresh logs2.3.6. SHOW MASTER STATUS2.3.7. UNLOCK TABLES2.3.8. DUMP2.3.9. COMMIT3. 总结 1. 前言 mysqldump 作为 MySQL 源生支持的逻辑复制工具自从上古时代就已经被DBA广泛使用 阅读详情

相关推荐

MySQL到Clickhouse的实时复制

文章目录一、基本了解1.1 MySQL与CK的简单比较1.2 MaterializeMySQL二、MySQL->CK的实时复制实现1.1 环境准备1.2 基本功能测试三、后续一些疑问以及思考 MySQL与Clickhouse是两个完全不一样的数据库,两者均有着自己的优缺点,两者所适合的业务场景也是不一样的,在实际业务中,我们需要根据数据库自身的特性优点选择合适它的业务场景。传统的MySQL数据库虽然很好的支持了OLTP的业务,但是对于OLAP这类需要对大批量数据进行统计分析的业务场景还是存在较大的一

三思的博客 2310

高级DBA教你clickhouse数据导入MYSQL数据库技术方法

此处注意2个数据库字段映射关系。

nasen512的博客 3165

论文阅读:Visual Relationship Detection with Language Priors

Visual Relationship Detection with Language Priors(ECCV2016) 文章   尽管大多数的relationship并不常见,但是它们的object和predicate却更频繁地独立出现。paper用这个insight分别独立训练训练object和predicate的模型,然后再进行组合来预测relationship。Visual relatio...

Kivee的博客 2877

clickhouse常用SQL语句,查询、建表、数据复制迁移、删除等

文章目录1. 查询 数据库容量2. 查看所有表3. 常用查询4. MySQL导入到ClickHouse5. clickhouse表数据迁移到新的分区表 1. 查询 数据库容量 select sum(rows) as "总行数", formatReadableSize(sum(data_uncompressed_bytes)) as "原始大小", formatReadableSize(sum(data_compressed_bytes)) as "压缩大小", round(s

闫玉林的博客 3545

三、STM32F103ZET6最小系统

stm32最小系统除去主控CPU外,需要包含,电源电路,复位电路,BOOT电路,时钟电路(因为stm32有内置时钟,对时钟要求不高的话,可以不要)。NRST引脚其实芯片已经用一个约40K的电阻上拉了,所以理论上来说是不需要再外接上拉电阻的,但我看大家都是有外接上拉的,心里没有底,不管这么多,先预留着。吃过亏,特意查看了芯片手册资料,下图是官方建议的供电方案,图片来自stm32f103zet6数据手册。首先明白目标,单纯的学习软件知识并不是我希望的,我还希望会硬件设计,这样后面才能摆脱开发板。

sevendecsdn的博客 6460

java链接opc报异常org.jinterop.dcom.common.JIException: Access is denied解决

记录一下这次从发现问题到解决问题的过程 项目是通过java链接OPC,读取数据,并且发送数据的 程序一直运行正常,最近客户反馈说无法读取数据,通过查看,发现访问异常了。花了2天的时间才解决了这个异常。 org.jinterop.dcom.common.JIException: Access is denied, please check whether the [domain-username-password] are correct. Also, if not already done please c

机器学习菜鸟 1万+

Clickhouse常用sql

clickhouse一些经常使用的sql

snow_adfe的博客 755

实战干货|.NET9 C#上位机:多PLC并发通信+数据防丢+指令精准下发(10台设备实测+踩坑实录)

摘要:本文介绍了一个基于.NET9重构汽车零部件产线10台西门子S7-1200 PLC并发通信的工业级解决方案。针对原有系统存在的同步轮询阻塞、数据丢失、指令重复等问题,采用连接池复用、异步并发控制、超时隔离等技术,实现800ms内完成10台PLC并发采集、零丢包率、100%指令精准下发。方案通过.NET9的ThreadPool调度优化和ValueTask内存管理,将CPU占用控制在15%以内,解决了多PLC通信中的并发冲突、超时扩散等核心痛点,并提供了可直接复用的工业级代码实现。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 455

ClickHouse和他的朋友们(9)MySQL实时复制与实现

原文出处:https://bohutang.me/2020/07/26/clickhouse-and-friends-mysql-replication/很多人看到标题还以为自己走错了夜...

老叶茶馆 1452

【Bluedroid】AVRCP 连接源码分析(一)

AVRCP连接源码分析流程是一个涉及多个步骤和协议交互的复杂过程。在源码中,需要仔细处理各种连接状态和协议交互,以确保AVRCP连接的稳定性和可靠性。同时,还需要根据具体的应用场景和需求,对AVRCP命令和响应进行定制化处理。

byte轻骑兵的技术小窝 3320

IoU的进化之路——IoU、GIoU、DIoU、CIoU四种损失函数总结

IoU、GIoU、DIoU、CIoU四种损失函数总结

chase 8131

源码分析 | ClickHouse和他的朋友们(11)MySQL实时复制之GTID模式

本文首发于 2020-08-28 20:40:14MySQL实时复制原理篇几天前 ClickHouse 官方发布了 v20.8.1.4447-testing,这个版本已经包含了 MaterializeMySQL 引擎,实现了 ClickHouse 实时复制 MySQL 数据的能力,感兴趣的朋友可以通过官方安装包来做体验,安装方式参考 https://clickhouse.tech/#quick-start,需要注意的是要选择 testing 分支。MaterializeMySQL 在 v20.8.1.444

dbkernel 的博客 257

【100%通过率】华为OD机试真题 JavaScript【数字最低位排序】【最低位排序】

2023华为OD机试真题 JavaScript【数字最低位排序】【最低位排序】 给定一个非空数组(列表) 起元素数据类型为整型 请按照数组元素十进制最低位从小到大进行排序 十进制最低位相同的元素,相对位置保持不变 当数组元素为负值时,十进制最低为等同于去除符号位后对应十进制值最低位

MISAYAONE的博客 587

ClickHouse实战--同步mysql(二)源码解析

六 、源码分析 6.1 概述 在最新源码 (v20.13.1.1) 中,ClickHouse 官方对 DatabaseMaterializeMySQL 引擎的相关源码进行了重构,并适配了 GTID 同步模式。ClickHouse 整个项目的入口 main 函数在 /ClickHouse/programs/main.cpp 文件中,主程序会根据接收指令将任务分发到 ClickHouse/programs 目录下的子程序中处理。本次分析主要关注 Server 端 MaterializeMySQL 引擎的工作流.

写轮眼之大数据 633

跨境电商产品信息抓取:使用Python爬虫进行市场分析

跨境电商平台是指为不同国家和地区的买卖双方提供在线交易服务的电子商务平台。亚马逊(Amazon):全球最大的电商平台之一,提供丰富的商品种类和全球配送服务。eBay:全球知名的在线拍卖和购物网站,支持个人和企业卖家。速卖通(AliExpress):阿里巴巴旗下的跨境电商平台,主要面向全球消费者提供中国制造的商品。Wish:以移动端为主的跨境电商平台,主打低价商品和个性化推荐。这些平台上的商品数据包括商品名称、价格、销量、用户评价、库存等信息,对于市场分析具有重要价值。

2201_76125261的博客 1235

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

Java开发新手应该挑战一下你的软肋(文末送书)

本文来源于华章计算机(hzbook_jsj)转载请标明出处DB-Engines 根据数据库管理系统的受欢迎程度对其进行排名,最近发布了 2020年 8月份的数据库排名。该网站实时统计了...

码农小胖哥 880

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

DB-Engines 4月数据库排名:Redis有望甩掉“千年老七”?

来源:华章计算机(hzbook_jsj)DB-Engines最近发布了2021年4月份的数据库排名。该网站根据数据库管理系统的受欢迎程度对其进行排名,实时统计了370种数据库的排名指数。前...

华章IT官方博客 1008

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

DB-Engines 8 月数据库排名:Redis悄悄拔高,猛超Elasticsearch

本文来源于华章计算机(hzbook_jsj)转载请标明出处DB-Engines 根据数据库管理系统的受欢迎程度对其进行排名,最近发布了 2020年 8月份的数据库排名。该网站实时统计了...

华章IT官方博客 313

干测试三年,我对数据库那可是一脸懵逼!

本文来源于华章计算机(hzbook_jsj)测试开发日常接触数据库相对较多,那么现在哪些数据库最受测试开发门的喜爱?我们来看看(粉丝回馈:文末有赠送福利,关注星标Python测试社区订阅...

325

眼花缭乱的数据库,怎样选择?给你这个书单,想学哪个学哪个

导读:随着分布式、云计算、大数据等技术的飞速发展,各种数据库百花齐放。它们在具体功能和使用场景上各有千秋,在实现细节上也不尽相同,但是在工作原理上又有着诸多共通性和相似性。在这个技术变革的...

大数据 577

AI时代C++进阶指南:2024-2026核心方向与学习路线

在当今技术领域,编程语言的选择往往决定了开发者的职业路径。从底层原理来看,系统级编程语言的核心价值在于对硬件资源的直接控制和高性能计算能力。C++作为一门支持零成本抽象和手动内存管理的语言,其技术价值在于为开发者提供了对程序性能和行为的极致掌控力,这在需要确定性和低延迟的场景中至关重要。这种能力使其在AI基础设施、自动驾驶、金融科技等对实时性要求极高的应用场景中成为不可替代的选择。本文聚焦于C++在AI时代的核心价值,探讨了其在**高性能计算**和**实时系统**中的关键作用,并提供了从基础到进阶的实战学习

weixin_30416871的博客 427

如何为DBX开发JDBC驱动插件:扩展支持更多数据库的开发者指南

DBX是一款15MB的轻量级跨平台数据库客户端,支持MySQL、PostgreSQL、SQLite、Redis、MongoDB、DuckDB、ClickHouse、SQL Server等多种数据库。如果你想让DBX支持更多的数据库类型,或者想要基于JDBC协议为特定数据库开发插件,本文将为你提供完整的开发指南。🔧 ## 为什么需要JDBC驱动插件? DBX默认使用原生Rust驱动来连接各种数

gitblog_00671的博客 478

技术文章系列整理(持续更新)

本博客有很多关于性能及测试开发的文章。我试着对你可能感兴趣的一些重要文章进行分类。

7DGroup,让技术更有价值! 1万+

程序员技术成长的动态闭环:从知识输入到认知校准

技术成长不是线性积累,而是一个涉及阅读、实践、表达与反馈的动态系统。理解‘知识加工-输出-反馈’的延迟性与耦合性,是突破‘学了不会用’‘写了没提升’困境的关键。本文聚焦程序员最常失真的两个环节——技术博客写作与论坛互动,揭示其本质是元认知训练与可证伪假设的构建过程。通过决策快照表、反流量写作、四段式提问等实操方法,将抽象能力转化为可测量、可迭代的行为单元。适用于希望摆脱无效勤奋、提升技术判断力与架构思辨能力的中高级开发者。

SailingAptech的专栏 468

clickhouse 核心特性及架构介绍

ClickHouse的全称是:Click Stream,Data WareHouse 简称:CH 是用于联机分析处理(OLAP)的列式数据库管理系统(DBMS),提供千亿级大数据集的在线多维查询和分布式存储 本文针对CH的特性、适用场景、不适用场景及架构进行初步介绍,提供CH的基础入门知识。

penriver的博客 2857

【Clickhouse】Clickhouse-copier数据复制-迁移案例

Clickhouse-copier数据复制-迁移案例背景方案调研方案一:拷贝数据目录操作流程方案二:使用 remote 表函数操作流程方案三:Clickhouse-copier(已采用)Clickhouse-copier的工作流介绍配置task.xml将task.xml写入zk执行过程启动任务日志分析补充说明 背景 因新环境上线,需要从旧环境中迁移数据至新环境。 方案调研 方案一:拷贝数据目录 先观察一下 ClickHouse 在文件系统上的目录结构(配置文件 /ect/clickhouse-server/

大锅霍皮久的博客 6449
上一篇: 程序人生 | 我的《C陷阱与缺陷》读书笔记
下一篇: 问题定位 | Peronca Xtrabackup 8.0近日踩坑总结 - xtrabackup 2.4和8.0区别
dbkernel
博客等级 码龄4年 60粉丝 42原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值