数据特征采样在 MySQL 同步一致性校验中的实践

news/2024/7/7 7:26:54/文章来源:https://www.cnblogs.com/vivotech/p/18283300

作者:vivo 互联网存储研发团队 - Shang Yongxing

本文介绍了当前DTS应用中,MySQL数据同步使用到的数据一致性校验工具,并对它的实现思路进行分享。

一、背景

在 MySQL 的使用过程中,经常会因为如集群拆分、数据传输、数据聚合等原因产生流动和数据复制。而在通常的数据复制过程中,因为涉及到目标的写入不可控、服务应用的未知问题、人为导致的异常缺陷等,很难保证复制产生的数据与源完全一致。除了通过完善流程与服务应用的能力和可靠性来保障数据一致性外,也需要提供快速有效的数据校验机制,便于发现存在异常的数据位置,服务于后续可能的自动重试或人工修订。

而具体到我们目前使用的数据传输服务DTS(MySQL部分),需要考虑的点:

  • 端对端从源集群到目标集群的外部数据校验

  • 内部数据校验机制,确保同步的数据正确可靠

二、选型参考

数据一致性校验,即对DTS的数据同步任务在目标产生(复制)的表数据,与在源库的原始数据进行对比,并给出对比结果。若存在不一致的情况则给出具体不一致的数据块,方便用户快速对不一致数据进行处理。它的基本原则是作为独立一个环节,既不能影响同步本身,也不能影响业务数据库的正常使用。

 

为了达成数据一致性的校验,需要具备以下的能力:

 

  • 校验的范围应当包括库表对象的结构、实际行数据已经其它被任务定义包含在内的内容(索引、视图、存储过程等)。

  • 校验应当在保证较小地侵入影响数据库的同时,尽快完成涉及数据的对比检查。

  • 校验应当具备精确定位不一致数据块的位置的能力,用于支持后续进行的数据修订。

三、端对端的数据一致性校验

3.1 现有问题

在数据传输的场景中,相关的数据大概率分散在无关的不同实例上,这种情况下想要对两端的数据进行对比分析,比较包括结构、索引、列数据等维度,当然可以通过最直接的逐行逐列地遍历各个表方式,这种方式最直观且可以最精确地对比相关的数据,但显然如果数据总量或数据列的规模较大时,这种逐行对比的方式会存在下列问题:

  • 执行耗时长

  • 结果时效性差,增量场景几乎无法使用

一般来说如果无法接受“全量”性质的扫描带来的时间开销,可以将“全量”转换为“部分”的验证,本质上一些数据同步场景后执行的点检就是数据的部分校验,这种方式完成速度快,可用于关键数据的快速验证,但这种形式也存在明显的问题:

  • 数据集覆盖度难以平衡

  • 如果确实存在一些不一致的情况,可能会被遗漏

针对这些问题,也许可以采取一些额外的校验保障,例如数据集大小(行数等)的校验,一定程度上可以降低数据不完整的错判风险。

那么回到我们的实际使用场景中,为了解决数据可靠性的问题,我们调研了几种比较主流的MySQL数据校验方案:

图片

pt本身更常被运维用于检查集群内主从的表数据是否一致,这显然与数据传输的场景存在较大的出入,不符合我们的实际需求。

px在实现上更满足数据传输场景的需求,同时包括上述两者在内,一些公用云的MySQL类型数据库的数据一致性校验也是采用类似部分采用数据进行比对的形式:

  • 表的数据分块

         - 不分支持动态分块大小来调整负载

  • 分块级的数据特征计算→简化对比规模

这个思路在数据遍历的完整性和效率方面均做了一定的取舍,相当于是一种中间状态。

而为了达成满足一些定制场景以及提高使用效率的目的,我们最终是采用了px-table-checksum的实现思路来完成的数据校验实现,接下来以一个具体的表结构来介绍进行数据对比的思路。

sysbench在MySQL的压测场景产生的一种表结构如下:

图片

 

前文我们已经提到虽然直接使用全表逐行对比会存在时间消耗较大的问题,但如果业务属性上源和目标的表发生变化的频率很低(定时更新类),这种校验也是可以发挥作用的:

SELECT id, k, c, pad FROM sbtest1 limit n;

基于这样简易的抽取逻辑进行逐行的比对是可以做到完全校验的,代价就是时间上的开销非常大。

3.2 实现思路

