【精选实践】TiDB 在 360 云平台的落地及实战干货

如何控制或减小大规模迁移时对业务的影响;如何提前规避因磁盘导致的大规模。
对于第一点,我们迁移的时候是有参数可以控制的 。
这里无论是磁盘空间阈值,还是调度速度,或者 drop 大量表后调整空merge 的速度,其实都是可以通过 pd-ctl 的set 命令来实时调节 。
例如:
high-space-ratio 0.7 #设置空间充裕阈值为 0.7 。当节点的空间占用比例小于指定值时,PD 调度时会忽略剩余空间这个指标,主要针对实际数据量进行均衡 。
--limit 8 #最多同时进行 8 个调度 。这个值主要影响的速度,值越大调度得越快,设置为 0 则关闭调度 。调度的开销较大,所以这个值不宜调得太大 。也可以通过减小该值来限制调度对集群产生的影响
merge--limit 12 #最多同时进行 12 个 merge 调度 。设置为 0 则关闭Merge 。Merge 调度的开销较大,所以这个值不宜调得过大 。
--limit 8 #最多同时进行 8 个调度 。这个值主要影响的速度,值越大调度得越快,设置为 0 则关闭调度 。调度的开销较小,需要的时候可以适当调大 。
max-merge--keys 50000 #设置Merge 的上限为 50k 。当大于指定值时 PD 不会将其与相邻的合并 。
max-merge--size 16 #设置Merge 的 size 上限为 16M 。当Size 大于指定值时 PD 不会将其与相邻的合并 。设置为 0 表示不开启Merge 功能 。
TIPS:理解了作用和原理,上述参数都可以根据需求自行控制 。
对于第二点,尤其是使用 DM 期间,将 DM- 和 TiKV 混合部署的情况下,要注意清理全量备份留下的文件和。

【精选实践】TiDB 在 360 云平台的落地及实战干货

文章插图
默认调度策略是当磁盘剩余的有效空间不足 40%,处于中间态时则同时考虑数据量和剩余空间两个因素做加权和当作得分,当得分出现比较大的差异时,就会开始调度 。
所以 DM 导入完成后,要记得删除全量备份 。就是 . 文件夹,这个全量备份一般都会比较大,如果 dm- 和 TiKV 混部,就会出现某个 TiKV 节点磁盘已使用率高于其他,这时 PD 的 storescore 就会相比其他节点出现异常,引起性能抖动和升高 。
【精选实践】TiDB 在 360 云平台的落地及实战干货

文章插图
一直等待其追上后:
【精选实践】TiDB 在 360 云平台的落地及实战干货

文章插图
进入平衡状态:
【精选实践】TiDB 在 360 云平台的落地及实战干货

文章插图
恢复正常水平,如下图 16:54 分时的情况:
【精选实践】TiDB 在 360 云平台的落地及实战干货

文章插图
QPS 也不再积压:
【精选实践】TiDB 在 360 云平台的落地及实战干货

文章插图
关于 relay-log,默认是不清理的,就和 MySQL 的一样,这块可以通过 dm- 的配置文件来进行配置,例如将配置为 7,代表 7 天后删除:
【【精选实践】TiDB 在 360 云平台的落地及实战干货】[purge]interval = 3600expires = 7remain-space = 15
来控制保留天数 。
默认 =0,即没有过期时间,而 -space=15 意思是当磁盘只剩于 15G 的时候开始尝试清理,这种情况我们极少会碰到,因此这个清理方式其实基本上是用不到的 。所以建议有需要删除过期 relay-log 的小伙伴,直接配置保留天数就可以了 。
DM 导入完成后,应该提供是否在完成后自动删除全备文件的选项,可以默认不删,由使用者决定是否删除 。
从使用者角度来说,全量备份目录无论是全量一次性导入还是 all 增量同步,后续都不会再使用到 。如果 dm- 和 TiKV 混部,会导致全备文件占据大量磁盘空间,引起 TiKV评分出现异常,导致性能下降,已转化为 PRM 产品需求 。
关于 DM 使用期间出现数据丢失的问题
在早期还没有 dm- 自动化生成 task 时,我们都是自行编写 DM 的 task 同步文件 。后来有了 dm- 自动化生成工具,只要图形页面点点点就可以了 。
【精选实践】TiDB 在 360 云平台的落地及实战干货

