黄东旭解析 TiDB 的核心优势
447
2024-03-17
线上tidb集群都是2.1.[5,7,8,17],因版本太低,面临诸多问题,比如管理难度大,热点问题,执行计划失效,性能瓶颈,其他已知/未知且无法解决的问题,现在需要升级至4.0.13版本。在调研后发现,如果原地升级将需要多次升级【2.1--> 3.0 --> 4.0】,担心原地升级遇到不可逆的故障,更担心的是解决不掉而影响业务,所以经过测试和评估,最终采用数据迁移的方式进行升级。
因为使用2.1版本的用户本身比较少,更别提升级了,所以可参考的迁移升级文档几乎没有,在升级中遇到了很多问题,也踩了很多坑,本文整理了升级操作流程,并标记每个步骤容易遇到什么问题及解决方案,权当经验交流,避坑指南。本文所有内容/操作命令仅供参考。
因5.0基于MySQL 8.0协议,担心和业务不兼容,也因为5.0+的小版本都还比较小,担心稳定性,所以就不考虑了,当时4.0.13是4.0最新的版本,就选了这个版本。
已经有24套tidb集群完成了从2.1到4.0.13的升级。
已有的组件
角色数量端口pd35017tidb34000tikv320117alertmanager19093prometheus19100grafana13000vip192.168.1.1004000dnsold.tdb.com4000未列举的组件表示未启用该组件,因历史原因,集群并没有启用pump组件。
端口规划也没什么规律
预计增加的组件
角色数量端口pump323001drainer1240012、旧集群访问信息dnsold.tdb.comvip192.168.1.100:4000rs : 192.168.1.1:4000192.168.1.2:4000192.168.1.3:40003、新集群环境介绍角色数量端口pd313002tidb315002tikv317002ticdc333002alertmanager121002prometheus119002grafana120002vip192.168.1.10015002dnsnew.tdb.com15002端口采用2+3的格式,前两位是组件编号,后三位表示集群编号。即后三位一样的表示同一个集群,前两位一样表示同一个组件。
4、新集群访问信息dnsnew.tdb.comvip192.168.1.100:15002rs : 192.168.1.1:15002192.168.1.2:15002192.168.1.3:150021、dba 打印当前连接tidb的ip列表让主业务方确认是否存在非本业务的ip。确保所有使用该集群的业务都参与进来。
2、dba 跟业务确认是否有重连机制。(开启binlog需要重启tidb组件)。
3、dba 开启binlog,这步需要滚动重启tidb组件,需要跟业务协商一个时间窗口。
4、dba 部署4.0环境并导入全量数据。
5、dba 同步增量数据。
6、dba 校验新旧集群数据一致性。
7、dba 交付新环境,提供新的域名 + 端口。
8、dba 提供只读账户,业务测试,验证业务场景(仅限读,不能写)。
9、dba 同步权限。
10、切换流量。
登录所有tidb节点,每个节点的输出结果追加到一个文件,然后排序去重进行统计客户端ip
2、确认是否有重连机制略
3、开启binlog并全量备份这步操作在ansible管理机执行
(1)编辑配置文件
ansible # vim /path/github/tidb-ansible-2.1.8/inventory.ini添加pump组件的监控
[monitored_servers] monitor-pump1 ansible_host=xxxx deploy_dir=/path/tidb-data/pump-23001 monitor-pump2 ansible_host=xxxx deploy_dir=/path/tidb-data/pump-23001 monitor-pump3 ansible_host=xxxx deploy_dir=/path/tidb-data/pump-23001添加pump组件
[pump_servers] #下面三个是pump组件的机器, 如果启用pump组件还需要打开 enable_binlog = True pump1 ansible_host=xxxx deploy_dir=/path/tidb-data/pump-23001 pump2 ansible_host=xxxx deploy_dir=/path/tidb-data/pump-23001 pump3 ansible_host=xxxx deploy_dir=/path/tidb-data/pump-23001pump端口设置及启用binlog参数
## Global variables [all:vars] pump_port = 23001 ## binlog trigger enable_binlog = True #enable_binlog = False如果不设置enable_binlog = True,在部署pump的时候会被忽略。另外需要注意,在pump能提供服务前,不能重新加载tidb的配置并重启,否则会导致业务写操作失败。
(2)编辑pump的配置
ansible # vim /path/github/tidb-ansible-2.1.8/conf/pump.yml修改binlog保存周期
global: # a integer value to control expiry date of the binlog data, indicates for how long (in days) the binlog data would be stored. # must bigger than 0 gc: 14改成14天,避免全量数据导入时间过长导致增量数据丢失(binlog被清理)。
(3)登录目标机器创建目录
登录各个pump节点创建目录及更改权限
ansible # ssh pump1 pump1 # mkdir -p /path/tidb-data/pump-23001 pump1 # chown -R tidb. /path/tidb-data/pump-23001ansible # ssh pump2 pump2 # mkdir -p /path/tidb-data/pump-23001 pump2 # chown -R tidb. /path/tidb-data/pump-23001ansible # ssh pump3 pump3 # mkdir -p /path/tidb-data/pump-23001 pump3 # chown -R tidb. /path/tidb-data/pump-23001(4)在ansible管理机部署pump及监控
ansible # ansible-playbook deploy.yml -l monitor-pump1,monitor-pump2,monitor-pump3,pump1,pump2,pump3 -i inventory.ini(5)在ansible管理机启动pump及监控
ansible # ansible-playbook start.yml -l monitor-pump1,monitor-pump2,monitor-pump3,pump1,pump2,pump3 -i inventory.ini(6)登录tidb查看pump是否部署完成
ansible # /opt/soft/mysql57/bin/mysql -u root -h old.tdb.com -P 4000 -ppassword mysql> show pump status; +------------+------------+--------+--------------------+---------------------+ | NodeID | Address | State | Max_Commit_Ts | Update_Time | +------------+------------+--------+--------------------+---------------------+ | xxxx:23001 | xxxx:23001 | online | 427138948355850245 | 2021-08-20 04:42:57 | | xxxx:23001 | xxxx:23001 | online | 427138948395171844 | 2021-08-20 04:42:57 | | xxxx:23001 | xxxx:23001 | online | 427138948408279045 | 2021-08-20 04:42:57 | +------------+------------+--------+--------------------+---------------------+ 3 rows in set (0.00 sec) mysql>需要注意,2.1.6之前的版本不支持这个查询操作,需要通过binlogctl 进行查看pump的状态,如下示例。
ansible # /path/binlogctl -pd-urls=http://pd_host:pd_port -cmd pumps INFO[0000] pump: {NodeID: xxxx:23001, Addr: xxxx:23001, State: online, MaxCommitTS: 432180280017551379, UpdateTime: 2021-08-20 04:45:57 +0800 CST} INFO[0000] pump: {NodeID: xxxx:23001, Addr: xxxx:23001, State: online, MaxCommitTS: 432180280004444167, UpdateTime: 2022-03-30 18:45:14 +0800 CST} INFO[0000] pump: {NodeID: xxxx:23001, Addr: xxxx:23001, State: online, MaxCommitTS: 432180280017551372, UpdateTime: 2022-03-30 18:45:14 +0800 CST}(7)在ansible管理机滚动重启tidb节点
<font color=red></font>
ansible # ansible-playbook rolling_update.yml -t tidb -i inventory.ini需要注意的是,这个操作可能会出现ansible启动或者关闭动作失败(一直卡着直到超时),如果碰到这种情况,可以登录到目标机器手动进行启动或者停止。参考命令如下:
启动 cd /path/tidb/scripts && sudo -u tidb bash start_tidb.sh
停止 cd /path/tidb/scripts && sudo -u tidb bash stop_tidb.sh
(8)登录tidb检查binlog是否已经开启
ansible # /opt/soft/mysql57/bin/mysql -u root -h old.tdb.com -P 4000 -ppassword mysql> show variables like log_bin; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | log_bin | 1 | +---------------+-------+ 1 row in set (0.01 sec)需要注意,2.1.6之前的版本 log_bin 恒等于 0,就是说即便enable_binlog = True,通过show variables like log_bin;查出来的也是0,但是pump会记录binlog。
建议挨个tidb都检查一遍。
(9)在ansible管理机更新监控
ansible # ansible-playbook rolling_update_monitor.yml -t prometheus -i inventory.ini(10)创建全量备份
ansible # /path/mydumper -u user -p pass -h old.tdb.com -P 4000 -t 2 -F 32 --skip-tz-utc -o /backup_path/4000 -B db_name备份需要注意:
工具获取 https://docs.pingcap.com/zh/tidb/v2.1/backup-and-restore
在业务低峰进行备份,否则可能会出现网卡打满的情况(尤其是tidb是万兆网卡,tikv是千兆网卡的架构)
可能会因为gc时间过短导致备份失败(通过调整gc时间解决)
可能因为tidb分配的内存过小导致备份失败(通过调整tidb内存解决)
备份完成后建议检查一下建表语句的文件,是否存在非法时间格式("0000-00-00"),如果存在在导入新集群的时候会报错,需要跟业务沟通一下变更默认值。
mydumper不支持限流备份,可以通过备份到磁盘性能很差的机器或者cfs这种网络存储,在一定程度上实现了限流备份。
4、部署4.0环境并导入全量数据悲观事务模型需要关注一下,4.0虽然支持悲观事务模型,而且新建集群默认也是开启状态,但是要想一个操作用到悲观锁,还是有一定的限定条件的,即非autocommit 的事务。具体请参考这个文章的【6.2.3.2部分】 https://book.tidb.io/session1/chapter6/pessimistic-txn.html
(1)安装tiup
ansible # curl --proto =https --tlsv1.2 -sSf https://tiup-mirrors.pingcap.com/install.sh | sh ansible # . /root/.bash_profile ansible # tiup --version ansible # tiup update --self(2)准备拓扑文件
ansible # vim topology-oltp-xxx.yamlglobal: user: "tidb" ssh_port: 22 deploy_dir: "/tidb-deploy" data_dir: "/tidb-data" monitored: node_exporter_port: 11000 blackbox_exporter_port: 12000 pd_servers: - host: 10.0.1.4 - host: 10.0.1.5 - host: 10.0.1.6 tidb_servers: - host: 10.0.1.1 - host: 10.0.1.2 - host: 10.0.1.3 tikv_servers: - host: 10.0.1.7 - host: 10.0.1.8 - host: 10.0.1.9 cdc_servers: - host: 10.0.1.7 - host: 10.0.1.8 - host: 10.0.1.9 monitoring_servers: - host: 10.0.1.10 grafana_servers: - host: 10.0.1.10 alertmanager_servers: - host: 10.0.1.10以上是官方提供的配置模板,请根据实际情况修改。
建议部署ticdc(pump),避免需要回滚的时候可追溯增量数据。
建议每个组件单独一台机器。
(3)检查tiup 管理机到各个节点的ssh通道是否正常
略
(4)部署集群
ansible # tiup cluster check tidb-oltp-xxx-v4.0.13 v4.0.13 topology-oltp-xxx.yaml ansible # tiup cluster deploy tidb-oltp-xxx-v4.0.13 v4.0.13 topology-oltp-xxx.yaml ansible # tiup cluster start tidb-oltp-xxx-v4.0.13 ansible # tiup cluster display tidb-oltp-xxx-v4.0.13check可能会报很多异常,可以根据提示进行修复,很多异常也可以忽略。请参考 https://docs.pingcap.com/zh/tidb/v4.0/tiup-component-cluster-check#tiup-cluster-check
(5)权限维护
ansible # /opt/soft/mysql57/bin/mysql -u root -h new.tdb.com -P 15002 -p mysql> create user if not exists root@"192.168.1.%" IDENTIFIED BY password; mysql> GRANT ALL PRIVILEGES ON *.* TO root@192.168.1.% WITH GRANT OPTION; mysql> GRANT ALL PRIVILEGES ON *.* TO root@pd1 WITH GRANT OPTION; mysql> GRANT ALL PRIVILEGES ON *.* TO root@pd2 WITH GRANT OPTION; mysql> GRANT ALL PRIVILEGES ON *.* TO root@pd3 WITH GRANT OPTION;这里用空密码就能登录。
这里需要加上pd节点的授权,而且要求是root用户(还是给all权限吧,测试发现给select权限不行,没做更细致的权限测试),否则dashboard不能正常使用。
ansible # /opt/soft/mysql57/bin/mysql -u root -h new.tdb.com -P 15002 -ppassword mysql> drop user if exists root@"%";建议删除root@%这个空密码用户。
(6)导入全量数据
ansible # /path/loader -d /backup_path/4000 -h new.tdb.com -u user -p password -P 15002 -t 2 -status-addr ":9299"恢复需要注意:
工具获取 https://docs.pingcap.com/zh/tidb/v2.1/backup-and-restore
建议在业务低峰进行恢复
可能会因为表情符导致loader失败,如果遇到,可以试试Dumpling
多个loader任务的场景,建议避开默认端口,否则可能会因为端口冲突导致失败
5、同步增量数据这步操作在ansible管理机执行
(1)在备份机获取备份点位(本例使用ansible管理机进行备份)
从备份目录查看metadata文件
ansible # cd /backup_path/xxx ansible # cat metadata Started dump at: 2021-08-29 15:34:30 SHOW MASTER STATUS: Log: tidb-binlog Pos: 425971435565482001 GTID: Finished dump at: 2021-08-29 15:34:33 ansible #(2)修改配置文件
ansible # vim /path/github/tidb-ansible-2.1.8/inventory.ini添加drainer组件的监控
[monitored_servers] monitor-drainer1 ansible_host=xxxx deploy_dir=/path/tidb-data/drainer-24001添加drainer组件
[drainer_servers] drainer1 ansible_host=xxxx deploy_dir=/path/tidb-data/drainer-24001 initial_commit_ts="425971435565482001"drainer端口设置
## Global variables [all:vars] drainer_port = 24001(3)准备drainer的配置文件
ansible # vim /path/github/tidb-ansible-2.1.8/conf/drainer1_drainer.toml配置文件名命名规则为【别名_drainer.toml】,否则部署时无法找到自定义配置文件。
# drainer Configuration. # the interval time (in seconds) of detect pumps status detect-interval = 10 # syncer Configuration. [syncer] # disable sync these schema ignore-schemas = "INFORMATION_SCHEMA,PERFORMANCE_SCHEMA,mysql" # number of binlog events in a transaction batch txn-batch = 2000 # work count to execute binlogs worker-count = 32 disable-dispatch = false # safe mode will split update to delete and insert safe-mode = false # downstream storage, equal to --dest-db-type # valid values are "mysql", "pb", "tidb", "flash", "kafka" db-type = "tidb" # the downstream MySQL protocol database [syncer.to] host = "new.tdb.com" user = "user" password = "xxxx" port = 15002txn-batch 和 worker-count的配置在配置文件默认值应该是1,建议根据实际情况改大点,如果太小可能出现增量数据一直追不上的情况。
(4)部署drainer及监控
ansible # ansible-playbook deploy_drainer.yml -i inventory.ini -l drainer1 ansible # ansible-playbook deploy.yml -i inventory.ini -l monitor-drainer1(5)登录新集群的tidb,给drainer节点授权
ansible # /opt/soft/mysql57/bin/mysql -u root -h new.tdb.com -P 15002 -ppassword mysql> create user if not exists user@"drainer_host" IDENTIFIED BY xxxx; mysql> GRANT ALL PRIVILEGES ON *.* TO user@drainer_host;注意:新集群(4.0)要给drainer所在的主机授权,否则启动drainer将报错,为了演示方便,这里直接给了所有权限
(6)启动drainer及监控
启动drainer前建议先确定一下目标库是否已经存在tidb_binlog库,如果存在,且又需要从备份的点位开始增量同步,这种情况需要手动删除一下,要不然drainer会从checkpoint开始同步数据。(一般出现在导入全量失败后需要重新导入全量,然后忘记清理tidb_binlog库)
ansible # ansible-playbook start_drainer.yml -i inventory.ini -l drainer1 ansible # ansible-playbook start.yml -i inventory.ini -l monitor-drainer1(7)登录tidb检查drainer状态
ansible # /opt/soft/mysql57/bin/mysql -u root -h old.tdb.com -P 4000 -ppassword mysql> show drainer status; +------------+------------+--------+--------------------+---------------------+ | NodeID | Address | State | Max_Commit_Ts | Update_Time | +------------+------------+--------+--------------------+---------------------+ | xxxx:24001 | xxxx:24001 | online | 431972431138127904 | 2021-08-25 16:42:57 | +------------+------------+--------+--------------------+---------------------+ 1 rows in set (0.00 sec) mysql>需要注意,2.1.6之前的版本不支持这个查询操作,需要通过binlogctl 进行查看drainer的状态,如下示例。
ansible # /path/binlogctl -pd-urls=http://pd_host:pd_port -cmd drainers INFO[0000] drainer: {NodeID: xxxx:24001, Addr: xxxx:24001, State: online, MaxCommitTS: 432180589478543384, UpdateTime: 2021-08-25 16:45:57 +0800 CST}(8)更新监控
ansible # ansible-playbook rolling_update_monitor.yml -t prometheus -i inventory.ini(9)登录grafana进行查看同步进度
注意:如果同步落后比较大,可以在alertmanager将drainer的告警先禁用
6、校验新旧集群数据一致性(1)下载工具
ansible # git clone https://gitee.com/mo-shan/check_data_for_mysql.git ansible # cd check_data_for_mysql(2)修改配置
编辑配置文件
ansible # cd /path/check_data_for_mysql ansible # vim conf/check.confmysql_user="xxxx" mysql_passwd="xxxx" mysql_port1="6666" mysql_port2="6666" mysql_host1="192.168.1.1" mysql_host2="192.168.1.2" max_count=10000 threads=5 max_threads_running=30 mysql_path="/opt/soft/mysql57/bin/mysql" log_partition="/dev/sda3" log_par_size="10" skip_check_table="" skip_check_db="INFORMATION_SCHEMA,METRICS_SCHEMA,PERFORMANCE_SCHEMA,mysql,sys,tidb_binlog,test,tidb_loader,dm_meta" #不建议改请结合实际情况根据注释提示进行相关配置
修改工作路径
ansible # sed -i s#^work_dir=.*#work_dir=\"/check_data_for_mysql_path\"#g start.sh #将这里的check_data_for_mysql_path改成check_data_for_mysql的家目录的绝对路径(3)测试用例
每次执行校验任务的时候强制要清空log目录,所以请做好校验结果的备份
执行校验任务的时候强烈建议开启screen
有网卡监控需求,执行监控脚本时也强烈建议单独开启screen进行监控
第一步:先开启一个screen监控网络
ansible # screen -S check_net_4000 ansible # bash manager.sh -a start [ 2022-01-18 11:55:34 ] [ 1000 Mb/s ] [ RX : 2 MB/S ] [ TX : 2 MB/S ] [ 2022-01-18 11:55:35 ] [ 1000 Mb/s ] [ RX : 2 MB/S ] [ TX : 4 MB/S ] [ 2022-01-18 11:55:36 ] [ 1000 Mb/s ] [ RX : 2 MB/S ] [ TX : 2 MB/S ] [ 2022-01-18 11:55:37 ] [ 1000 Mb/s ] [ RX : 2 MB/S ] [ TX : 3 MB/S ] [ 2022-01-18 11:55:38 ] [ 1000 Mb/s ] [ RX : 1 MB/S ] [ TX : 2 MB/S ] [ 2022-01-18 11:55:39 ] [ 1000 Mb/s ] [ RX : 1 MB/S ] [ TX : 2 MB/S ] [ 2022-01-18 11:55:41 ] [ 1000 Mb/s ] [ RX : 1 MB/S ] [ TX : 2 MB/S ] [ 2022-01-18 11:55:42 ] [ 1000 Mb/s ] [ RX : 2 MB/S ] [ TX : 8 MB/S ]第二步:新开启一个screen执行校验任务
ansible # screen -S check_data_4000 ansible # bash start.sh -d dba -t dbatest1 -f true [ 2022-01-17 20:32:19 ] [ 成功 ] [ 192.168.1.1 ] [ start.sh/start.sh ] [ f_prepare:130 ] [ 本次数据一致性检查开始 ] [ 2022-01-17 20:32:19 ] [ 警告 ] [ 192.168.1.1 ] [ start.sh/start.sh ] [ f_main:185 ] [ 本次数据一致性检查将检查如下库 : [dba] ] [ 2022-01-17 20:32:19 ] [ 成功 ] [ 192.168.1.1 ] [ start.sh/start.sh ] [ f_main:203 ] [ 正在检查dba库 ] [ 2022-01-17 20:32:19 ] [ 成功 ] [ 192.168.1.1 ] [ func/f_check_diff_for_mysql.sh ] [ f_check_diff_for_mysql:249 ] [ dba.dbatest1 ] [ 表结构一致 ] [ 2022-01-17 20:32:19 ] [ 成功 ] [ 192.168.1.1 ] [ func/f_check_diff_for_mysql.sh ] [ f_check_diff_for_mysql:491 ] [ dba.dbatest1 ] [ 1,1 ] [ 00 d 00 h 00 m 00 s ] [ 9.09%, (0:0)/1 ] [ 数据一致 ] [ 2022-01-17 20:32:19 ] [ 成功 ] [ 192.168.1.1 ] [ func/f_check_diff_for_mysql.sh ] [ f_check_diff_for_mysql:491 ] [ dba.dbatest1 ] [ 2,11 ] [ 00 d 00 h 00 m 00 s ] [ 100.00%, (0:0)/1 ] [ 数据一致 ] [ 2022-01-17 20:32:19 ] [ 成功 ] [ 192.168.1.1 ] [ func/f_check_diff_for_mysql.sh ] [ f_check_diff_for_mysql:504 ] [ dba.dbatest1 ] [ 检查完毕 ] [ 2022-01-17 20:32:19 ] [ 成功 ] [ 192.168.1.1 ] [ start.sh/start.sh ] [ f_main:242 ] [ 本次数据一致性检查完成 ] [ 通过 ] ansible #检查结束后会提示检查通过,否则就是检查不通过。
工具实现逻辑请参考 https://tidb.net/blog/09e2fdf0
7、交付新环境dba提供新的域名和端口给业务,这里给业务提供一个只读账户即可。
ansible # /opt/soft/mysql57/bin/mysql -u root -h new.tdb.com -P 15002 -ppassword mysql> create user if not exists read_only@"host" IDENTI版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。