而我们将要采取的分块获取数据的方式则是在这一基础上进行了优化,我们逐步介绍逻辑,首先这里假定使用的分块大小为10行–chunk_size=10

1.数据分块

mysql> SELECT * FROM sbtest1 FORCE INDEX(`PRIMARY`) WHERE ((`id`>= 1) AND  ((`id`) <= 10));+----+---------+-------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------+
| id | k       | c                                                                                                                       | pad                                                         |
+----+---------+-------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------+
|  1 | 3230682 | 68487932199-96439406143-93774651418-41631865787-96406072701-20604855487-25459966574-28203206787-41238978918-19503783441 | 22195207048-70116052123-74140395089-76317954521-98694025897 |
|  2 |  556124 | 13241531885-45658403807-79170748828-69419634012-13605813761-77983377181-01582588137-21344716829-87370944992-02457486289 | 28733802923-10548894641-11867531929-71265603657-36546888392 |
|  3 | 2757236 | 16516882386-05118562259-88939752278-62800788230-55205008755-06868633780-74894238647-69655573455-70526404237-73358617781 | 73198647949-50059256035-48039302709-77824424754-93913530645 |
|  4 | 3080419 | 88936868384-35413314949-47572298747-62301572168-04725458949-84024294746-95505588496-92367527122-22018143923-07447340456 | 35540797267-28848817162-69859656941-29402637497-25804052865 |
|  5 | 2755665 | 38000028170-70584813101-64973736504-76149487237-52945047102-11275974719-79041047383-53171259040-17278926045-71359842623 | 24429914423-05032864825-55698585282-50062977513-27378309065 |
|  6 | 1689856 | 90918476202-02089391467-64272595615-72064149272-80467152282-18848936545-61767310237-38205570677-59195835610-06087350040 | 37783104634-08719671341-44662007841-24831185436-08450447859 |
|  7 |  367648 | 69873895168-42508713642-77344499431-18964268934-99713628807-43846750254-87716358839-40367934805-98231362293-37861509854 | 65003009667-83421336486-43798350655-86517975104-79705317753 |
|  8 | 4069722 | 03426487304-27156530652-16106764306-84175870374-36434920674-38029783924-53173822921-96186178437-58319716571-95077711704 | 31784578367-14387657451-27946335198-02419089416-67782425795 |
|  9 | 4608666 | 81689156752-44921640552-35987563480-16691191991-27936686268-18588338593-16235034269-90308874838-52095870672-98075954786 | 03144707666-87793208474-21823431822-18751222077-39980824756 |
| 10 | 2975029 | 03392914016-90098596959-72565142257-56206208928-54469213163-80095083408-91183949560-45926629535-07758798231-14358688386 | 44959141897-52907315042-08586003451-12076203782-52848887604 |
+----+---------+-------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------+

2.按列聚合

mysql> SELECT CONCAT_WS('#', `id`, `k`, CRC32(`c`), CRC32(`pad`), CONCAT(ISNULL(`pad`))) AS CRC FROM `sbtest1` FORCE INDEX(`PRIMARY`) WHERE ((`id`>= 1) AND  ((`id`) <= 10));+-----------------------------------+
| CRC                               |
+-----------------------------------+
| 1#3230682#4041434652#3764881225#0 |
| 2#556124#847118261#777674597#0    |
| 3#2757236#2890838841#3354864368#0 |
| 4#3080419#2053219065#3018733667#0 |
| 5#2755665#4230533455#266494007#0  |
| 6#1689856#2940387143#1608825719#0 |
| 7#367648#2894429300#3186127078#0  |
| 8#4069722#1825802258#3718534773#0 |
| 9#4608666#1487055134#1908388285#0 |
| 10#2975029#1272074468#264227369#0 |
+-----------------------------------+

3. 按行聚合

在前一步的基础上,可以再计算一次当前聚合列的CRC32值使长度减少(因为按列聚合时使用的group_concat可能会存在长度的限制,这也是需要关注的问题)