文章插图
但该工具目前有一个问题是,没有全库正则匹配,即便你只勾选一个库,他底层是默认把每张表都给你配置一遍 。这就会出现当上层 MySQL 新创建某张表的时候,下游会被忽略掉,例如当你使用改表工具 gh-ost 或者 pt---,你的临时表都会被当做为不在白名单内而被忽略,这个问题使用者需要注意 。我们也已经反馈给了官方 。未来不久的版本估计就可以修复 。
["skip event"] [task=task_20357] [unit="binlog replication"] [event=query] [statement="ALTER TABLE `360`.`_data_201910_gho` ADD COLUMN `raw_url_md5` CHAR(32) NOT NULL DEFAULT '' COMMENT 'raw_url md5'"]["skip event"] [task=task_20357] [unit="binlog replication"] [event=query] [statement="ALTER TABLE `360`.`_data_201910_gho` ADD INDEX `idx_rawurl_md5`(`raw_url_md5`)"] [schema=flow]["skip event"] [task=task_20357] [unit="binlog replication"] [event=query] [statement="ALTER TABLE `360`.`_data_201910_gho` DROP INDEX `idx_raw_url`"] [schema=flow]
这里日志可以看到 event 被 skip 了 。
关于 DM 使用期间偶发性 1062 主键冲突的问题
query-error task 能看到具体的报错信息,下游看都没有该值:
mysql> select * from client where clientid='82b51e6f6eb64955487f978dd94a2c81e492f6170xxxxxxxxxxxxxxxxxxxxxxxxx';Empty set (0.00 sec)
再去上游看,结果发现也没有值,业务逻辑应该是后来了:
mysql> select * from client where clientid='82b51e6f6eb64955487f978dd94a2c81e492f6170xxxxxxxxxxxxxxxxxxxxxxxxx';Empty set (0.00 sec)
因为上游也没有值,去上游看后分析如下:
是先写入,再删除,所以上游没值是可以预期的,但是下游还没有同步到这块,此时也是没有值的,不应该存在 1062 的问题 。
当集群有大规模 kv:1062 报错时,或者集群写入压力大时,DM 从结果看无法保证的有序落盘,需确认 DM 能不能保证 lvs 下的多个 TiDB的每一个 event 是有序执行的 。只从现象看,只要集群没有大量的 1062 报错,PD 相关的监控值都比较低,DM 也不会出现任何同步报错,反之就出现 。从看就像是第一条了,还没来得及,直接产生的报错,但报错后那个的也完成了,所以这时候我再怎么快也快不到毫秒级,下游看不到所有记录 。解决的办法是将 1062 大量冲突的业务拆分出集群,或 DM 直接写 TiDB 的真实 ip 而不是 lvs 。
DM 同步异常
有业务反馈 drop 分区和 drop 列时出现同步异常 。补充下分区表相关的测试的结果,DM 更多的无法拆分的情况还是在 drop 这块,普通的 add,没问题的:
alter table dsp_group_media_report drop partition p202006 ,p202007 ;
Alter table dsp_group drop column test_column;
40 亿表添加 DDL 添加索引导致的升高
【精选实践】TiDB 在 360 云平台的落地及实战干货

文章插图
定位到是
mysql> show global variables like 'tidb_ddl_reorg_worker_cnt'; +---------------------------+-------+| Variable_name| Value |+---------------------------+-------+| tidb_ddl_reorg_worker_cnt | 16|+---------------------------+-------+1 row in set (0.11 sec)mysql> show global variables like 'tidb_ddl_reorg_batch_size';+---------------------------+-------+| Variable_name| Value |+---------------------------+-------+| tidb_ddl_reorg_batch_size | 1024|+---------------------------+-------+
上述两个参数对已有非 pcie 集群压力比较大导致 。
通过 set调节(3.0.3 后,默认从 256 涨到了 1000 和 16):
tidb_ddl_reorg_batch_size 1000-256tidb_ddl_reorg_worker_cnt 16-4
同时,提高相关:
max-background-jobs: 8-10-12max-sub-compactions: 1-2-4defaultcf.compression-per-level: ["lz4", "lz4", "lz4", "lz4", "lz4", "zstd", "zstd"]writecf.compression-per-level: ["lz4", "lz4", "lz4", "lz4", "lz4", "zstd", "zstd"]
最终的优化结果是,QPS 稳定在 3k 左右:
【精选实践】TiDB 在 360 云平台的落地及实战干货

