伴鱼TiDB升级到3.0

TiDB3.0版本特性

随着数据的增加对单机DB挑战越来越大,NEWSQL数据库应运而生。TiDB1.0GA版本在2017年10月发布,后面几乎以每半年一次大版本发布速度进行产品的优化迭代。2019年6月进入了3.0时代,在本次升级中我们选择了3.0.13最新的GA版本,官方压测与 2.1 相比,TPC-C 性能提升约 4.5 倍,Sysbench 性能提升约 1.5 倍。升级后在使用过程中明显感受到了在大数据量集群下有明显的改进,使用中数据灌入速度有4倍左右的提升。3.0在稳定性方面有较大的提升。集群支持 150+ 存储节点,300+ TB 存储容量长期稳定运行,升级后对大数据量的存储打下了基础,我们单集群的数据量还未达到几十TB或上百TB的规模。优化 Raft 副本之间的心跳机制,按照 Region 的活跃程度调整心跳频率,减小冷数据对集群的负担。优化 PD 调度流程。新增 Fast Analyze 功能,提升收集统计信息的速度,降低集群资源的消耗及对业务的影响。其他特性还包括:SQL优化器的提升、支持窗口函数,悲观事务(从2.1升级后的版本依然是乐观事务,新部署的集群3.0.8以后支持悲观事务)、视图、分区表、SQL Trace等新特性。其中企业级的支持审计日志,白名单访问。

决定升级

正如DBA对数据库稳定运行的保障工作一样,TiDB进入3.0版本,官方还是在系统稳定性、易用性、功能、优化器、统计信息以及执行引擎做着持久的优化改进,稳定性和读写性能有非常大的提升。

基于对2.1使用过程中遇到的问题,例如:瞬间插入性能差,偶尔爆出insert的慢SQL、select查询不能准确的使用合适的索引、数据量较大的集群Raftstore单线程压力的问题,长时间考虑官方对2.1版本的优化和问题支持的滞后、以及公司业务的发展导致数据量的持续增加。我们带着对3.0版本新功能和性能提升期待,开始了对tidb集群进行3.0大版本的升级之路。

操作升级选择在业务低峰期,时间一般是在业务的低峰期凌晨以后来实施,这是很好的时间窗口。可以对现有集群做一些优化的调整(原因是会涉及到集群重启,比如:PD机器的扩容,调整)。为了实现TiDB部署机器的标准化,后期运维方便。需要对现有集群所使用的硬件资源进行评估,更换,迁移等操作。最终达到各组件机器硬件配置标准化、配置参数标准化、监控及部署结构标准化。 为以后对TiDB指标告警打下基础。

升级准备工作

经过一段时间的调研和参数对比,参考官方升级说明并结合部署结构的实际情况。制定了升级方案,机器调整方案(包括机器的扩容、下线)重启流程,回滚方案。

1、 从2.1.15升级到3.0.13版本跨度较大,是否存在复杂场景sql查询不一致的问题,目前已知的问题是where条件后存在小括号时,索引使用不准确的问题。
2、 不支持在升级后回退至2.1或更旧的版本。
3、 在升级的过程中不能执行 DDL,否则可能会出现行为未定义的问题。正是这个限制在升级过程中第一台是遇到DDL OWNER机器,导致一个集群升级失败。通过与官方支持沟通最终解决了问题。也为顺利完成其他集群的升级总结了经验。
4、 确认并对比每个集群TiDB、TiKV、PD、Grafana、Prometheus 等组件的组参数的变化,老版本集群配置项不一致,包含日志路径,新增配置,或已有参数的默认值改变等。避免出现因配置不同导致出现问题。

升级过程

对每个需要升级的集群,需要编辑并配置文件包括inventory.ini、tidb.yml、pd.yml、tikv.yml。通过滚动升级的方式对集群中各个机器的组件进行升级。滚动升级的顺序是:PD->TiKV->PUMP->TiDB

⚠️注意:此处有2个过程会导致连接出现闪断:

A) 滚动升级PD Leader时,PD重新选举Leader导致所有连接无法操作数据库
B) 滚动升级TiDB过程中,重启TiDB-Server过程中会断开服务的连接

由于每个集群部署时期跨度大使用机器的硬件配置有差异,本次升级过程中对10个集群的机器配置实现了标准化。总调整机器数40台左右。
Tidb_server、PD_server、tikv_server、pump机器在升级过程前后集群的扩容与缩容,退回高配阿里云机器,节省了成本同时也提高了集群的负载能力。

由于在升级的过程中,应避免执行DDL操作,所以在inventory.ini配置文件里[tidb_servers]项,第一个配置避开DDL OWNER机器

上图:查询DDL OWNER机器

上图:升级过程3.0新的系统表的DDL操作

上图:查看执行的DDL语句