mysql> SELECT CRC32(CONCAT_WS('#', `id`, `k`, CRC32(`c`), CRC32(`pad`), CONCAT(ISNULL(`pad`)))) AS CRC FROM `sbtest1` FORCE INDEX(`PRIMARY`) WHERE ((`id`>= 1) AND  ((`id`) <= 10));+------------+
| CRC        |
+------------+
|  501470676 |
| 3723711314 |
| 4091031521 |
|  571991173 |
| 3184804606 |
| 1525903855 |
| 3331492255 |
|  105586567 |
| 3803559186 |
| 3193672787 |
+------------+  mysql> SELECT GROUP_CONCAT(CRC32(CONCAT_WS('#', `id`, `k`, CRC32(`c`), CRC32(`pad`), CONCAT(ISNULL(`pad`))))) AS CRC FROM `sbtest1` FORCE INDEX(`PRIMARY`) WHERE ((`id`>= 1) AND  ((`id`) <= 10));+------------------------------------------------------------------------------------------------------------+
| CRC                                                                                                        |
+------------------------------------------------------------------------------------------------------------+
| 501470676,3723711314,4091031521,571991173,3184804606,1525903855,3331492255,105586567,3803559186,3193672787 |
+------------------------------------------------------------------------------------------------------------+

4.特征计算

到这一部分为止,我们可以将这种类型的CRC值作为这10行4列数据块的一种“特征”,用它来代表这部分数据,可以进一步进行压缩来提高比对效率,可选md5或继续CRC32等计算方式。

mysql> SELECT CRC32(GROUP_CONCAT(CRC32(CONCAT_WS('#', `id`, `k`, CRC32(`c`), CRC32(`pad`), CONCAT(ISNULL(`pad`)))))) AS CRC FROM `sbtest1` FORCE INDEX(`PRIMARY`) WHERE ((`id`>= 1) AND  ((`id`) <= 10));
+------------+
| CRC        |
+------------+
| 3337375759 |
+------------+mysql> SELECT md5(GROUP_CONCAT(CRC32(CONCAT_WS('#', `id`, `k`, CRC32(`c`), CRC32(`pad`), CONCAT(ISNULL(`pad`)))))) AS md5 FROM `sbtest1` FORCE INDEX(`PRIMARY`) WHERE ((`id`>= 1) AND  ((`id`) <= 10));
+----------------------------------+
| md5                              |
+----------------------------------+
| 6b2fb38d05fee0733382f2e4d6dc2f91 |
+----------------------------------+

实际使用中使用更大的数据块来进行映射,能加快校验的速度:

  • 数据块越大,特征的精度越低,但匹配校验的速度越快,对源和目标的负载越大。

  • 数据快越小,特征的精度越高,但匹配校验的速度越慢,对源和目标的负载越小。

相对应的,以上是在源计算对应块的特征,在目标以同样的形式计算可以得到一个“类似”的结果,通过对它进行比对,可以判断两块数据的特征是否一致。  但这同样也有一些问题

  • 概率上存在特征值相同但数据存在差异的情况,无法避免。

  • 比对的块依赖主键ID,不允许在目标存在主键覆盖的情况(源的数据因主键冲突被跳过)。

若存在数据不一致(块之间的CRC32值不一致),此时可以基于当前chunk的上下边界(upper/lower bound)进行进一步切分,通过精确的数据对比来定位到不一致的行。

图片

数据最终一致性

前文中的例子更偏向于一个单纯的全量数据抽取场景,如果目标的数据存在一定程度上的变化时,如何对应处理呢?

  • 差异块的重复校验

我们需要解决两个问题:尽可能在机制上确保数据不会出错,若存在异常或无法处理的情况应当以中断同步为优先选择;同时需要在端对端数据校验的基础上覆盖增量的数据同步场景。

数据校验任务并不是持续运行的场景,它应当是在低峰期、同步延迟1秒内或在业务要求的情况下发生的行为,那么基于数据同步的最终一致性特征,当增量场景下校验出某些块存在差异时:

例如:

两侧的chunk[1001-2000]存在差异,那么需要按照精细拆分地形式定位到具体的差异行, 一般基于binlog的延迟在0秒(1秒内)时,行的差异数量是有限的,可以对其进行全部的记录或抽样记录。

在一定的时间间隔后重新校验上一次记录中的差异行,判断是否最终达成了一致;

可能存在特殊的场景,只频繁更新某一行,导致校验一直无法判断两端一致。

图片

四、总结与思考