文章插图
静默开启
在实际情况中,读写请求并不会均匀分布到每个上,而是集中在少数的上 。那么可以尽量减少暂时空闲的的消息数量,这也就是的功能 。无必要时可不进行 raft-base-tick,即不驱动空闲的 Raft 状态机,那么就不会触发这些的 Raft 产生心跳信息,极大地减小了的工作负担 。
截至 TiDB v3.0.5,仍是一个实验功能,在TiKV分支上已经默认开启 。可根据实际情况和需求来开启该功能 。参数如下:
raftstore.hibernate-regions: true
【精选实践】TiDB 在 360 云平台的落地及实战干货

文章插图

【精选实践】TiDB 在 360 云平台的落地及实战干货

文章插图
DM 导入期间升高
在 DM 导入集群期间,确实会因为写热点的问题导致集群整体更高,因为 IO 争用会更明显 。这里其实也是可以通过一些参数来让集群运行的更快的 。
【精选实践】TiDB 在 360 云平台的落地及实战干货

文章插图
如下参数从原值调到-新值:
raftstore:apply-pool-size: 3-4store-pool-size: 3-4storage:scheduler-worker-pool-size: 4-6server:grpc-concurrency: 4-6rocksdb:max-background-jobs: 8-10max-sub-compactions: 1-2
可以看到效果如下:
QPS 不再抖动,也恢复到正常的水平 。
【精选实践】TiDB 在 360 云平台的落地及实战干货

文章插图
DM Debug 相关
DM 还有个注意点就是 dm-.toml 配置文件里的配置 log-level = “debug” 是不生效的,启动的时候默认有个 -L=info 选项,会覆盖掉配置文件里的,默认 -L 优先级高于配置文件,人工排查时自行启动 。也就是说当需要对 dm- 开启 debug 模式,要人工拉起进程并指定 -L 选项 =debug 。
TiDB load data 速度不理想
TiDB 目前 load data 的导入速度不及 MySQL,如果依赖 load data 的话,这块可以调优一下参数 。我们的场景是 TiKV 上没有明显的瓶颈,主要慢在了latch wait,可以调下参数看看:
storage:scheduler-concurrency: 204800000raftstore:raft-max-inflight-msgs: 4096
【精选实践】TiDB 在 360 云平台的落地及实战干货

文章插图
调优完成后是有提升,但提升不大,我们得知新版本的 TiDB 在Load data 这块又有速度提升,比较期待新版本 。
TiDB 列数超限
MySQL 是 1024,TiDB 目前限制是 512 列 。如果你的表有非常多的列,那么这块要提前注意下是不是可以拆分出去 。
【精选实践】TiDB 在 360 云平台的落地及实战干货

文章插图
GC can not work
GC 的数据包括两部分,一部分是 DML 和 DDL,DDL 的 GC 的对象信息包含在mysql. 和 mysql.,分别记录的是待 GC 的对象以及已经 GC 的对象 。mysql. 表里面没有数据不代表 GC 异常 。
官方建议更换规则:
sum(increase(tikv_gcworker_gc_tasks_vec{task="gc"}[1d]))
TiDB or 条件优化
在 TiDB 中,如下查询是不能用到索引的:
select * from manual_domain where host_md5= '55fbea39965484a61xxxxxxxxxx'or domain_md5 = '55fbea39965484a61xxxxxxxxxx';
MySQL 中用到了,TiDB 计划 4.0 支持,可以先用 union all 来处理这种 a or b 。
CPU 消耗过大
业务反馈查询变慢,发现是另外一个业务全表扫into导数据导致的 。
【精选实践】TiDB 在 360 云平台的落地及实战干货

