TiCI 上线过程

记录了 TiCI 上线过程中遇到的一些问题:

  • 针对这些问题的技术性解法和运维性的解法
    涉及到某些内部知识的将不予公开。
  • 对于问题严重程度应该如何判断
  • 如何为了达成上线的既定目标,设计临时性的缓解措施

POC on TiDB-X for Customer U, late Nov 2025

主要问题

  1. 支持 Keyspace
  2. 运维手段
    包含 Shard、Reader 和 Importer
  3. 支持 Security
  4. openssl 的编译问题
  5. arm 编译的问题
  6. 上线后出现的影响可用性的 bug
  7. 上线后出现的影响性能的 bug

Nov 21

讨论 import into 场景下,如果某个 worker 因为 OOM 重启,则因为目前缺少 Heartbeat 机制和 reschedule 机制,整个任务会因为这个小任务失败而停止。

另外,也提到了和 import into 流控相关的问题。

Nov 23

遇到了 tokio Sender 报错 channel closed 问题。当时没有空查。

这个问题实际上就是协程因为哪里 unwrap 而 panic 了,而因为协程池是跑的消息循环,所以 panic 了不 join 也不知道。一直没找到是哪里,后来我加了点 panic hook,才在 Nov 30 定位到是服务发现的问题。

Nov 26

  1. TLS options are only supported with HTTPS URLs
    这个错误很 plain
  2. Client had asked for TLS connection but TLS support is disabled. Please enable one of the following features: [“native-tls-tls”, “rusttls-tls”]
    我们不能用 native,只能用内置的 rusttls
  3. undefined symbol: pthread_atfork
    ARM 上的编译问题,有专门文章介绍
  4. TLS error error:0A000086
    这个就是要启动的时候指定下用 ring 还是 aws_lc_rs

Nov 27

  1. 排查 ARM 上的问题,这里做了两套方案,先设法用 x86 跑起来。这证明也是正确的,白天我们发现了更多的问题,最终因为 TLS 的问题也没有跑起来。但是晚上我们把 ARM 验证了下,发现不报原先的错了。
  2. 遇到一个新问题是我们的云上 operator 机制不支持改参数,我们挂的又是 ro 文件系统,导致很难验证
  3. etcd client unavailable or unhealthy, attempting reconnect
    这个是 kebab-case 的锅,Rust 和 C++ 的格式不一样,写配置的同学把 ca-path 写成 ca_path 了。
  4. 后来发现,TiFlash CN 还是绕不开 TLS 的问题。所以还是得兼容。

Nov 28

  1. get meta channel failed times
    这个错误还是 etcd client 的 ca-path 没传对
  2. 到这里为止,整体看上去能跑了,但是查询报错,看日志感觉核心服务没起来
    首先 lsof 看了一下,发现服务器都没起来。
    因为没有 panic,直觉是哪里有个报错死在协程里面没传播出去。进而发现是 rust 的 grpc server 不能在 dns 格式的 url 上启动。不得不说我几天前的 advertise_addr 的改动很有先见之明 https://github.com/pingcap-inc/tici/pull/515

Nov 29

  1. 白天是在 import into 导入数据,晚上出现了一堆问题。
  2. 首先,是之前的那个 panic 导致协程退出的阴魂不散又来了。我紧急去掉了一堆 unwrap,并且加了 panic hook 打印错误日志。
  3. 然后,是 writer 那边没有对 meta 返回的错误码进行处理,但是加上了处理之后,一个集成测试不通过了。大家觉得要不就把这个测试禁用了吧,但是我很反对,因为这个测试是唯一一个带上真实的 worker 和 reader 跑完 e2e 的测试。并且我看了日志发现一个 writer node 被超时移出了,所以尽管 pr owner 认为他并没有改动到这一块的逻辑,我仍然认为他的修改导致一个严重问题暴露了。因此,我们应该先查问题。原因是即使我们强行合并了,也不能拿这个 commit 去跑生产。后来,确实发现了是在处理 heartbeat 的时候会等待一个异步任务结束,所以导致后面 heartbeat 消息循环直接卡死了。所以,这个问题确实会导致 writer 因为丢失心跳从而被全不 failover,进而整个集群没有 writer 可用的 critical 问题。不 approve 这个 PR 是完全正确的。

Nov 30

今天主要切换到性能方面的支持上:

  • warmup 的速度太慢了,所以想把这一块改成并发执行
    在这个处理之后,8 个节点,24 个并发,大概是不到两个小时就处理完毕了。
  • 因为 worker 出现了异常重启,导致重启后 meta 向它发送了大量的 add shard message,导致触发了 grpc 的消息大小上限。临时通过增加上限来 workaround 了。实际上是可以通过拆成多个 heartbeat response 来解决。另外同事也提到,可以只发部分信息,其他的后续让主动请求,但这个可能会产生很多的 grpc 调用。

Dec 1

  • 发现查询速度比较低,原因是串行访问的所有 shard

Dec 2

  • 发现查询并发比较低,原因是查询的 filter 不能通过主键进行过滤,所以导致每次查询需要访问所有的 shard

Dec 3

  • 关于昨天的并发问题,认为一个 shard 中有多个 fragment,并且一个 fragment 中又有多个 segment,因此会影响查询的速度。通过 Manual compaction 和调大内存的方式,使得 fragment 和 segment 都变少。
  • 因为目前没有自动 balance 机制,所以还需要 Manual reschedule。

Dec 5

功能侧:

  • 主要处理 duplicate fragment 的问题。我认为因为 apply compaction 需要根据 frag path 来定位,重名的 frag 会导致问题,所以应该由 meta 来禁用。

测试侧:

  • 执行了 Compaction,并且后续自动执行了 Merge,发现查询 QPS 提高了 50%,但依然是比较差的
  • 因此决定用 (token0_address, ts) 作为新的主键,和 TiKV 解耦

Dec 6

这一轮测试发现调整了新的主键之后,QPS 增加了很多,可以看出列存中使用不同的 Sharding key 的重要性: