解读 TiDB Server

三种视角下的 TiDB Server

TiDB Server 在 TiDB 集群中主要承担了 F1 负责计算和为应用提供 API 工作外 。实际还提供很多重要的功能,我们从三种不同视角来谈一下 TiDB Server。

进程视角

TiDB Server 作为一个进程提供默认监听端口 4000,为应用层提供 API,通过 Go 编译的 MySQL 协议解析器兼容 MySQL 对应用层数据处理方式。从 PD 获取 TSO 开启事务,完整的执行完成 2 阶段提交后,将数据持久化到承担 Spanner 工作的 TiKV Server 。

接入层视角

TiDB Server 兼容 MySQL 协议,可以将 MySQL 支持的 SQL 语言(标准 SQL 或者 MySQL 方言 SQL)进行 SQL 解析。作为应用的接入层,为了提高 TiDB 集群的高并发处理能力,一般会在 TiDB Server 上层配置 Load Balancer 层(F5 或者 Haproxy)。如果在应用层发生 TiDB Server connect timeout 的报错时候,在真实的网络链路里应用的一个事务已经在至少 3 层链路中流动过,所以在判断连接问题的时候,建议还是顺流而下一一判断不同层级的状态。在应用端(或称为 TiDB Server 的客户端)存在网络超时的设置;也可能在 Load Balancer 里面有设置过默认超时或者异常中断机制;或许在系统层(Operation System)对长链接有超时设置。TiDB Server 目前不支持数据库层的会话超时,很大一部分原因是因为在 TiDB Server 上层的 LB 或者 APP Client 对超时是可控的。

独立性视角

TiDB Server 不是完全独立,彼此间还会有间接影响。为提供 Online DDL 的功能,TiDB Server 利用 PD Server 的 Etcd 端口实现完整的标示,选主,注册,DDL 执行的任务。首先会通过 TiDB Server UUID 作为唯一标示,优势在于无状态且唯一性。这个标示仅在一个生命周期内,TiDB Server 重启会重新生成。IP 加 Port 的标示方式在 Docker 部署方式下不能保证唯一性可能存在重复性,如果自动设置可能带来更多的不唯一性隐患。所以不作为 TiDB Server 的标示方式。

通过 Etcd (PD supports distribution and fault-tolerance by embedding etcd.) 端口在 PD Server 注册信息后,将 Tidb Server 的 uuid 作为 key ,value 放自己的信息,在进行选主,leader 会做 DDL owner 。

假使一个 TiDB Server 收到 DDL Job ,TiDB Server 会将 DDL Job 写入到 TiKV 线性队列中完成持久化。如果 DDL owner 的 TiDB Server 发生宕机,依然会有其他的 TiDB Server 承担 DDL owner 完成 Job 。而持久化到 TiKV Job 队列中的 DDL 操作的结果只有写入成功或者因为语法报错返回失败。提交 DDL Job 的 TiDB Server 会按照一定时间检查 Job 状态,并最终将结果反馈给 APP Client。如果 DDL 操作出现问题,我们一般定位问题都会在 TiKV Job 线性队列持久化或者 Etcd 协同工作的环节进行排查。

TiDB Server 功能

TiDB Server 是 TiDB 分布式数据库的 Input/Output 端口,为 APP Client 提供完整数据库服务,已经实现很多功能,这些功能分为用户可感知的前台服务,包括诸如 连接,Golang 版本的 MySQL 协议的 SQL 解析,标准 SQL 语法等;也有对应用透明实际在数据库运行中提供重要维护工作的 GC 清理机制,Online DDL 执行机制,统计信息以及权限管理等等。详细的功能点如下:

  • Foreground
    • Connection/Session Management
    • MySQL Protocol decode/encode
    • Standard SQL
    • MySQL Dialect
    • MySQL Database/Table/SysVar
      • Information Schema
      • System Variables
    • Query Optimization
    • Query Execution
    • Transaction Management
      • TiDB server -> tikv driver (client)完成
    • Privilege Management
    • DDL
    • DML
  • Background
    • GC :tidb 主动发起 GC 命令,驱动 Tikv 完成清理无用数据;
    • DDL Execution :key range 记录存储,保证 snapshot ,在 ddl owner 宕机,DDL job 依然可以继续执行;
    • Statistics Management:全量 analyze ,增量 ,统计信息策略
    • Privilege Management:后台维护 cahche,提供权限隔离等机制
    • InfoSchema Management:schema 信息的收集

