【AICon】AI 大模型超全落地场景&最佳实践 了解详情
写点什么

DM 运维踩坑实践总结

  • 2020-12-05
  • 本文字数:6700 字

    阅读完需:约 22 分钟

DM运维踩坑实践总结

8 月 16 - 19 日,与零一万物李开复、蔚来李斌、面壁智能李大海,及工商银行、交通银行、华夏银行等 100+ 行业专家相聚 FCon x AICon

背景


在早期从 MySQL 到 TiDB 实施同步操作过程中,我们大多数用的是 mydumper+loader 进行整体全量备份的导出,之后拿到 meta 信息后,通过 syncer 实现增量同步,整体操作起来比较麻烦,涉及的配置文件较多,其基本原理就是 Syncer 通过把自己注册为一个 MySQL Slave 的方式,和 MySQL Master 进行通信,然后不断读取 MySQL Binlog,进行 Binlog Event 解析,规则过滤和数据同步。其架构如下:



而后 pingcap 官方推出了 TiDB Data Migration (DM)套件,这一套件极大地降低了同步工具使用的门槛。DM 是一体化的数据迁移任务管理平台,支持从 MySQL 或 MariaDB 到 TiDB 的全量数据迁移和增量数据复制。使用 DM 工具有利于简化错误处理流程,降低运维成本。后续更是有 dm-portal 工具方便 dba 通过图形化界面的方式进行选择性导出和自动生成配置文件,虽然有一些小 bug 和不够人性化的方面,但无伤大雅,可惜的是这个项目最后咨询官方得知被砍掉了,不再进行维护。


原因


我有幸从 DM 内测版本开始就接触和使用这一工具,直至其最新版 1.0.6,见证了 DM 功能不断的完善,真切体会到了这一工具给我们带来的帮助,我认为这是每一个 DBA 和 TiDB 使用者都应该了解甚至熟练掌握的工具,因为大多数场景下,我们使用 TiDB 并不是全新的系统上去直接建库建表,而是从 MySQL 迁移过来,先进行性能对比和测试,而后进行数据迁移的,因此熟练掌握 DM 工具可以让你的工作事半功倍。


架构


集群配置


集群版本:v3.0.5集群配置:普通SSD磁盘,128G内存,40 核cputidb21 TiDB/PD/pump/prometheus/grafana/CCStidb22 TiDB/PD/pumptidb23 TiDB/PD/pumptidb01 TiKVtidb02 TiKVtidb03 TiKVtidb04 TiKVtidb05 TiKVtidb06 TiKVtidb07 TiKVtidb08 TiKVtidb09 TiKVtidb10 TiKVtidb11 TiKVtidb12 TiKVtidb13 TiKVtidb14 TiKV/DM-prometheus/DM-grafana/DMMtidb15 TiKV/DMW1tidb16 TiKV/DMW1
复制代码


正常来说,官方建议抽出单独的机器来部署 DM,且推荐每个节点上部署单个 DM-Worker 实例。除非机器拥有性能远超 TiDB 软件和硬件环境要求中推荐配置的 CPU 和内存,并且每个节点配置 2 块以上的硬盘或大于 2T 的 SSD,才推荐单个节点上部署不超过 2 个 DM-Worker 实例。而我们的线上环境机器比较吃紧,所以一直以来都是和 TiKV 进行混部的,例如上述架构中,选取了 tidb14,tidb15,tidb16 进行 dm 相关的软件部署。所幸运行起来效果还可以,但有条件的建议大家还是老老实实按照官方文档,单独部署。


DM 架构



DM 架构如上图所示,主要包括三个组件:DM-master,DM-worker 和 dmctl。DM-master 负责管理和调度数据迁移任务的各项操作 DM-worker 负责执行具体的数据迁移任务 dmctl 是用来控制 DM 集群的命令行工具具体的功能本文不再赘述,可参考官方文档了解每一个模块的详细功能


DM 特性


Table routing 合并迁移 Block & allow table lists 白名单 Binlog event filter binlog 级别过滤 Shard support 合库合表。


新特性


dm 从内测版本开始,每一个版本的迭代都修复和新加入了不少功能,这里我单独拎出来 1.0.5 这个版本,因为从这个版本开始,它支持了以前从来没有但又让人早就期盼已久的功能:online ddl 的支持。