经过一定时间的线上实际应用,这种方案确实可以解决绝大部分(99%以上)的校验需求,不论是纯粹的全量还是涉及到增量的场景,都可以完成定点形式的数据一致性校验能力,但总的来说,它也存在可以优化改进的点:

  1. 本质上,块的特征计算值(MD5或CRC32)一致,还是存在内容实际不一致的可能性,虽然这部分概率很低,需要在当前基础上寻找更精确可靠的采样计算方式。

  2. 目前提供的一致性校验方案,只能支持同构型的数据库间,例如本文介绍的mysql->mysql(pg,tidb等),DTS支持的其它数据场景(redis->redis/kv)也是类似的情况,对于异构数据(例如订阅),暂时就没有比较好的方案可以做端对端的校验,需要使用方抽检部分或核心数据。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/738007.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

什么是容器镜像?

镜像是容器的模板,容器运行需要借助镜像来装载环境。镜像描述了容器所需的运行时环境,我们以Docker镜像为例来了解镜像到底是什么。Docker镜像实际上是由一层一层的文件系统构成,这种层级的文件系统称为UnionFS。UnionFS文件系统是一种分层、轻量级并且高性能的文件系统,它…

字符串相似度算法完全指南:编辑、令牌与序列三类算法的全面解析与深入分析

在自然语言处理领域,人们经常需要比较字符串,这些字符串可能是单词、句子、段落甚至是整个文档。如何快速判断两个单词或句子是否相似,或者相似度是好还是差。这类似于我们使用手机打错一个词,但手机会建议正确的词来修正它,那么这种如何判断字符串相似度呢?本文将详细介…

Avalonia应用在基于Linux的国产操作deepin上运行

本文介绍了Avalonia应用如何在基于Linux的国产操作deepin上运行。deepin系统介绍 deepin(原名Linux Deepin)致力于为全球用户提供美观易用,安全可靠的 Linux发行版。deepin项目于2008年发起,并在2009年发布了以 linux deepin为名称的第一个版本。2014年4月更名为 deepin,在中…

java中的测试片段和include控制器使用

1.作用 可复用,提高测试计划的可维护性和效率。 2.具体使用 2.1在jmeter中将写好的一组请求保存为测试片段,保存到一个jmx文件 2.2新建一个线程组,添加include控制器,选择刚刚保存的测试片段文件即可将刚刚的测试片段重用。

splay-前驱后继