MySQL 兼容

我们希望用户使用 TiDB 时候,更像在使用一套非常强悍吞吐能力的 MySQL 数据库,在应用使用 TiDB 时候,就像后面的集群是透明的一样。在进行 TiDB Server 研发过程中,努力让 TiDB 集群高度兼容 MySQL 不同版本的功能,让用户无缝迁移到 TiDB 集群上面。

  • 以 5.7 为主 - 计划每次发版本前调整到最新的 MySQL 5.7 release
  • 逐步演进 8.0

在 TiDB Server 支持 MySQL 的协议,语法,方言语法,DDL/DML,系统变量,内置功能,SQL Mode 以及类型推导等等。MySQL 的功能非常多,而且在自身的实现功能上也存在一定差距,所以在产品分析中,其实功能功能是否和 MySQL 一致的问题,实际是上是没有可比性的。

TiDB Server 启停

启动 TiDB Server

TiDB Server 启动过程分为如果的步骤流程,第一步在开始解析命令行参数读取启动参数;第二布再进行 metrics 注册,初始化 Pormetheus 客户端,这里开始收集 Metric 信息;第三部将读取配置 tidb.toml 配置文件里面的参数,注意这里的配置文件参数会被第一步命令行参数覆盖。第四步设置参数,包括 gRPC 等参数配置;第五步会初始 logger ,也就是开始输出日志,我们可以看到 tidb.log 或者 tidb_stderr.log 会输出相关启动信息;第六步就是发送心跳到 PD 节点,在这里会有有个 keep alive OPM 监控视图,可以看到集群的 keep_alive_total 的数据,阈值 12 左右就是正常的;第七步就开始初始化实例,会 load information schema 信息,这一步耗时最长,里面会涉及后面解读的 Bootstrap 的过程;第八步设置 Stop 方法;第九步启动 Loop 监听端口,TiDB Server 可以对外提供服务,循环监听 4000 端口。

Bootstrap

TiDB Server 是无状态的,所有状态信息都在 TiKV 中。TiDB Server 启动后是不清楚数据最新的状态的。Bootstrap 流程为 TiDB Server 保证最新的版本的数据。

bootstrap

  • 独立进行 bootstrap ,启动自动发起的,不会相互协调。
  • bootstrap 做什么
    • 检查版本是否最新的,会版本升级,通过 DDL DML 更新 schema 信息

TiDB Server 停止

监听系统信号,根据系统信号来执行 TiDB Server 停止方式

  • SIGHUP
  • SIGINT
  • SIGTERM
  • SIGQUIT (Graceful Shutdown)

Shutdown TiDB server 会有两种方式:

  • 断开连接
    • Shutdown:直接断开所有连接

比较粗暴,如果当时会有事务在执行,尤其是在 2 阶段提交的阶段,这种断开是不计后果的,可能会导致数据的不一致。

  • Graceful Shutdown:等待当前 query 运行完毕再断开连接

TiDB Server 收到 unix 的 SIGQUIT 信号,通过systemd 进行 TiDB Server 服务关闭,这种关闭会先等到 TiDB Server 上面的 query 全部运行停止后,再断开连接。如果出现大事务长时间执行没有返回成功,那么需要等待很久。Oracle 数据库也有类似的 Shutdown 方式,在 Oracle 数据库关闭数据库一般会先采用 Shutdown immediate 完成关闭,命令会在发起时候,会将当前未执行完成或者正在执行的事务停止,回滚事务后关闭数据库。

  • 关闭 Domain
    • 关闭 DDL 线程,清理 Etcd 上面的信息
  • Event Metrics

这是 TiDB Server 监控中会有 Event OPM 来监控 TiDB Server 的服务状态,可以根据监控可以判断 TiDB Server 是否 start,stop,kill,hang 或者 close 。

客户端连接管理

  • 客户端连接过程

