1. 先说结论TDSQL到底是一套什么样的架构很多朋友第一次接触TDSQL上来就问我它跟MySQL是什么关系是不是就是MySQL加了一堆中间件。这个理解方向对了一半但远远不够。TDSQL是腾讯云推出的企业级分布式数据库兼容MySQL协议核心做的是两件事一是把数据库的扩展能力从单机边界拉出来从几千QPS拉到几十万、上百万的QPS二是在这个基础上解决分布式环境里最难搞的数据一致性、故障自动切换、在线扩容这些问题。早期它叫TDSQL后来腾讯云把TDSQL扩展成了一个完整产品家族包含TDSQL-C、TDSQL PostgreSQL版等但咱们这篇聊的是最经典的那条产品线前身可以追溯到腾讯内部的计费系统。大家知道腾讯的计费系统是那种一分钟都不能挂的业务对数据一致性要求极其苛刻。TDSQL从这种环境里长出来天然就把强同步复制、自动故障恢复这些东西当成了头等大事去设计。架构层面TDSQL的分层思路非常清晰它不是把一堆MySQL节点随便串一块儿就叫分布式而是把整个集群拆成了不同的角色——管理面、接入面、数据面、调度面每个面各干各的活。这种解耦带来了一个直接好处任何一面出问题都不会把整个集群拖下水而且每一面都能单独做水平扩展。我个人的理解是TDSQL的架构设计哲学可以概括成一句话让计算层无状态让数据层可复制让管理层可调度。这句话怎么解咱们在后面的章节里一层层拆开来看。这篇文章我会从整体架构讲到核心组件从SQL请求的完整流程讲到强同步复制和高可用切换最后再聊聊分片机制和分布式事务以及我在实际运维中踩过的坑。无论你是想评估TDSQL在当前系统落地还是已经在维护TDSQL集群的DBA还是纯粹想研究企业级分布式数据库的设计思路这篇文章应该都能给你一些有价值的参考。2. 整体架构设计与角色分工2.1 三大平面的划分逻辑TDSQL的组件多但如果先捋清角色架构就不乱了。整个集群可以分成三个大层面接入层负责承接客户端连接转发SQL请求。这是Proxy网关干的活。客户端不需要关心自己连接的是集群里哪一个具体的数据库节点统一连Proxy就行。Proxy对外暴露的是MySQL协议所以应用侧基本不用改代码JDBC串改一下MySQL驱动照样用。数据层真正存数据的节点叫数据节点DB Node。每个数据节点内部本质上是一个经过定制优化的MySQL实例再配上一套强同步复制方案。数据节点的集合用Set这个概念来管理——一个Set是一个逻辑上的分片单位一个Set内部通常是一个一主多从的MySQL高可用组。调度与管理层负责集群的配置管理、状态监控、故障判断和自动切换。这一层主要由ZooKeeper集群和OSSOperation Support System组成赤兔管理平台则是人机交互的窗口。ZooKeeper管的是元数据和集群状态共识OSS管的是调度逻辑和运维操作。这样分层的道理说来也简单如果接入、存储、调度都塞在一个组件里做扩展的时候就会互相掣肘——你要扩存储接入能力也跟着被动变你要修调度逻辑可能碰坏数据链路。分层以后每一层都能独立演化和扩展。2.2 从部署形态看架构差异TDSQL在不同部署形态下架构细节会有一些区别主要在管理面的部署密度和网络拓扑上标准版集中式一个Set单分片通常就是一套一主两从的MySQL高可用结构。管理面ZK/OSS可以跟数据节点混部适合中小业务。分布式版TBase/分布式TDSQL多个Set组成集群Proxy层负责路由和汇总全局事务管理比如全局时间戳、分布式事务协调介入。适合超大规模、高并发场景。两种形态下数据节点的高可用方案是一脉相承的区别主要在于有没有分片路由、有没有全局事务协调。2.3 元数据管理为什么选ZooKeeper分布式系统最怕的事情之一是各节点对集群当前是什么状态没有共识——比如主节点是谁哪些节点在服务配置版本是多少。扯皮久了很容易脑裂也就是两个节点都以为自己是主。ZooKeeper在这个体系里承担了这个共识中心的角色。所有的节点状态变化比如故障切换、扩容缩容、配置更新都要在ZK上留下记录。ZK本身用的是ZAB协议能保证多个节点间数据的强一致性。虽然ZK在业界有各种争议比如性能天花板、运维复杂度但在TDSQL的架构选型里ZK很好地匹配了中等规模元数据、高可靠性要求的场景。相比etcdZK的成熟度和周边生态在数据库管控领域里积累更久很多老牌分布式数据库都在用它。我在实际维护中观察到一个细节TDSQL的ZK集群一般部署3或5节点节点之间跨机架甚至跨机房分布目的就是防止单个机架掉电导致整个元数据层失联。这个问题后面在排查章节我会再讲。3. 核心组件逐个拆解Proxy、OSS、数据节点3.1 ProxySQL语句的交通警察Proxy是应用连接TDSQL的第一道关卡。很多第一次接触的同学容易产生误解是不是有了Proxy对MySQL的兼容性就得打折扣实际上TDSQL在Proxy层做了非常深的语法适配工作。Proxy本身不是代理中间件那样简简单单包一层它内置了高版本的MySQL协议解析能力常规的增删改查、预处理语句、事务控制、数据库管理命令都支持。Proxy的核心功能我整理了一份清单连接管理客户端连接资源池化一个Proxy可以撑几万个客户端连接避免大量连接直接压到数据节点上。读写分离与路由可以配置写操作走主节点读操作按权重分发到只读节点。分布式模式下还负责把SQL按分片键路由到对应的Set。安全管控拦截危险SQL、超时控制、账号权限校验。状态感知跟ZK保持心跳感知数据节点主备状态的变化。主节点切换到新节点后Proxy会自动把写流量转发到新的主。Proxy本身是无状态节点可以水平堆。需要提升接入能力加节点就行。很多用户会在Proxy前面再挂一层负载均衡比如腾讯云内的CLB进一步屏蔽Proxy故障对应用的影响。3.2 OSS系统运维操作的调度中枢OSS这个缩写容易被误解其实对应到系统里就是负责集群调度和生命周期管理的服务。创建实例、升降配、备份恢复、巡检调度、故障主从切换这些动作都是由OSS来编排执行和推进的。OSS与数据节点之间的通信走的是管理面网络跟业务数据网络是隔离的。这是TDSQL架构里很值得注意设计业务流量和管理流量分开防止运维操作影响业务链路的稳定性。赤兔管理平台是OSS的可视化门户DBA的大部分日常操作——查看实例状态、改配置、看监控、发起主备切换演练——都能在赤兔上完成。3.3 数据节点对MySQL做了哪些定制数据节点用的是深度定制的MySQL内核在MySQL社区版的基础上主要做了几方面增强强同步复制机制。普通的MySQL主从异步复制主库提交完事务不等待从库确认半同步复制只等一个从库确认。TDSQL默认的强同步方案多线程强同步在主库提交前要求事务日志在N个备机中至少M个备机落盘成功才算提交成功。这个机制带来的收益是主库宕机后从库的数据不丢达到RPO约等于0的效果。代价是如果备机确认慢主库的提交时延会被拉高。TDSQL对此做了特别优化通过并行复制和确认消息合并来降低对性能的影响。线程池。连接数非常多的时候MySQL原生的one-thread-per-connection模式很容易把CPU耗光。TDSQL把线程池技术在数据节点内部做了实现限制同时执行的活跃线程数让大量并发连接在排队等待时不至于把系统资源耗尽。企业级审计和加密。这块更多是为金融政企客户设计的包括SQL审计、透明数据加密、脱敏等能力。3.4 赤兔管理平台DBA的驾驶舱赤兔在TDSQL整个产品栈里属于锦上添花但非常关键的部分。底层系列事做得再好如果运维入口不友好客户也难用起来。赤兔提供的是集群拓扑可视化的能力一眼看到当前集群有几套Set、每个Set的主备关系、各节点的延迟指标、磁盘使用率。切换操作也在赤兔上提供了一键的入口并且支持切换预案的设定——比如切换前先做哪些检查主备切换的可用性阈值等这在金融行业对实操的合规性要求很高。4. 从一条SQL说起请求在TDSQL里的完整旅程理解了组件职责不妨模拟一条SQL请求看看它在TDSQL集群里的完整路径。假设客户端发起一条查询select * from user_info where uid 12345。第一步连接建立。应用程序通过驱动连接到Proxy。Proxy完成认证之后解析这条SQL。第二步路由决策。如果这是分布式表Proxy会根据分片键这里就是uid做哈希算出这条数据落在哪个Set。如果是单分片的标准版就直接把SQL转发给唯一的Set主节点。第三步语句执行。主节点把这条select语句在存储引擎里执行。如果是读写分离场景且这条SQL没有跨库事务、不在事务中、不是写操作Proxy可能将其路由到只读节点执行。第四步数据返回。查询结果从数据节点返回ProxyProxy再以MySQL协议报文返回客户端。整个过程看似链路不短但Proxy转发走的是内部网络延迟通常在微秒到亚毫秒级别对最终业务的整体时延影响很小。如果是写操作流程会比读多一截第一步到第三步相同。第四步主节点执行InnoDB引擎层的写操作同时要准备提交。提交动作触发强同步复制——主库把binlog或者特定格式的复制事件发给备机备机收到并写入从库的relay log且刷盘成功后返回确认。主库收到足够数量的确认后才真正向客户端返回提交成功。这个过程中如果出现主库和备机网络分区TDSQL的强同步策略会触发退化机制——为了保证可用性可以临时把强同步降级为异步等网络恢复了再重新追平数据。这个降级不是随便做的是在数据可靠性和服务可用性之间做一个权衡。这块在企业级数据库里永远都有取舍。5. 高可用、容灾与分布式事务的底层机制5.1 故障自动切换机制切换是分布式数据库最容易出问题的地方。TDSQL的切换主要由OSS/ZK协作完成大体链路是数据节点之间持续心跳通信。ZK集群发现主节点失联或者OSS收到异常监控项。OSS发起切换流程确认当前集群状态、选出数据最新的备机作为新主、通知Proxy更新路由。Proxy在老连接上主动断开应用重连后自动走新拓扑。原主节点恢复后作为新主的备机重新接入集群追平数据后回归正常。整个切换过程中影响最明显的是发现异常的耗时和选主耗时。TDSQL在异常发现的灵敏度和选主机制上做了很多参数调优。实际生产里自动切换通常在秒级到十几秒内完成具体时间取决于网络状况和监控采集周期。我建议所有使用TDSQL的团队一定要定期做切换演练而不是只在故障真实发生时被动应对。切换不是大姑娘上轿第一次就会的需要把预案提前在测试环境反复演练。5.2 强同步与异步之间的动态漂移在实际运维中强同步复制并不会永远保持强同步状态。当备机延迟过大、或者网络抖动导致确认超时时为了保证业务连续性TDSQL可能临时把对应节点的复制模式降级。这个降级动作从高可用角度是合理的但值得注意对RPO的冲击。如果这个时间段主库物理损坏且备份不可用理论上可能丢失故障前一段时间的数据。所以对于RPO极其敏感的业务比如支付交易监控上要特别重视强同步率的波动。实操中我会建议用以下指标来盯主备之间延迟的秒数通常要求接近0强同步复制的开启状态是否持续为YES备机的relay log积压量5.3 分布式事务与全局一致性分布式版TDSQL下一个事务如果跨多个Set比如转账场景里一个账户数据在Set1另一个账户在Set2那就要用到分布式事务能力。TDSQL的分布式事务方案本质上是两阶段提交2PC的思路——协调者先把事务请求发给各个分片各分片执行prepare全部成功后协调者通知commit。同时TDSQL优化了全局时间戳策略保证跨节点的事务时间戳全局有序从而让分布式事务的读已提交级别有全局一致性视图。这个机制的学习路径上有个常见的坑很多开发者在写分布式事务里的业务逻辑时潜意识里还按照单机MySQL的隔离级别去揣测行为认为RC级别下读到的都是最新值。分布式环境即使事务已经提交如果一致性级别没有要求读到旧数据在特定时刻是有可能的。真正确保严格一致的方式是使用强一致读比如指定主节点编写路由或者调整一致性设置但会带来性能开销。这块需要架构师根据业务场景做权衡。5.4 容灾体系与多活设计TDSQL支持同城双活、两地三中心等典型的容灾架构。实现方式是跨机房部署数据节点的主备分布在不同的可用区或物理机房依靠强同步复制保障RPO≈0配合OSS的调度实现机房间的切换。如果要做到异地灾备可以在主集群和灾备集群间开启基于binlog的异步复制一般RPO在秒级以下。这种时候一般不追求严格零丢失因为异地之间的网络延迟太大强同步会影响业务。6. 常见问题与排查技巧实录6.1 强同步退化不感知我接过一个客户案例他们TDSQL集群的磁盘高水位导致备机刷盘变慢强同步频繁超时系统自动降级成了异步复制。结果那段时间主库发生了物理故障重启后因为异步复制少量已提交事务没来得及同步最后靠备份找回了一部分数据。排查要点在赤兔和监控系统里重点看强同步开启状态的变化曲线。如果发现强同步状态频繁在YES和NO之间跳变说明系统正在反复触发降级和恢复机制要排查网络抖动和磁盘延迟。6.2 Proxy连接数被打满有些业务初期只接了少数几个Proxy做了集中部署。大促时流量暴涨Proxy连接数很快耗尽应用侧开始报无法获取连接。排查要点看Proxy所在主机的文件描述符限制、线程池活跃数、网络连接队列长度。解决上首先确认连接池参数优化应用侧到Proxy的连接不必要建太多其次就是横向扩Proxy节点。TDSQL的Proxy节点支持无状态扩容这个能力要靠预先评估别等故障变严重了再扩。6.3 跨Set查询性能差分布式表设计时开发经常忽略分片键选择的重要性。有客户把所有数据默认用主键做分片结果业务里的热点查询都按用户ID来导致查询全部变成了跨Set的汇总查询性能惨不忍睹。排查要点业务建模阶段就要确定高频查询维度把分片键尽量贴近这个维度。要是分片键实在没法选好也可以通过冗余表或者反范式化的方式在多个Set上都冗余一份高频查询所需的数据通过本地路由来规避跨Set查询。TDSQL也支持全局表和广播表适合那种全量数据量不大、但几乎所有分片都要用的维表。这个功能是我最推荐的分布式表设计三板斧之一——分片表、全局表、广播表要根据业务查询特征灵活组合而不是一律分片。设计组合适用场景查询特征设计建议分片表数据量大、维度集中按分片键查询热点高分片键选业务主维度全局表数据量小、频繁关联对维表做关联查询数据冗余到全部分片广播表小维表、配置类数据所有节点需要同步读取修改频率低时更适用6.4 ZK集群异常导致集群假死有一次线上运维发现整个TDSQL集群的数据节点和Proxy都失联了但从网络上看数据节点之间还是存活的。后来定位到是ZK集群所在的几个节点发生了资源争抢导致ZK服务频繁同步超时整个集群的元数据视图出现问题。经验是ZK所在的机器要跟业务节点资源隔离不要混部ZK的JVM堆内存要和节点数量匹配避免频繁FullGC。同时监控上要关注ZK的follower和leader之间的同步延迟这个指标通常能在问题爆发前提前预警。6.5 日常巡检建议清单这算是经验总结吧我一般会建议客户至少做到以下几条每天看一遍集群巡检报告重点关注强同步状态、主备延迟、磁盘增长趋势。每周做一次主备切换演练在测试环境做把生产预案的每一个步骤都跑一遍。每月梳理一次容量和性能趋势特别关注Proxy和ZooKeeper的CPU、内存使用率。每一次变更前做性能基准测试别在生产环境直接调参数。7. 最后分享一点使用心得TDSQL不是那种拿来就能直接跑得特别完美的产品它跟任何成熟的企业级数据库一样需要DBA和架构师去理解设计哲学才能发挥最大价值。我最大的体会是架构决定上限细节决定下限。TDSQL把基础的高可用、分布式路由、强一致这些框架搭得很完整但最终能不能稳定运行仍然取决于你在分片键选择、连接池规划、监控告警配置、容灾预案演练上下了多少功夫。如果团队要从零开始上TDSQL我会建议先做小范围业务试点把切换、扩容、备份恢复这些操作在非核心业务上趟熟再逐步扩大规模。数据库切到分布式架构真正难的从来不是装好软件而是把运维习惯和业务设计模式一起升级到分布式的思维方式上。