在滚动升级TiKV过程中,需要调整代码延长Transfer leader时间,来减少滚动 TiKV 过程的性能抖动,如果提前 transfer leader 完成以后,会停止 check。继续下面的工作。下面是调整方法

vim tidb-ansible-v3.0.13/common_tasks/add_evict_leader_scheduler.yml
– name: check tikv’s leader count
uri:
url: “http://{{ pd_addr }}/pd/api/v1/store/{{ store_id }}”
method: GET
return_content: yes
body_format: json
status_code: 200
register: store_info
until: (store_info.json.status.leader_count is defined and store_info.json.status.leader_count|int < 1) or store_info.json.status.leader_count is not defined
retries: 18 ##我们把18调整到了80
delay: 10
failed_when: false
when: not enable_tls|default(false)


上图:升级过程中tikv transfer leader的过程

带来的收益:

1、 版本升级后,读写性能的提升,监控项Duration观察,在大数据量的情况下,999线从4秒提高到200多毫秒,对业务SQL的查询性能有较高的提升。同时单纯从大数据集群恢复备份对比,数据灌入的速度有4倍左右提升
2、 所有集群升级后自动开启了数据的merge功能,减少了空region给TiDB带来的通讯压力和释放了磁盘空间。反过来看这个问题DB长期资源不回收,在数据量达到一定量级时,会是一个非常棘手的问题。不但总的机器使用数量会升高,集群内部机器消耗和稳定性也会有一定的影响
3、 统一了各组件部署机器的配置,隔离了不合理混部带来的风险,tikv机器全部迁移到物理机器上,提高了集群的抗压能力,能应对较大的突发流量。
4、 单次事务操作的数据量从5千提升到了30万,核心集群的DML操作依然要谨慎操作,避免大事务导致的锁和性能飙升,影响到生产业务

由于大数据集群上游同步了4个生产集群,集群本身计算任务产生的临时表,特殊的使用场景,每天删除部分表的数据或删除整个表,再计算产生新的表或数据插入tidb。在2.1版本没有开启merge的情况下,遗留下大量的未回收的region。(在2.1版本即使开启merge,对region的合并依然不完全),升级后还会有大量的region合并,下图体现了region数减少的过程


上图:region merge过程中空region在减少

上图:tidb集群总的region number在减少

⚠️注意:如果集群数据量较大且使用过程有较多的表和数据的删除动作,堆积了比较多的需要merge的region。为了避免升级后开启Region Merge对cpu的消耗较大,可以通过pd-ctl调整merge-schedule-limit参数
./pd-ctl -u http://{pd-ip}:{pd_client_port}
» config set merge-schedule-limit 2
Success!

5、多线程 Raftstore 在多个线程处理不同 Region 的 Raft 逻辑,多线程 Apply Pool – 在多个线程执行不同 Region 已经提交了的命令。Raftstore 线程池是 TiKV 最为复杂的一个线程池, store-pool-size在2.1版本默认参数为1。升级后默认配置为2,Raftstore cpu监控指标则从最大值100%提高到200%,该参数tikv配置文件里可以手动调整,但并不是越大越好。核心生产集群应控制在120%以下
Use how many threads to handle raft messages
store-pool-size: 2

TiDB升级到3.0以后比较直观的变化:

1、现有的监控界面图改进,新增了监控项,比如:Region Health
空region个数的统计和准确程度,提高了Leader Balance,Region Balance准确度

2、由于每个TiDB集群独立使用一个prometheus导致采集的监控数据不集中,不好实施监控告警的配置,我们在升级后采用prometheus联邦功能将每个集群的监控数据收集到一个prometheus集群里,完成告警的统一配置。

3、整个TiDB集群机器数量越多,采集的监控数据量会越来越多。Prometheus数据刷盘的数据和频率会增加。导致磁盘IO瞬时的飙升,可以考虑调整数据落盘的频率

4、慢日志格式统一,新增Plan项Plan:表示语句的执行计划,使用 select tidb_decode_plan('xxx…') SQL 语句可以解析出具体的执行计划。