Hash value 进行握手验证

  • 认证 用户名+密码,需要读取 TiKV 数据,如果出现 load 数据慢的情况,可能是读取性能存在问题。
  • Session Context 建立,保存 session scope system variable。session 建立时候,会以默认 Global 参数,然后根据个性化设置覆盖默认设置。
  • 如果出现连接慢的情况,会启动循环处理 Command (如 CmdQuery ),每来一次连接会有一个 Command 连接,收到 Command 到 Command 结束,记录 Command 的时间,类型和数量。

Connection 监控

  • 连接状态和数据量

  • TiDB instance SQL 情况

其他的监控

  • Panic 监控:tidb,server,panic_total
  • Prepared Statement 监控:tidb,server,prepared_stmts
  • Critical error:critical_error_total
  • Token:get_token_duration_seconds

连接断开

  • 优先判断是否客户端主动断掉连接
  • 遇到 Undeterminated Error:给 TiKV 发送请求,Commit PrimaryKey,但是没收到回应
  • 收到 Stop 信号,实例要退出
  • Kill Connection,通过 TiDB Command kill tidb session_id 的方式杀掉 TiDB session。

连接管理

  • show processlist

TiDB 的 show processlist 与 MySQL 的 show processlist 显示内容基本一样,不会显示系统进程号,而 ID 表示当前的 session ID。其中 TiDB 的 show processlist 和 MySQL 的 show processlist 区别如下:

1)由于 TiDB 是分布式数据库,tidb-server 实例是无状态的 SQL 解析和执行引擎(详情可参考 TiDB 整体架构),用户使用 MySQL 客户端登录的是哪个 tidb-server,show processlist 就会显示当前连接的这个 tidb-server 中执行的 session 列表,不是整个集群中运行的全部 session 列表;而 MySQL 是单机数据库,show processlist 列出的是当前整个 MySQL 数据库的全部执行 SQL 列表。

2)TiDB 的 show processlist 显示内容比起 MySQL 来讲,多了一个当前 session 使用内存的估算值(单位 Byte)。

  • kill
    • 可以 kill DML 语句,首先使用 show processlist,找到对应 session 的 id,然后执行 kill tidb [session id]。
    • 可以 kill DDL 语句,首先使用 admin show ddl jobs,查找需要 kill 的 DDL job ID,然后执行 admin cancel ddl jobs ‘job_id’ [, ‘job_id’] …。具体可以参考 admin 操作。
    • 注意:默认 kill 命令是不会真正执行的,需要开启设置才会真正执行。compatible-kill-query
      • 设置 “kill” 语句的兼容性。
      • 默认: false
      • 在 TiDB 里面 “kill xxx” 语句和 MySQL 行为不一致。只有执行 “kill tidb xxx” 的时候,才会真正的杀死一条查询。当 compatible-kill-query 设置为 true 的时候,则兼容 MySQL 的行为,不需要 “tidb” 关键字。
    • 另外 Ctrl + C 不会停止当前正在执行的 session,因为在 BL 层的时候,如果是通过浮动 IP 连接的 session ,执行事务已经在执行,Ctrl + C 实际就是 session 退出,但是不会停止当前正在执行事务。

TiDB 常用端口

  • MySQL Procotol Port,默认 4000
    • 和 MySQL 提供一样的功能,对应用提供服务端口,用来 Input/Output 数据。
  • HTTP 控制端口,默认 10080
    • TiDB 特有的接口
      • 查询状态 schema information
      • 动态修改配置 query 级别/general log
    • Golang Pprof 端口,增加 TiDB Server 事务性能分析的诊断,复用 10080 端口。
      • Goroutines - Goroutine Count 持续涨,可能会有内存泄漏。
      • CPU/Memory
      • Blocks

TiDB Server 3.0 功能展望

  • slow query 格式日志兼容 MySQL 分析工具
  • show processlist 兼容 MySQL 监控工具
  • TiDB idea list 来激发社区用户和 Contributor 来一起完善 TiDB 集群的管理和分析工具。

延伸阅读链接

Connect Manager 机制: https://dev.mysql.com/doc/internals/en/connection-phase.html

Golang Pprof 使用:https://golang.org/pkg/net/http/pprof/

1赞

看不到图了 :slight_smile:

图片我们稍后重新传一下

图片的问题还没有解决

现在应该已经好啦

nice