TiDB 在 2021 易车 818 汽车狂欢节的应用
【是否原创】是
【首发渠道】TiDB 社区
作者:陈青松 易车资深研发工程师
彭召静 易车 DBA
1. 背景介绍
易车公司成立于 2000 年,于 2010 年在美国纽交所挂牌上市。 并于 2020 年 11 月完成私有化,成为腾讯大家庭一员。 作为中国汽车互联网平台企业,易车公司为中国汽车用户提供专业、丰富的互联网资讯服务,并为汽车厂商和汽车经销商提供卓有成效的互联网营销解决方案。《超级 818 汽车狂欢夜》是浙江卫视联合易车 App 推出的汽车主题超级“晚”,由浙江卫视节目中心超级晚工作室制作。晚会把汽车的速度与激情,与科技创新、时尚潮流融合,配合台网跨屏互动体验,呈现一场展现汽车工业魅力的大秀。
2. 业务场景介绍
易车 818 狂欢节,tidb 应用场景比较多,818 汽车狂欢数据看板是 tidb 主要的应用业务之一,看板实时展示 818 购车节的专题、活动、流量、线索、互动等数据表现。其中摇一摇(红包,半价车,易车币)和主会场分会场直播节目投票是用户参与度最高,数据流量最大的环节。在整个活动中,不仅要求数据库能够存储海量的数据,同时能够应对高并发,低延迟场景,不仅作为数据的存储介质,还会作为实时计算的数据源头,配合流量数据,实现秒级数据实时播报。数据库和 flink 是整个系统中非常重要的两个组件,flink 的数据来源包括数据库和业务流量数据,所以数据库不仅要满足数据秒级实时推送,还要支持 flink 高并发的读(维表)写(结果表)请求,经过严格的压测及各种线上场景的模拟,最终选择了 tidb 作为大屏展示核心业务的数据库。
3. 数据库选型
818 活动期间,我们对数据库提出的要求是:
需要具备海量数据存储的能力
提供高并发,低延迟的读写能力
服务稳定,易扩展
最初,MYSQL 仍然是数据库的首选方案,为了应对流量暴涨及可能遇到的突发情况,我们进行了多次模拟压测。压测过程中,为了保证计算结果的实时性,实时任务会频繁的对数据库进行大批量的数据写入,MYSQL 主从延迟升高,极端情况下引起 MYSQL 主从切换,切换时间过长,导致数据库出现短暂不可用状态。同时实时任务会持续写入大量数据,引起磁盘爆满。TIDB 最初作为备选方案,在多次压测之后,我们考虑采用 TIDB 作为主方案,在 PingCAP 技术同学的帮助下,对现有版本进行了升级,排查和优化 TIDB 在使用过程中的问题,经过多次压测后,TIDB 能够完全满足在各个场景下的需求。
红包摇一摇业务方采用 MYSQL 作为主要方案,在压测过程中,MYSQL 基本满足需求,为了避免由于业务流量暴涨引起 MYSQL 不可用的情况,业务方选用 TIDB 作为容灾方案,TIDB 通过 DM 将数据实时同步到 TIDB 中,当 MYSQL 不可用时,业务方直接将数据库切换为 TIDB。
4.tidb 架构
818 汽车狂欢数据看板业务:
在整个业务中,实时计算的数据源包括 MYSQL、TIDB、SQLSERVER 和流量日志。为了保证实时计算的稳定,大数据相关组件都有主备两个方案。
TIDB 作为其中的关键组件,我们也准备了两个集群,和实时计算的主备方案一一对应,业务研发通过双写的方式把数据同时写入两个集群,一部分业务的查询连接集群 1,另一部分业务的查询连接集群 2,当其中一个集群出现问题,应用端切换到另外一个集群。两个 TiDB 集群都是部署 3 个 TiDB server 用 consul 做负载均衡对外提供服务,3 个 pd server,存储节点有 2 块数据盘所以采用单机双节点部署 TiKV,2 个 Tiflash 节点,另个我们还准备了 4 台机器做扩容以免数据量暴涨集群支撑不了。TiDB 版本选择 v4.0.14,架构图如下:
红包摇一摇业务:
TIDB 在整个业务中需要作为数据源、实时计算维表和实时计算结果存储引擎三个角色。TIDB 通过 TICDC 将数据实时推送到 KAFKA 中,为了保证 TICDC 稳定高效,我们为 TIDB 中的每个库创建了一个 TICDC 任务,将数据实时推送到指定 KAFKA 中,然后 FLINK 负责将同一个 TOPIC 中的属于不同库表的数据进行解析,分流到库表对应的 TOPIC 中,提供给实时计算业务使用。实时计算任务消费 KAFKA 中的 TIDB 数据进行业务逻辑计算,同时还需要从 TIDB 中查询对应的维度数据,最终将计算结果再输出到 TIDB 中。具体架构图如下:
5. 遇到的问题及解决方案
1)4.0.12 版本 bug
前期测试期间,最初 tidb 的版本采用的是 v4.0.12,总是收到 increase(tidb_server_panic_total[10m]) > 0 的警告,通过查看 tidb server 的日志发现有大量的 analyze worker panic 的错误日志,具体信息如下:
[
2021
/
08
/
11
17
:
29
:
03.989
+
08
:
00
] [ERROR] [update.go:
796
] [
"[stats] auto analyze failed"
] [sql
=
"analyze table %n.%n"
] [cost_time
=
4.247917467s
] [error
=
"analyze worker panic"
]
[
2021
/
08
/
11
17
:
29
:
07.872
+
08
:
00
] [ERROR] [analyze.go:
172
] [
"analyze worker panicked"
] [stack
=
"goroutine
20458702777
[running]:\"ngithub.com
/
pingcap
/
tidb
/
executor.
经过官方小伙伴的确认,此报错为 v4.0.12 的 bug #20874,当集群配置了 new_collations_enabled_on_first_bootstrap: True 新的排序规则后此 bug 会出现。
解决方案:升级版本,跟研发同学确认升级时间后,将 tidb 集群版本升级到 v4.0.14,解决此问题,
2)执行计划变化
818 晚会期间集群慢日志中出了一个慢 sql,如下:
SELECT id, report_dt, user_id, avatarpath, interact_type, reward_type_id, show_name, reward_name, city_name, winning_create_time, winning_time_str, create_time, update_time, version
FROM table_name
WHERE report_dt = ‘’ AND reward_type_id = ‘’ ORDER BY winning_create_time DESC LIMIT 1;
执行时长:
通过查看执行计划发现活动最开始的一小时此查询走的是单字段 winning_create_timep 索引的 IndexFullScan,随着活动期间数据量越来越多,执行计划变为 TableScan,定位问题流程如下:
通过查看执行计划各环节的耗时发现 SQL 的等待耗时主要集中在 TiKV 侧的 coprocessor,并且 SQL 扫描了大量的 Key,从 21 点开始该 SQL 扫描的 Key 数量是之前的 2 倍,跟业务研发确认此表插入量比较大。通过查看 TiDB 侧监控发现 TiKV 侧 Coprocessor 相关指标耗时高;再接着查 TiKV 侧的 Unified read pool CPU、Coprocessor Detail→Wait duration、Coprocessor Handle duration 的监控发现个别 TiKV 资源利用率高,怀疑有读热点;通过查看 TiDB DashBoard 流量可视化流量部分可以看到明显的读热点现象,PD 监控的 hot read 显示每个 TiKV 交替出现读热点:
解决方案:
a. 使用 Load Base Split 打散读热点
b. 添加联合索引
3)TiCDC 遇到的问题及需要注意的点
a. 报错 1:Error: [CDC:ErrKafkaNewSaramaProducer]dial tcp 64.70.19.203:9092: i/o timeout,是由于 TiCDC 的命令行中 kafka 的地址只写了一个,TiCDC 找不到 kafka 的地址,解决办法:把 kafka 集群的 3 个 ip 都添加到命令行后此问题解决
b. 业务研发要求 kafka 接入的数据必须是 canal 格式,否则不能正常使用,这里需要在命令行设置 protocol=canal-json,并且配置文件中配置 enable-old-value=true
c. 报错 2:CDC:ErrKafkaAsyncSendMessage]kafka: Failed to produce message to topic bigdata_test: kafka server: Message was too large, server rejected it to avoid allocation error. 此报错是因为 kafka 接收的单次数据过大不能写入的,解决办法: 修改发送消息的最大数据量为 1M,max-message-bytes=1048576
d. 研发反馈数据只能分发到一个 kafka 分区,解决方案:以 rowid 做 hash 计算做并行分发,问题解决
主要配置文件及 ticdc 同步命令如下:
# test.conf ticdc配置文件
enable
-
old
-
value
=
true
[
filter
]
rules
=
[
'bigdata_test.*'
]
[sink]
dispatchers
=
[
{matcher
=
[
'bigdata_test.*'
,], dispatcher
=
"rowid"
},
]
同步命令:
tiup ctl:v4.
0.14
cdc changefeed create
-
-
pd
=
http:
/
/
10.20
.
20.20
:
2379
-
-
sink
-
uri
=
"kafka://10.10.10.1:9092,10.10.10.2:9092,10.10.10.3:9092/bigdatatest?kafka-version=2.6.1&partition-num=3&max-message-bytes=1048576&replication-factor=1&protocol=canal-json"
-
-
changefeed
-
id
=
"bigdata_test"
-
-
config
=
/
home
/
tidb
/
cdc_conf
/
test.conf
6. 性能表现
TiDB 集群运行稳定
818 汽车狂欢数据看板业务 SQL 999 在 8ms 以内,SQL 99 在 3ms 左右,qps 达到 62k
2) 红包摇一摇灾备业务:TiCDC 在前期压测期间,单表数据向下游 kafka 分发会有同步延迟情况,多表数据同步向下游 kafka 分发延迟可以忽略不计。818 晚会期间为多表分发,未出现延迟。
7. 改进计划与建议
818 过后,易车要实行去 sqlserver 计划,其中会有部分数据量较大业务将由 sqlserver 迁移到 TiDB,比如新闻、粉丝、IM 等,有了前期的经验对于后续业务的使用也提供了一些改进计划:
a. 表的自增主键 AUTO_INCREMENT 修改为 AUTO_RANDOM 随机主键,AUTO_RANDOM(n) n 的值设置越大则打散的程度越大,默认值为 5。此属性可以避免写入热点。
b. 主键索引最好使用聚簇索引,聚簇索引与非聚簇索引在存储上的区别为:
聚簇索引:
非聚簇索引:
tidb rowid(键) – 行数据 (值)
聚簇索引的性能和吞吐量都有较大优势,插入数据或根据主键查询数据时会减少一次或多次网络连接。
c.JDBC 连接器要使用较新版本,否则程序端会报 Coult not retrieve transaction read-only status from server 的问题。JDBC 连接时需要设置 userConfigs=maxPerformance 来避免额外开销。
d. 建议官方在 TiCDC 单表数据向下游同步的延迟问题方面做进一步改进。
8. 感谢
非常感谢高振娇、王晓阳、苏丹、东玫等 PingCAP 小伙伴多次到场支持,提出了很多切实可用的调优建议,帮助解决了前期测试当中遇到的问题和 Bug,并于 818 当天晚会期间现场支持,在此表示最衷心的感谢。
版权声明: 本文为 InfoQ 作者【TiDB 社区干货传送门】的原创文章。
原文链接:【http://xie.infoq.cn/article/e2c035cf82e5f166649024abd】。文章转载请联系作者。
评论