最新版的慢查询事例如下:
Time: 2020-06-15T19:44:20.738011501+08:00
Txn_start_ts: 417391302532137136
User: product@10.100.100.134
Conn_ID: 4560686
Query_time: 0.250088873
Parse_time: 0.000021011
Compile_time: 0.000154348
Process_time: 0.266 Wait_time: 0.002 Request_count: 12 Total_keys: 35927 Process_keys: 34921
DB: growthsystem
Index_names: [growthsystem_rank_day:idx_dt]
Is_internal: false
Digest: aa618de9f9cba86d3ccb6a8d41bdf94ecb0a139b17692ebef4ac0d6ab9c8b5d9
Stats: growthsystem_rank_day:417391301273846080
Num_cop_tasks: 12
Cop_proc_avg: 0.022166666 Cop_proc_p90: 0.065 Cop_proc_max: 0.115 Cop_proc_addr: 10.106.9.13:20160
Cop_wait_avg: 0.000166666 Cop_wait_p90: 0.001 Cop_wait_max: 0.001 Cop_wait_addr: 10.106.9.13:20160
Mem_max: 2298044
Prepared: false
Has_more_results: false
Succ: true
Plan: tidb_decode_plan('8AGYMAkzMV8xMAkwCTIzNzU4Ljc2MzM0MTgyMDQyNAkKMQkxM184CTEJSh0A8El0YWJsZTpncm93dGhzeXN0ZW1fcmFua19kYXksIGluZGV4OmRhdGUsIHRvdGFsLCB1dCwgcmFuZ2U6WzE1OTIxNTA0MDAgMTAwLDYPAEhdLCBrZWVwIG9yZGVyOmZhbHNlAYgUMF85CTEJvogAQkoA')
Plan_digest: 3c2d2aee62687159f33c71ad0eb6dd83c339c474b63cc39fae91630914abb30a
SELECT * FROM growthsystem_rank_day WHERE date=1592150400 AND total=100;

优化了慢查询日志的查询方法,通过内存表 INFORMATION_SCHEMA.SLOW_QUERY,ADMIN SHOW SLOW 语句查询慢查询,原来的方式都是通过慢日志文件查看,升级后可以在表里查询。查询事例如下:

select * from INFORMATION_SCHEMA.SLOW_QUERY limit 1\G
*************************** 1. row ***************************
Time: 2020-05-20 00:07:01.418867
Txn_start_ts: 416783904547012615
User:
Host:
Conn_ID: 0
Query_time: 0.279259531
Parse_time: 0.000052662
Compile_time: 0.000111603
Prewrite_time: 0
Wait_prewrite_binlog_time: 0
Commit_time: 0
Get_commit_ts_time: 0
Commit_backoff_time: 0
Backoff_types:
Resolve_lock_time: 0
Local_latch_wait_time: 0
Write_keys: 0
Write_size: 0
Prewrite_region: 0
Txn_retry: 0
Process_time: 0.236
Wait_time: 0.001
Backoff_time: 0
LockKeys_time: 0
Request_count: 14
Total_keys: 101019
Process_keys: 91607
DB:
Index_names: [stats_buckets:tbl]
Is_internal: 1
Digest: 1b3fae494a405ffc5252cd18390a98d751473ad35dfa6acc7220713c90532bf0
Stats: stats_buckets:pseudo
Cop_proc_avg: 0.016857142
Cop_proc_p90: 0.05
Cop_proc_max: 0.075
Cop_proc_addr: 10.111.203.238:20160
Cop_wait_avg: 0.000071428
Cop_wait_p90: 0
Cop_wait_max: 0.001
Cop_wait_addr: 10.111.203.238:20160
Mem_max: 47997076
Succ: 1
Plan: Projection_5 root 10000 mysql.stats_buckets.table_id, mysql.stats_buckets.is_index, mysql.stats_buckets.hist_id, mysql.stats_buckets.count, mysql.stats_buckets.repeats, mysql.stats_buckets.lower_bound, mysql.stats_buckets.upper_bound
└─Projection_13 root 10000 mysql.stats_buckets.table_id, mysql.stats_buckets.is_index, mysql.stats_buckets.hist_id, mysql.stats_buckets.bucket_id, mysql.stats_buckets.count, mysql.stats_buckets.repeats, mysql.stats_buckets.upper_bound, mysql.stats_buckets.lower_bound
└─IndexLookUp_12 root 10000
├─IndexScan_10 cop 10000 table:stats_buckets, index:table_id, is_index, hist_id, bucket_id, range:[NULL,+inf], keep order:true, stats:pseudo
└─TableScan_11 cop 10000 table:stats_buckets, keep order:false, stats:pseudo
Plan_digest: 54bbce67d7e4f533792032e077071a56595a385a0aad02029f230125064bd9d3
Prev_stmt:
Query: select HIGH_PRIORITY table_id, is_index, hist_id, count, repeats, lower_bound, upper_bound from mysql.stats_buckets order by table_id, is_index, hist_id, bucket_id;

已只问题及挑战

1、 集群升级后,事务依然保持乐观事物
2、 3.0的SQL优化器依然存在使用错误索引的情况,必要情况下还需要使用hint
3、 3.0版本还不支持官方提到的BR物理备份,短期内还需要沿用现有的备份方式
4、 部署方式的改变,ansible到tiup部署方式的转换,3.0升级4.0可以使用tiup
5、 保证DB的稳定运行是长期且最重要的工作。期间包含很多的风险的发现和故障处理预案,突发事件的处理。