众所周知,MySQL 在数据量大了后,没有人会直接去对原表进行 alter,大多数人都通过第三方工具 pt-online-schema-change 或者 gh-ost 来进行改表,以此削减改表期间对线上业务的影响。而早期的 dm 不支持该功能时,每次上游改完表后,由于临时表(_xxxx_new,_xxx_gho 等)不在白名单里,会直接导致下游 tidb 丢失该 DDL,引发同步异常报警。当然,如果你是全库同步,那自然不会有这个问题,但绝大多数场景下都是部分表导入到 TiDB,用到了白名单功能的情况下就会导致该问题出现。而 1.0.5 版本后,这便不再是问题,虽然目前仅仅只能同时支持一种改表工具,但对比之前来说,无疑是我认为最好的改进,还没用的朋友们不妨试一试。


例如:


上游通过 pt-online-schema-change 工具为表 helei5 新增一列–alter=“ADD column hl2 varchar(10) not null default ‘’;” D=h_2,t=helei5 先看下没有配置跳过的情况



几个关键的词:


skip event 因为不在白名单中被跳过skip event, need handled ddls is empty ,中间表因为被过滤掉在下游不存在,所以提示is empty,也被跳过RENAME TABLE `h_2`.`helei5` TO `h_2`.`_helei5_old`","RENAME TABLE `h_2`.`_helei5_new` TO `h_2`.`helei5`rename操作在上游为了保证原子性是一条SQL实现表名互换的,我们可以看到,好在拆分后也依旧是被跳过的,这是因为中间表不存在rename的ddl里部分表例如_helei5_new是空的,所以整个SQL不会被执行"RENAME TABLE `h_2`.`helei5` TO `h_2`.`_helei5_old`的话被执行了是我们不希望看到的
复制代码


此时 task 状态依旧是 running,但下游已经没有新增的列