文章插图
去 CPU 占用率高的这台机器上搜索对应的 log,关键字 slow,发现如下情况:
[2019/09/18 10:04:37.339 +08:00] [INFO] [tracker.rs:150] [slow-query] [internal_key_skipped_count=46649] [internal_delete_skipped_count=0] [block_cache_hit_count=1596] [block_read_count=9] [block_read_byte=31933] [scan_first_range="Some(start: 7480000000000002285F72800000000021E9BD end: 7480000000000002285F72800000000024199A)"] [scan_ranges=1] [scan_iter_processed=46650] [scan_iter_ops=46652] [scan_is_desc=false] [tag=select] [table_id=552] [txn_start_ts=411244239493267464] [wait_time=2ms] [total_process_time=1.41s] [peer_id=ipv4:192.168.1.248:45686] [region_id=835437]
根据去通过 . 表查一下,可以通过上述方式来定位到是哪张表导致的问题 。
TiDB enum 导致的性能问题enum 在 TiDB 3.0.2 进行 where 条件查找是,发现不能下推到 TiKV 。官方说4.0GA 修复 。临时办法是修改到其他类型 。enum为发现内容出现变化,原本的’'变成了值,‘1’ 变成了 2,经测试正常,因此不要尝试去变更 DM 备份出来的文件来实现表结构变更,应该从上游 MySQL 解决 。分区表元数据无法获取
没有视图可以查询当前已建分区信息 。在 TiDB 中目前没有视图支持查询分区表已建分区信息,那么用户那边没有办法直观的判断当前已建的分区,以及当前是否需要及时的添加新分区 。目前已转化为 PRM 产品需求,相信新版本不旧会实现 。
分区表 - 部分分区 - limit 未下推
分区表出现 limit 未下推的现象,表其中只有分区有数据 。该问题已在 3.0.6 版本修复 。
mysql.tidb 表权限异常
使用 use或者 mysql 客户端指定 DB name 后,可以对该表进行查询或更新操作 。计划 3.1 版本修复 。
事物的限制
单个事物的 SQL statement 不超过 5000(stmt-count-limit 参数可调);每个键值对不超过 6M;键值对的总数不超过 300000;键值对的总大小不超过 100M;
注:键值对是指一张表里有 2 个索引,那么一共就是数值 +2 个索引,总共 3 个键值对,那么每个键值对的总是不能超过 30万/3 = 10万 。
一行数据会映射为一个 KV entry,每多一个索引,也会增加一个 KV entry,所以这个限制反映在 SQL 层面是:总的行数 *(1 + 索引个数) < 30w 。
官方提供内部 batch 的方法,来绕过大事务的限制,分别由三个参数来控制:
tidb_batch_inserttidb_batch_deletetidb_dml_batch_size
写热点的处理
如果可以去掉 MySQL 自增主键,就可以通过建表时指定 、 来实现预切分,避免单调自增引发的只往某个 KV 上写数据引起的热点问题 。详情可参考官网TiDB 专用系统变量和语法中的介绍 。
TiDB 监控和 DM 监控部署数据冲突
这块可以通过将 TiDB 和 DM 监控部署到不同的机器上来绕过解决,否则就会出现通过安装后,- or.yml --tags= 时,两者只有一个是正常的 。
磁盘已使用不建议超过 50%
数据量太多 LSM 过大,成本会很高,并且内存命中率下降,同时单机恢复时间很长,50% 左右最好,使用率太高,如果突然写入爆增,来不及调度会写满磁盘,有风险 。因此建议 SSD 不要使用超过 2T 的,采用更多的机器会有更好的性能 。
导致的内存和网卡打满
在使用备份大时,会打满 TiDB 网卡,同时会消耗 TiDB、TiKV 更多的内存 。
【TiDB ERR】[emergency]TiDB_schema_error:192.168.1.1:10080,[add_dba_mysql]【360】【TiDB ERR】[critical]NODE_memory_used_more_than_80%:192.168.1.2:9100,[add_dba_mysql]【360】
去抓取慢日志会看到如下内容:
grep Query_time tidb_slow_query-2019-12-24T04-53-14.111.log|awk -F : '$2>10'# Time: 2019-12-24T03:18:49.685904971+08:00# Txn_start_ts: 413433784152621060# User: backup@192.168.1.3# Conn_ID: 4803611# Query_time: 4002.295099802SELECT /*!40001 SQL_NO_CACHE */ * FROM `360`.`t_d` ;
期待后续的版本物理备份,逻辑备份看起来目前是可以备份,但会比较消耗资源,同时恢复时间也会更久 。
展望
从 TiDB 2.x 开始我们就已经开始进行测试了,最终选择的版本是 3.0.2,后续升级到 3.0.5 。上述文章总结和一些案例希望能够帮助到已使用或打算使用 TiDB 的朋友 。
360 云平台 DBA 团队也计划将 TiDB 推上 360 HULK 云平台,为 360 集团更多的业务线提供丰富多彩和稳定可靠的数据库服务 。在这里首先要感谢同学及时的技术支持,帮助我们尽快的解决了一些技术问题 。同时,我自己也通读完了 TiDB 的官方手册 。从部署、二进制部署、升级、DM、、Pump、、调优、排障、迁移、备份,这一路打怪下来,切身感受到了 TiDB 越来越好的过程 。
我相信未来随着 3.1 和 4.0 版本的推出,有更多人加入使用 TiDB 的这个队伍中来 。从业务给我们的反馈也是对 TiDB 的使用情况表示满意,我们相信,TiDB 会在大家共同的努力下,越来越好 。