在平衡树中,经常会让我们查一下一个值的前驱或后继是谁,写两个函数就非常麻烦好吧,所以这里咱们用一点小技巧来让他变 成一个函数(这里的前驱后继定义时包括与本身相等的值) 代码点击查看代码 int nxt(int k){if(!m[rt].size) return 0;int root=rt;while(k!=m[root].val&…

softlockup detector

1 简介 从内核稳定性问题的角度来看内核安全,是基础,也是必备技能。很多时候,一个内核稳定性问题,就是造成系统安全的罪魁祸首。 当出现异常死锁、Hang up、死机等问题时,watchdog的作用就很好的体现出来。Watchdog主要用于监测系统运行情况,一旦出现以上异常情况,就会重…

drduino串口通信中文乱码

​ 第一次使用 Arduino 板学习时,遇到了串口工具接收乱码的问题。 最初认为可能是数据位或停止位设置不正确。当前设置如下:波特率:9600 数据位:8 校验位:无 停止位:1在 Arduino 代码中使用 Serial.begin(9600) 进行初始化。 Serial.begin(9600):- 波特率:9600- 数据位…

合理利用符号,用负反馈解决正反馈系统

首先,系统框图:此处的Kyrg当成是1,aircraft的状态方程系数为:A=[-0.0558 -0.9968 0.0802 0.0415; 0.598 -0.115 -0.0318 0; -3.05 0.388 -0.4650 0; 0 0.0805 1 0]; B=[0.00729 -0.475 0.153 0]; C=[0 1 0 0]; D=0;使用函数ss2tf和tf求出系统的传递函数为:sysGs =-0.475 …

若依框架前端表格自适应

1. 背景 问题描述: 如图,若依前端表格高度都是固定写死的,因此会出现底部空一部分,现在希望自适应表格,使得表格一屏展示,且在隐藏查询条件等操作,导致屏幕大小变化时,表格可以同步自适应。问题现状:很多时候,前端开发都是尽可能本机调整到刚刚好的高度,但不同用户不…

CentOS 7 升级 OpenSSH 9.8p1

背景 OpenSSH 官方发布安全通告,披露CVE-2024-6387 OpenSSH Server远程代码执行漏洞。 环境操作系统 内核 openssh 版本 openssl 版本7.8.2003 3.10.0-1127 7.4p1 1.0.2k-fips安装编译软件和下载 OpenSSH9.8p1 软件包 mkdir -p /data/software cd /data/software/yum install…

ComfyUI基础篇:为什么要学 ComfyUI?

前言:在AI生成图像领域,有许多产品,例如 Midjourney 和 Stability AI 等。为什么要学习 ComfyUI 呢?我斗胆带大家一起分析一下。目录1.Midjourney VS Stable Diffusion2.SD Web UI VS ComfyUI3.总结Midjourney VS Stable Diffusion在回答这个问题之前,我觉得有必要介绍下目…

功能齐全!一套基于AGPL3开源协议开源的智慧物业社区系统!!

ejyy —— 一套开源的智慧物业解决方案。实现了微信公众号、小程序、PC、H5、智能硬件多端打通,旨在提升物业公司效率、规范物业服务流程、提升物业服务满意度、加强小区智慧化建设、便捷业主服务。大家好,我是 Java陈序员。 今天,给大家介绍一套开源的物业社区管理系统,涵…

关于搭建可商用AI平台的小感想

AI时代已经到来,建立自己的AI平台不仅能提升技能,还能带来更多职业和商业机会。我们的开源AI平台解决了技术难题,并提供全套商业化解决方案,让你专注于业务拓展。想学习从0-1搭建AI平台的朋友,欢迎加入我们的开发者交流群,一起交流学习。前言 AI时代已经到来,从智能客服…

QChartView显示实时更新的温度曲线图(二)

目录参考图说明1. 项目结构2. TempChartView.pro3. main.cpp4. TemperatureSeries.qml5. main.qml详细说明 参考图说明Qt Charts 提供了一系列使用图表功能的简单方法。它使用Qt Graphics View Framework 图形视图框架,因此可以很容易集成到用户界面。可以使用Qt Charts作为QW…

程序人生日记20240704|工作零食:米饭+十分米莲藕汁+饼干(减脂记录)

程序员的工作饮食减脂记录打卡 餐别:早餐 零食详情:(同事给的不算统计内) 零食名称:十分米莲藕汁配饼干 其他选择:米饭+海盐饼干。 大致热量估算: 莲藕汁约50卡,低脂全麦饼干2片约80卡,米饭约500卡,总计约630卡。 初始数据: 体重:90公斤 目标:80公斤 完成情况:完…

开发一个题库系统App和小程序的心得

开发一个题库系统App和小程序的心得序言 对于一名开发者来说,独自开发一款小程序与App,也许总会有一些疑问:1. 需要掌握哪些技术? 答:java、vue、及常规Linux命令2. 需要多少成本? 答:服务器购买,云服务器新人50多三年; 域名购买,10块的域名够用,后续每年30左右的续…

SFE人才需要具备哪些能力

SFE(销售队伍效力)人才在企业中扮演着至关重要的角色,他们需要具备一系列的能力来确保销售队伍的高效运作和业绩提升。关于SFE的角色和能力,可以从业务理解、数据洞察、向上管理以及效率提升等几个方面来通俗地解释。01 懂业务 SFE人才首先需要深入了解公司的业务,像医药企…

doris 数据库与mysql的不同之处

1.doris与mysqldoris可以使用mysql驱动进行连接,也支持mysql的部分语法。 2.具体分析清空表数据 在mysql中,清空表数据有两种方式: 一种是delete from table_name,一种是truncate table table_name。 而在doris中,清空表数据只能使用truncate table table_name。delete fr…

Kylin V10SP2安装openGauss5.0.2企业版

一、本地系统环境 [root@localhost ~]# cat /etc/os-release NAME="Kylin Linux Advanced Server" VERSION="V10 (Sword)" ID="kylin" VERSION_ID="V10" PRETTY_NAME="Kylin Linux Advanced Server V10 (Sword)" ANSI_COLO…

VMware ESXi 8.0U3 macOS Unlocker OEM BIOS Huawei (华为) FusionServer 定制版

VMware ESXi 8.0U3 macOS Unlocker & OEM BIOS Huawei (华为) FusionServer 定制版VMware ESXi 8.0U3 macOS Unlocker & OEM BIOS Huawei (华为) FusionServer 定制版 ESXi 8.0U3 标准版,Dell (戴尔)、HPE (慧与)、Lenovo (联想)、Inspur (浪潮)、Cisco (思科)、Hitac…