{            "taskName": "task_4369",            "taskStatus": "Running",            "workers": [                “192.168.1.248:8262"            ] 此时插入包含新列h2的数据mysql> insert into helei5 values(14,'cccc','pt alter');
复制代码


这个时候 dm 就会报错


  {            "taskName": "task_4369",            "taskStatus": "Error - Some error occurred in subtask. Please run `query-status task_4369` to get more details.",            "workers": [                “192.168.1.248:8262"            ]
报错信息是:msg": "[code=36027:class=sync-unit:scope=internal:level=high] current pos (4369-binlog|000001.000021, 62771055): gen insert sqls failed, schema: h_2, table: helei5: Column count doesn't match value count: 2 (columns) vs 3 (values) 点位:sync": { "totalEvents": "3", "totalTps": "0", "recentTps": "0", "masterBinlog": "(4369-binlog.000021, 62774081)", "masterBinlogGtid": "1c3add9b-7c26-11e7-81bf-70e28411103e:1-910975,1d1872fd-7c26-11e7-81bf-70e284110e52:1-3,200ccab3-f941-11e8-b6de-6c92bf96384c:1-800846", "syncerBinlog": "(4369-binlog|000001.000021, 62765733)",

复制代码


因为少列,所以报错,我们在下游添加列,然后跳过


mysql> alter table helei5 add column h2 varchar(10) not null default '';跳过语句是:» sql-skip --worker=192.168.1.248:8262 --binlog-pos=4369-binlog|000001.000021:62765733 task_4369{    "result": true,    "msg": "",    "workers": [        {            "result": true,            "worker": "",            "msg": ""        }    ]}
复制代码


dm-worker 的日志有如下内容:


[2020/05/14 15:48:05.883 +08:00] [INFO] [operator.go:136] ["set a new operator"] [task=task_4369] [unit="binlog replication"] ["new operator"="uuid: b52784e4-e804-46f5-974c-ca811a34dc30, pos: (4369-binlog|000001.000021, 62765733), op: SKIP, args: "]
复制代码


执行恢复任务


» resume-task task_4369           {            "taskName": "task_4369",            "taskStatus": "Running",            "workers": [                “192.168.1.248:8262"
复制代码


在添加 online-ddl-scheme: "pt"参数后,下游成功读取到 pt-online-schama-change 加的新列:



gh-ost 工具同理:


几个关键词:ghc表的创建DM是忽略的:prepare to handle ddlsskip event, need handled ddls is emptygho表的创建和新DDL也是忽略的,而是把该 DDL 记录到 dm_meta.{task_name}\_onlineddl 以及内存中:prepare to handle ddlsskip event, need handled ddls is emptydel表的创建也是忽略的:rename /* gh-ost */ table `h_2`.`helei5` to `h_2`.`_helei5_del`, `h_2`.`_helei5_gho` to `h_2`.`helei5`不执行 rename to _helei5_del。当要执行 rename ghost_table to origin table 的时候,并不执行 rename 语句,而是把记录在内存中的 DDL 读取出来,然后把 ghost_table、ghost_schema 替换为 origin_table 以及对应的 schema,再执行替换后的 DDL。操作完日志会有:finish online ddl and clear online ddl metadata in normal mode
复制代码


在添加 online-ddl-scheme: "gh-ost"的参数后,下游也读取到了加的列



1062 的踩坑


在早期,我们有一个业务通过 DM 同步到 TiDB,但每过几个小时后,同步总是中断,而每次我们人工 resume task 又能恢复,咨询后得知 resume 操作后,dm 内部前几分钟是 debug 模式,执行的 replace。当时的报错内容如下:


>> query-status task_3306...... "msg": "[code=10006:class=database:scope=not-set:level=high] execute statement failed: commit: Error 1062: Duplicate entry '21277ed5f5e7c3b646a5229269d54d3a7fccc08bf34c8f2113fdd4df62f4a229' for key 'clientid'\ngithub.com/pingcap/dm/pkg/terror.(*Error).Delegate\n>>query-error task_3306"errorSQL": "[tp: insert, sql: INSERT INTO `360sudi`.`client` (`id`,`clientid`,`toid`,`updatetime`) VALUES (?,?,?,?);, args: [4102315138 62ba2a78af090ab1337c6b62f8dedfc8b6338007cdeb5a7ea4e7f4b4c23e3e0c 3250350869 2019-11-21 19:54:56], key: 4102312246, ddls: []
复制代码


用自增 id 的主键查:


[helei@db01 ~]$ curl http://192.168.1.1:10080/mvcc/key/360/client/4102315138{ "key": "7480000000000011945F7280000000F4845C82", "region_id": 2278436, "value": {  "info": {   "writes": [    {     "type": 3,     "start_ts": 412703076417274370,     "commit_ts": 412703076417274370    }   ]  } }}
复制代码


根据查询出来的 commit-ts 使用 pd-ctl tso 命令看下在下游已经存在的记录提交的时间


[root@tidb helei]# /data1/tidb-ansible-3.0.5/resources/bin/pd-ctl -i -u http://192.168.1.2:2379     » tsoUsage: tso <timestamp>» tso 412703076417274327system:  2019-11-21 19:54:57.124 +0800 CSTlogic:  471» tso 412702903507091560system:  2019-11-21 19:43:57.524 +0800 CSTlogic:  104»
复制代码


查找 dm-worker 日志中跟这个记录相关的内容


-binlog.000020, 185499141), relay-binlog-gtid = "][2019/11/21 19:54:47.710 +08:00] [INFO] [syncer.go:2004] ["binlog replication progress"] [task=task_3306] [unit="binlog replication"] ["total binlog size"=378940822] ["last binlog size"=378533105] ["cost time"=30] [bytes/Second=13590] ["unsynced binlog size"=0] ["estimate time to catch up"=0][2019/11/21 19:54:47.710 +08:00] [INFO] [syncer.go:2029] ["binlog replication status"] [task=task_3306] [unit="binlog replication"] [total_events=1528442] [total_tps=1455] [tps=40] [master_position="(3306-binlog.000020, 185616633)"] [master_gtid=] [checkpoint="(3306-binlog|000001.000020, 185616633)(flushed (3306-binlog|000001.000020, 185484711))"][2019/11/21 19:54:57.157 +08:00] [ERROR] [db.go:269] ["execute statements failed after retry"] [task=task_3306] [unit="binlog replication"] [queries="[INSERT INTO `360sudi`.`client` (`id`,`clientid`,`toid`,`updatetime`) VALUES (?,?,?,?);]"] [arguments="[[4102315138 62ba2a78af090ab1337c6b62f8dedfc8b6338007cdeb5a7ea4e7f4b4c23e3e0c 3250350869 2019-11-21 19:54:56]]"] [error="[code=10006:class=database:scope=not-set:level=high] execute statement failed: commit: Error 1062: Duplicate entry '62ba2a78af090ab1337c6b62f8dedfc8b6338007cdeb5a7ea4e7f4b4c23e3e0c' for key 'clientid'"]
复制代码


比较下第二个步骤查询出来的时间和第三个步骤查询出来的时间第二个步骤 2019-11-21 19:54:57.124 +0800 CST 第三个步骤 2019/11/21 19:54:57.157 +08:00 第二个步骤 2019-11-21 19:43:57.524 的时间,在第三个步的 worker 日志里未找到相关


我们尝试过:


1.将 dm 下游配置为单一 tidb 而非 tidb 的 lvs,防止多个 ip 写入 ntp 引起毫秒级的误差(无果)2.task 文件针对 syncer 的 worker 进行限制,只让一个 syncer 进行同步(无果)3.业务变更为 replace into,开始测试改 syncer worker count 的时候,光 rolling_update 是没用的,需要 dm-ctl 去 stop/start task 才可以生效


可以看到,15:25 起,qps 在 syncer worker count 配置为 16 后瞬间从 256 涨到 4k



限制 worker,库里也有多个而非一个进程



而单个进程依然会报错 1062 不说,还会导致延迟不断增加,之后我们又调整会 16 后,能看到快速追上上游主库日志



最终我们是通过业务更改 replace into 解决该问题


DM 大批量导入调参


集群稳定运行旗舰,有新数据要通过 DM 灌入,此时会影响已有集群的稳定性如下图所示,能看到 DM 导入期间集群响应出现延迟



我们通过如下参数从原值调到-新值规避了这一问题,但每个集群场景和配置完全不同,适度谨慎调整,调整前应了解每一个参数的含义,如下仅做参考


raftstore:apply-pool-size: 3-4store-pool-size: 3-4
storage:scheduler-worker-pool-size: 4-6
server:grpc-concurrency: 4-6
rocksdb:max-background-jobs: 8-10max-sub-compactions: 1-2

复制代码


限制


版本限制:


  • 数据库版本

  • 5.5 < MySQL 版本 < 8.0

  • MariaDB 版本 >= 10.1.2

  • 仅支持 TiDB parser 支持的 DDL 语法

  • 上下游 sql_model 检查

  • 上游开启 binlog,且 binlog_format=ROW


DM 不支持的类型:


1)一次删除多个分区的操作则会报错:alter table dsp_group_media_report drop partition p202006 ,p202007 ;


2)drop 含有索引的列操作会报错 Alter table dsp_group drop column test_column;


DM-portal 限制:


●在早期还没有 dm-portal 自动化生成 task 时,我们都是自行编写 DM 的 task 同步文件●后来有了 dm-portal 自动化生成工具,只要图形页面点点点就可以了



但该工具目前有一个问题是,没有全库正则匹配,几遍你只勾选一个库,他底层是默认把每张表都给你配置一遍。这就会出现当上层 MySQL 新创建某张表的时候,下游会被忽略掉,例如当你使用改表工具 gh-ost 或者 pt-online-schema-change,你的临时表都会被当做为不在白名单内而被忽略,这个问题使用者需要注意。我们也已经反馈给了官方。且如文章第四节所示,已于 1.0.5 版本修复。


DM-worker 清理配置:


[purge]interval = 3600expires = 7remain-space = 15
复制代码


关于 relay-log,默认是不清理的,就和 mysql 的 expire_logs_days 一样,这块可以通过 dm-worker 的配置文件来进行配置,例如将 expires 配置为 7,代表 7 天后删除:


#默认 expires=0,即没有过期时间,而 remain-space=15 意思是当磁盘只剩于 15G 的时候开始尝试清理,这种情况我们极少会碰到,因此这个清理方式其实基本上是用不到的。所以建议有需要删除过期 relay-log 的小伙伴,直接配置 expires 保留天数就可以了。


DM 导入完成后,应该提供是否在完成后自动删除全备文件的选项,可以默认不删,由使用者决定是否删除。从使用者角度来说,全量备份目录无论是全量一次性导入还是 all 增量同步,后续都不会再使用到。如果 dm-worker 和 tikv 混部,会导致全备文件占据大量磁盘空间,引起 tikv region 评分出现异常,导致性能下降,这一点如果有相同的架构的朋友们需得注意。


默认调度策略是当磁盘剩余的有效空间不足 40% ,处于中间态时则同时考虑数据量和剩余空间两个因素做加权和当作得分,当得分出现比较大的差异时,就会开始调度。


所以 DM 导入完成后,要记得删除全量备份,就是 dumped_data.task_xxx 文件夹,这个全量备份一般都会比较大,而且默认是不删除的,也没有配置项。如果 dm-worker 和 tikv 混部,就会出现某个 tikv 节点磁盘已使用率高于其他,这时 pd 的 store region score 就会相比其他节点出现异常。引起性能抖动和 duration 升高


总结和感慨


零零散散,大大小小的分享也做了很多了,从小白用户第一次在 2019 年 7 月接触 TiDB,到入选核心成员组,到 MVA,到 DEVCON 2020 作为嘉宾宣讲 360 在 TiDB 的分享,再到后续获 TUG 最具有影响力内容奖章,笔者一直都是本着分享才能让人进步的态度,毫无保留地去分享技术干货。因为我真真切切地感受到了 TiDB 产品本身在不断的做大,做强。就拿我司来说,360 集团目前已经有 8 个业务线在使用,4 套集群,总数据量接近 190TB,稳定流畅运行。目前 12 月份还接了一个大部门的 80 人 TiDB 内部培训,从我自己来说,我要感谢 TiDB,我分享的同时,也有很多大牛帮助我改正文中的错误,让我自己也有了进一步的提升。


本文转载自: 360 技术(ID:qihoo_tech)

原文链接:DM运维踩坑实践总结


2020-12-05 21:381528

评论

发布
暂无评论
发现更多内容

再获殊荣!AlphaSights荣获猎聘“2022年度非凡雇主”称号

科技热闻

倒计时2天 | 第六届openGauss技术文章征集活动最新初审合格名单(截至8.3)

daydayup

MiniRBT中文小型预训练模型:结合了全词掩码技术和两段式知识蒸馏技术,加快推理速度

汀丶人工智能

人工智能 自然语言处理 nlp 预训练模型 知识蒸馏

行业信创-太极信创研习院第36期ITAIP信创精华班央企专场培训在京成功举办

电子信息发烧客

【我和openGauss的故事】可视化运维平台openGauss Datakit带你轻松玩转openGauss 5.0

daydayup

纵览 PoseiSwap 经济体系,如何从宏大的叙事中持续捕获价值?

西柚子

纵览 PoseiSwap 经济体系,如何从宏大的叙事中持续捕获价值?

BlockChain先知

盘点一对一直播源码的那些小功能

山东布谷网络科技

源码 社交APP 一对一直播

父子线程共用线程池

soap said

【我和openGauss的故事】 openGauss 5.0.0 事务相关语法

daydayup

[腾讯云 Cloud studio 实战训练营] 制作Scrapy Demo爬取起点网月票榜小说数据

ベ布小禅

9. 数据类型 - 列表详解

茶桁

Python

在 Go 语言单元测试中如何解决 Redis 存储依赖问题

江湖十年

后端 单元测试 Go 语言 redis'

MTK 2.9.2 迁移Oracle 11g 至 openGauss 5.0.0操作指南

daydayup

C与C++之间的相互调用及函数区别

芯动大师

纵览 PoseiSwap 经济体系,如何从宏大的叙事中持续捕获价值?

小哈区块

Java 文字转图片输出,Java 输出透明背景图片,Java文字转图片防爬虫

java易二三

Java 程序员 爬虫 计算机 电脑

【我和openGauss的故事】使用Ora2Pg迁移oracle数据到openGauss

daydayup

openGauss数据库源码解析系列文章—安全管理源码解析(五)

daydayup

图数据库使用及业务场景

小小怪下士

Java MySQL 数据库

【我和openGauss的故事】为集群增加VIP

daydayup

程序员如何利用AI加持

Bruce Talk

AI 敏捷开发

HDC 2023 | HarmonyOS应用联运服务,帮助开发者实现全链路经营提效

Geek_2d6073

纵览 PoseiSwap 经济体系,如何从宏大的叙事中持续捕获价值?

股市老人

Gartner 首发中国数据分析与人工智能技术成熟度曲线,TDengine 入选

爱倒腾的程序员

【我和openGauss的故事】带有out参数的存储过程及自定义函数的重载测试

daydayup

纵览 PoseiSwap 经济体系,如何从宏大的叙事中持续捕获价值?

大瞿科技

VLE基于预训练文本和图像编码器的图像-文本多模态理解模型:支持视觉问答、图文匹配、图片分类、常识推理等

汀丶人工智能

人工智能 自然语言处理 多模态大模型 视觉问答 图文匹配

简单好用的ElasticSearch可视化工具:es-client和Head

javalover123

搜索引擎 elasticsearch ELK ES Elastic Search

华为发布数字资产继承功能

HarmonyOS SDK

华为 HarmonyOS HMS Core

DM运维踩坑实践总结_软件工程_360技术_InfoQ精选文章