tidb-install-pit
前言
近期随着公司的业务发展,现有的mysql分库分表,无缝动态扩容,分布式事物,分布式id等等一些问题得不到满足,为此我们做了一次对tidb的考察,此文是记录tidb的安装遇到的坑进行记录,并做了一些功能性和性能方面的测试,详情按照官方doc进行。
环境
集群规模:
node1 192.168.138.18 PD1, TiDB1 4c16G 200GHHD
node2 192.168.138.19 PD2, TiDB2 4c16G 200GHHD
node3 192.168.138.21 PD3 2c16G 200GHHD
node4 192.168.138.22 TiKV1,zk,kakfka 2c16G 200GHHD
node5 192.168.138.23 TiKV2,zk,kakfka 2c16G 200GHHD
node6 192.168.138.24 TiKV3,zk,kakfka 2c16G 200GHHD
当前os环境:
1 | # cat /etc/redhat-release |
磁盘分布情况:
1 | # lsblk -f |
每台机器有2块硬盘,按照官方要求外挂的那块文件系统是ext4的。
然后机器需要安装git。
官方安装doc
https://pingcap.com/docs-cn/v3.0/how-to/deploy/orchestrated/ansible/
首先执行的是:
1 | # yum -y install epel-release git curl sshpass |
[坑]No package epel-release available
根据epel-repo-centos-7指南需要执行:
1 | # rpm -ivh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm |
然后在执行[yum -y install epel-release git curl sshpass]才会成功.
[坑]提前配置Grafana Dashboard 上的 Report 按钮可用来生成 PDF 文件
在Grafana部署的机器上执行:
1 | sudo yum install fontconfig open-sans-fonts |
[坑]PD 和 TiDB 同时部署的机器要求要有8个cpu core
异常如下:
[192.168.138.18]: Ansible FAILED! => playbook: bootstrap.yml; TASK: check_system_optional : Preflight check - Check TiDB server’s CPU; message: {“changed”: false, “msg”: “This machine does not have sufficient CPU to run TiDB, at least 8 cores.”}
[192.168.138.19]: Ansible FAILED! => playbook: bootstrap.yml; TASK: check_system_optional : Preflight check - Check TiDB server’s CPU; message: {“changed”: false, “msg”: “This machine does not have sufficient CPU to run TiDB, at least 8 cores.”}
解决方式:
- 找运维增加虚拟机的cpu core数量
- 修改参数:vi roles/check_system_optional/defaults/main.yml
1 | tidb_min_cpu: 2 |
其他的内存和硬盘的检查参数也在这个文件配置。
- 参考: https://github.com/pingcap/tidb/issues/6423
[坑]磁盘检查异常
异常信息:
[192.168.138.22]: Ansible FAILED! => playbook: bootstrap.yml; TASK: machine_benchmark : Preflight check - Does fio randread iops of tikv_data_dir disk meet requirement; message: {“changed”: false, “msg”: “fio: randread iops of tikv_data_dir disk is too low: 7748 < 40000, it is strongly recommended to use SSD disks for TiKV and PD, or there might be performance issues.”}
[192.168.138.23]: Ansible FAILED! => playbook: bootstrap.yml; TASK: machine_benchmark : Preflight check - Does fio randread iops of tikv_data_dir disk meet requirement; message: {“changed”: false, “msg”: “fio: randread iops of tikv_data_dir disk is too low: 3128 < 40000, it is strongly recommended to use SSD disks for TiKV and PD, or there might be performance issues.”}
[192.168.138.24]: Ansible FAILED! => playbook: bootstrap.yml; TASK: machine_benchmark : Preflight check - Does fio randread iops of tikv_data_dir disk meet requirement; message: {“changed”: false, “msg”: “fio: randread iops of tikv_data_dir disk is too low: 8847 < 40000, it is strongly recommended to use SSD disks for TiKV and PD, or there might be performance issues.”}
解决方式:
1 | # vi roles/machine_benchmark/defaults/main.yml |
修改min_ssd_randread_iops的大小。
跳过cpu、mem、disk检查
有些企业由于成本问题,在开发测试环境都是HHD,没法满足tidb的硬件要求,因此我们可以使用开发模式,跳过cpu、内存、硬盘的检查。
1 | # ansible-playbook bootstrap.yml --extra-vars "dev_mode=True" |
[注意事项]TiDB的binlog开启
/home/tidb/tidb-ansible/inventory.ini配置如果【enable_binlog = True 】
意味着需要配置TiDB-Binlog,当前集群按照官方doc搭建了zk和kafka集群,然后部署了pump(抓取tidb的binlog塞到kafka集群)。
[坑]启动之后grafana进程没有
切换到部署目录/data/deploy/scripts
手动执行: ./start_grafana.sh
tidb在navicat下修改表结构问题
tidb在navicat下修改表结构一次性不允许修改(添加或者修改)多个列,否则报错:
登陆
- 使用mysql客户端登陆
- 使用tidb(密码:tidb)登陆开发机,注意:必须是tidb用户。
- mysql -u root -proot -h 192.168.138.18 -P 4000
- mysql -u tnp_test -ptnp_test -h 192.168.138.18 -P 4000
- PS:192.168.138.19 和 192.168.138.18都可以链接
- 使用tidb(密码:tidb)登陆开发机,注意:必须是tidb用户。
修改集群配置之后重启步骤/集群启动/集群关闭
配置
对【/home/tidb/tidb-ansible/inventory.ini】进行修改后需要执行:1
# ansible-playbook deploy.yml
目的是把配置下放到所有的机器。
启动集群
ansible-playbook start.yml关闭集群
ansible-playbook stop.yml
启动集群 | ansible-playbook start.yml |
---|---|
停止集群 | ansible-playbook stop.yml |
销毁集群 | ansible-playbook unsafe_cleanup.yml (若部署目录为挂载点,会报错,可忽略) |
清除数据(测试用) | ansible-playbook cleanup_data.yml |
滚动升级 | ansible-playbook rolling_update.yml |
滚动升级 TiKV | ansible-playbook rolling_update.yml –tags=tikv |
滚动升级除 PD 外模块 | ansible-playbook rolling_update.yml –skip-tags=pd |
滚动升级监控组件 | ansible-playbook rolling_update_monitor.yml |
Prometheus访问地址
http://192.168.138.18:9090/graph
Pushgateway访问地址
http://192.168.138.18:9091/
Node_exporter访问地址
http://192.168.138.18:9100/
grafana访问地址
http://192.168.138.18:3000
用户名/密码:admin/admin
指标解释:https://github.com/pingcap/docs-cn/blob/master/dev/reference/key-monitoring-metrics/tidb-dashboard.md
全量备份与恢复
https://pingcap.com/docs-cn/v3.0/how-to/maintain/backup-and-restore/
增量备份与恢复
TiDB Binlog从kafka收集binlog给Drainer
https://pingcap.com/docs-cn/v3.0/reference/tidb-binlog-overview/
Reparo从Drainer得到数据恢复到mysql/tidb
https://pingcap.com/docs-cn/v3.0/reference/tools/tidb-binlog/reparo/
注意事项
db-type = “file”是为了Reparo做恢复用,和官方文档不同的是要创建
drainer_file_drainer-cluster.toml文件,而不是drainer_file_drainer.toml。
相关问答:https://asktug.com/t/drainer-file-drainer-cluster-toml/406/3
定位慢查询
1 | select `Query_time`, query from INFORMATION_SCHEMA.`SLOW_QUERY` where `Is_internal`=false order by `Query_time` desc limit 2; |
官方doc:https://pingcap.com/docs-cn/v3.0/how-to/maintain/identify-slow-queries/
扩容缩容
https://pingcap.com/docs-cn/v3.0/how-to/scale/with-ansible/
与 MySQL 安全特性差异
仅支持 mysql_native_password 身份验证方案。
不支持外部身份验证方式(如 LDAP)。
不支持列级别权限设置。
不支持使用证书验证身份。#9708
不支持密码过期,最后一次密码变更记录以及密码生存期。#9709
不支持权限属性 max_questions,max_updated,max_connections 以及 max_user_connections。
不支持密码验证。#9741
不支持透明数据加密(TDE)。
对mysql的支持
TiDB 目前还不支持触发器、存储过程、自定义函数、外键,除此之外,TiDB 支持绝大部分 MySQL 5.7 的语法。
- 支持分布式事物
- TiDB 字符集默认就是 UTF8 而且目前只支持 UTF8,字符串就是 memcomparable 格式的。
- 自增id只保证自增和唯一,不保证顺序性(段式分配导致)。
事物
事物隔离级别Snapshot Isolation
tidb只支持Snapshot Isolation事物隔离级别,TiDB 实现了快照隔离 (Snapshot Isolation) 级别的一致性。为与 MySQL 保持一致,又称其为“可重复读”。MySQL 可重复读隔离级别的一致性要弱于 Snapshot 隔离级别,也弱于 TiDB 的可重复读隔离级别。
另外多线程操作同一行数据,一定会有一个失败,失败的事物默认不会重试,而是以异常的形式抛出,是否重试交给应用来判断,但是也可以开启自动重试,只不过开启之后,重试事务可能会导致更新丢失,因为 TiDB 自动重试机制会把事务第一次执行的所有语句重新执行一遍,当一个事务里的后续语句是否执行取决于前面语句执行结果的时候,自动重试会违反快照隔离,导致更新丢失。
doc:https://pingcap.com/docs-cn/v3.0/reference/transactions/transaction-isolation/
乐观锁
- 数据操作冲突比较验证不适,会产生大量的重试,如果访问冲突并不十分严重,那么乐观锁模型具备较高的效率。
- 在冲突严重的场景下,推荐在系统架构层面解决问题,比如将计数器放在 Redis 中。
事务大小限制
- 单个事务包含的 SQL 语句不超过 5000 条(默认)
- 单条 KV entry 不超过 6MB
- KV entry 的总条数不超过 30W
- KV entry 的总大小不超过 100MB
建议无论是 Insert,Update 还是 Delete 语句,都通过分 Batch 或者是加 Limit 的方式限制。
具体罗亿乔之前的sql技术分享。
支持悲观锁,但是官方不建议生产环境使用,因为在官方将其定义为实验性的特性
- 不支持 GAP Lock 和 Next Key Lock 在悲观事务内通过范围条件来更新多行数据的时候,其他的事务可以在这个范围内插入数据而不会被阻塞。
- 不支持 SELECT LOCK IN SHARE MODE。
事物限制
- 小事物比单机mysql性能要低,以为有网络参与,用显式事务代替
auto_commit
,可优化该性能。 - 事物惰性检查,执行insert语句,不在
INSERT
语句执行时进行唯一约束的检查,而在事务提交时进行唯一约束的检查。1
2
3
4
5
6
7CREATE TABLE T (I INT KEY);
INSERT INTO T VALUES (1);
BEGIN;
INSERT INTO T VALUES (1); -- MySQL 返回错误;TiDB 返回成功
INSERT INTO T VALUES (2);
COMMIT; -- MySQL 提交成功;TiDB 返回错误,事务回滚
SELECT * FROM T; -- MySQL 返回 1 2;TiDB 返回 1
这样做的目的是为了减少网络开销。
小结
总的来说事物这方面的最贱实践是:乐观锁+事物失败应用级别处理+分布式锁加强,不建议开启事物失败重试机制(除非事物之间没有任何关系)。事物结束之后(commit之后)要判断返回值是否成功.
存在数据热点问题
相同的表数据会优先聚集到TiKV节点,如果某个表的数据比较热,那么TiKV很有可能成为系统的瓶颈,尤其是在很小范围的数据频繁操作,某个region会成为系统的热点。
https://pingcap.com/blog-cn/tidb-best-practice/
解决之道(通过设置 SHARD_ROW_ID_BITS
来适度分解 Region 分片):https://pingcap.com/docs-cn/v3.0/reference/configuration/tidb-server/tidb-specific-variables/#shard-row-id-bits
热点问题官方FAQ:https://asktug.com/t/tidb/358
GC 垃圾回收
tidb使用MVCC关林数据的版本,老版本的数据通过垃圾收集器进行删除,时间默认是10分钟执行一次回收,回收线程和频率可以在系统表设置。
TiDB 的最佳适用场景
- 数据量大,单机保存不下
- 不希望做 Sharding 或者懒得做 Sharding
- 访问模式上没有明显的热点
- 需要事务、需要强一致、需要灾备
在单台tidb做sybench
参考官方doc:https://pingcap.com/docs-cn/v3.0/benchmark/how-to-run-sysbench/
[坑]导入数据耗时较长,导入数据的命令要使用nohu执行
官方doc导入数据的命令会执行很长一段时间,当xshell超时的时候,我们没法监控命令的执行日志,因此要使用nohup:
1 | nohup sysbench --config-file=config oltp_point_select --tables=32 --table-size=1000000 prepare 2>&1 & |
- 样本数据
- 32张表、每张表100万条数据,每张表大约1M数据。
- 集群规模
node1 192.168.138.18 PD1, TiDB1 4c16G 200GHHD
node2 192.168.138.19 PD2, TiDB2 4c16G 200GHHD
node3 192.168.138.21 PD3 2c16G 200GHHD
node4 192.168.138.22 TiKV1 2c16G 200GHHD
node5 192.168.138.23 TiKV2 2c16G 200GHHD
node6 192.168.138.24 TiKV3 2c16G 200GHHD
sysbench所有测试结果详情在[192.168.138.18]: vi /home/tidb/tidb-bench/nohup.out
###
oltp_point_select
- nohup sysbench –config-file=config oltp_point_select –tables=32 –table-size=1000000 prepare 2>&1 &
threads | read | write | tps | qps | total time | min | avg | max | 95th |
---|---|---|---|---|---|---|---|---|---|
8 | 5937332 | 0 | 5937332 (9895.26 per sec.) | 5937332 (9895.26 per sec.) | 600.0156s | 0.40 | 0.81 | 223.17 | 1.03 |
16 | 9396775 | 0 | 9396775 (15660.86 per sec.) | 9396775 (15660.86 per sec.) | 600.0148 | 0.39 | 1.02 | 177.08 | 1.52 |
32 | 12217819 | 0 | 12217819 (20362.72 per sec.) | 12217819 (20362.72 per sec.) | 600.0075s | 0.39 | 1.57 | 119.33 | 3.75 |
64 | 13085444 | 0 | 13085444 (21808.49 per sec.) | 13085444 (21808.49 per sec.) | 600.0142s | 0.41 | 2.93 | 270.10 | 8.43 |
128 | 13680931 | 0 | 13680931 (22800.08 per sec.) | 13680931 (22800.08 per sec.) | 600.0370s | 0.43 | 5.61 | 1033.14 | 13.70 |
95th :https://www.zhihu.com/question/20575291
oltp_update_index
- nohup sysbench –config-file=config oltp_update_index –tables=32 –table-size=10000000 run 2>&1 &
threads | read | write | tps | qps | total time | min | avg | max | 95th |
---|---|---|---|---|---|---|---|---|---|
8 | 0 | 149902 | 149902 (249.82 per sec.) | 149902 (249.82 per sec.) | 600.0418s | 10.26 | 32.02 | 475.79 | 46.63 |
16 | 0 | 213850 | 213850 (356.39 per sec.) | 213850 (356.39 per sec.) | 600.0444s | 9.30 | 44.89 | 659.85 | 142.39 |
32 | 0 | 483912 | 483912 (806.47 per sec.) | 483912 (806.47 per sec.) | 600.0370s | 10.34 | 39.68 | 689.26 | 54.83 |
64 | 0 | 880168 | 880168 (1466.72 per sec.) | 880168 (1466.72 per sec.) | 600.0897s | 10.60 | 43.63 | 1109.14 | 58.92 |
128 | 0 | 1344814 | 1344814 (2241.17 per sec.) | 1344814 (2241.17 per sec.) | 600.0473s | 9.90 | 57.11 | 8177.34 | 75.82 |
256 | 0 | 1882603 | 1882603 (3137.16 per sec.) | 1882603 (3137.16 per sec.) | 600.0950s | 11.88 | 81.59 | 1418.85 | 211.60 |
oltp_read_only
- nohup sysbench –config-file=config oltp_read_only –tables=32 –table-size=10000000 run 2>&1 &
threads | total | tps | qps | total time | min | avg | max | 95th |
---|---|---|---|---|---|---|---|---|
8 | 6204464 | 387779 (646.28 per sec.) | 6204464 (10340.44 per sec.) | 600.0174s | 8.88 | 12.38 | 427.50 | 16.41 |
16 | 9270576 | 579411 (965.65 per sec.) | 9270576 (15450.37 per sec.) | 600.0211s | 10.03 | 16.57 | 1203.28 | 26.20 |
32 | 11644768 | 727798 (1212.92 per sec.) | 11644768 (19406.73 per sec.) | 600.0359s | 9.18 | 26.38 | 1132.08 | 46.63 |
64 | 12632864 | 789554 (1315.79 per sec.) | 12632864 (21052.63 per sec.) | 600.0590s | 11.66 | 48.63 | 423.32 | 84.47 |
128 | 12792912 | 799557 (1332.37 per sec.) | 12792912 (21317.86 per sec.) | 600.1013s | 10.65 | 96.06 | 3153.57 | 150.29 |
TPC-C测试
https://pingcap.com/docs-cn/v3.0/benchmark/how-to-run-tpcc/
TPC-C 是一个对 OLTP(联机交易处理)系统进行测试的规范,使用一个商品销售模型对 OLTP 系统进行测试。
TPC-C 使用 tpmC 值(Transactions per Minute)来衡量系统最大有效吞吐量 (MQTh, Max Qualified Throughput),其中 Transactions 以 NewOrder Transaction 为准,即最终衡量单位为每分钟处理的新订单数。
BenchmarkSQL 配置
修改 benchmarksql/run/props.mysql
1 | conn=jdbc:mysql://{HAPROXY-HOST}:{HAPROXY-PORT}/tpcc?useSSL=false&useServerPrepStmts=true&useConfigs=maxPerformance |
初始化数据库
1 | create database tpcc |
之后在 shell 中运行 BenchmarkSQL 建表脚本:
1 | cd run |
运行导入数据脚本:
1 | nohup ./runLoader.sh props.mysql 2>&1 & |
这个过程时间会有点长(我们的测试环境集群这条命令运行了6个小时,等的花儿都谢了。。。)。
验证导入的数据:
1 | nohup ./runSQL.sh props.mysql sql.common/test.sql 2>&1 & |
运行测试
1 | nohup ./runBenchmark.sh props.mysql &> test.log 2>&1 & |
测试结果
[192.168.138.18] vi /home/tidb/benchmarksql/run/test.log
系统每分钟的吞吐量是在4399.16(官方机器配置结果是:77373.25),即集群每分钟能承载的订单数量是4399个订单。
其他企业在tidb的实践与分享
https://github.com/pingcap/presentations