写点什么

TiDB 如何做到无限扩展和保证节点 id 唯一

  • 2022 年 7 月 11 日
  • 本文字数:2366 字

    阅读完需:约 8 分钟

原文来源:https://tidb.net/blog/81f11679


【是否原创】否


【作者】 @seiang


【首发渠道链接】http://www.seiang.com/?p=1179


相信大家对 TiDB 已经很熟悉了,但是很多人觉得他是分布式数据库,自己的业务是使用 mysql,基本使用不上这个技术,可能不会去了解他或不会去深入了解。最近一个月,基于实际业务的应用场景,从测试环境测试基础学习,到生产环境性能压测、高可用测试、故障测试等的学习,到今天 TiDB 终于完成了线上业务的承接使命,而这一切只是开始,而非终点。


经过这一个月的学习,发现 TiDB 这些原理其实不仅仅局限于分布式数据库这一块,很多技术都是通用的,所以在这里写一下分享一下学习 TiDB 的一些心得。当然还有更深层次的东西需要后续慢慢的打磨。


先说说为什么选择 TiDB 吧,一般来说在咱们的业务中都是使用的 mysql, 但是单机数据库容量和并发性能都有限,对于一些大容量或者高并发的场景我们会选择 mycat 去做,使用 mycat 的确解决了问题但是增加了开发难度,开发需要对每一个表都设置分表 key,并且每个查询都得带入这个 key 的值,这样就增加了查询限制,如果不带 key 的值就得所有库表都得查询一次才行,效率极低,而且也无法满足 AP 的业务场景。随着核心业务的逐步从 SQL Server 迁移到 MySQL,怎么解决这个问题呢?经过对开源数据库对比测试,最终选择了 TiDB。


经过一个月左右的对 TiDB 的学习,总体感觉,学习成本其实相对来说还是蛮高的,但是不得不说的是,TiDB 的官方文档及社区非常的棒,TiDB 文档是我见过做得算是比较顶级的文档了,可以说不叫做文档,其实是一个文章知识库,对新手学习来说,还是比较方便的;


在 TiDB 学习前,对 TiDB 总是会有很多的疑问:


TiDB 如何保证无限扩展?因为平时使用的大多都是 mycat 的技术,这种其实无限扩展是比较麻烦的

如何保证 id 唯一,分布式数据库往往会进行分片,在单机数据库中的自增 id 就不成立,TiDB 是如何保证的呢?

TiDB 是如何保证事务的呢?

TiDB 数据库是如何存储的?为什么即适用于 TP 场景又适用于 AP 场景?


带着这些问题,先来看看 TiDB 的架构,下面是官方的给出的架构图:



TiDB 其实是典型的计算分离的架构


TiDB Server :计算层,对外暴露协议的连接端口,负责管理客户端的连接,主要做的就是执行 SQL 解析以及优化,生成分布式执行计划,由于这里是计算层是没有状态的,所以是可以无限扩展。

PD Server :PD 是整个集群的大脑,负责存储每个 TiKV 节点实时的数据分布情况和集群的整体拓扑结构,提供 TiDB Dashboard 管控界面,需要保持高可用。

TiKV: k-v 存储引擎,在 tikv 内部,存储数据的基本单位是 Region。

Tiflash :这个是用于列式的存储引擎,类似与 Clickhouse

TiDB 如何做到扩展?

首先我们来看看计算层: tidb-server,刚才说过在计算层中,是无状态的,所以就可以进行无限扩展,如果你的场景并发度很高或者数据库连接很多,可以考虑多扩展 tidb-server。


然后我们来看看存储层,作为保存数据的系统,首先要决定的是数据的存储模型,也就是数据以什么样的形式保存下来。TiKV 的选择是 Key-Value 模型,并且提供有序遍历方法。在每个 tikv 上会划分出多个 Region, 这个也就是我们的基本存储单位;


任何持久化的存储引擎,数据终归要保存在磁盘上,TiKV 也不例外。但是 TiKV 没有选择直接向磁盘上写数据,而是把数据保存在 RocksDB 中,具体的数据落地由 RocksDB 负责。这个选择的原因是开发一个单机存储引擎工作量很大,特别是要做一个高性能的单机引擎,需要做各种细致的优化,而 RocksDB 是由 Facebook 开源的一个非常优秀的单机 KV 存储引擎,可以满足 TiKV 对单机引擎的各种要求。这里可以简单的认为 RocksDB 是一个单机的持久化 Key-Value Map。


TiKV 利用 Raft 来做数据复制,每个数据变更都会落地为一条 Raft 日志,通过 Raft 的日志复制功能,将数据安全可靠地同步到复制组的每一个节点中。不过在实际写入中,根据 Raft 的协议,只需要同步复制到多数节点,即可安全地认为数据写入成功。



总结一下,通过单机的 RocksDB,TiKV 可以将数据快速地存储在磁盘上;通过 Raft,将数据复制到多台机器上,以防单机失效。数据的写入是通过 Raft 这一层的接口写入,而不是直接写 RocksDB。通过实现 Raft,TiKV 变成了一个分布式的 Key-Value 存储,少数几台机器宕机也能通过原生的 Raft 协议自动把副本补全,可以做到对业务无感知。


所以对于 TiDB 来说无论是存储层还是计算层,我们都可以无限扩展。

TiDB 如何保证节点 id 唯一?

在 mysql 中我们可以对于主键直接设置 AUTO_INCREMENT 来达到自增列的效果,mysql 是怎么做到自增的呢?


在 MySQL5.7 及之前的版本:InnoDB 引擎的自增值,自增值保存在内存里,并没有持久化。每次重启后,第一次打开表的时候,都会去找自增值的最大值 max(id),然后将 max(id)+ 步长作为这个表当前的自增值。

在 MySQL8.0 版本:将自增值的变更记录在了 redo log 中,重启的时候依靠 redo log 恢复重启之前的值。


在 TiDB 中同样支持 AUTO_INCREMENT,不能保证严格递增,只能保证趋势递增,具体原理是:对于每一个自增列,都使用一个全局可见的键值对用于记录当前已分配的最大 ID。由于分布式环境下的节点通信存在一定开销,为了避免写请求放大的问题,每个 TiDB 节点在分配 ID 时,都申请一段 ID 作为缓存,用完之后再去取下一段,而不是每次分配都向存储节点申请。


TiDB 还支持 AUTO_RANDOM,可以用于解决大批量写数据入 TiDB 时因含有整型自增主键列的表而产生的热点问题。因为 region 是有序的如果一段时间大量有序的数据产生有可能会在同一个 region 上,所以我们可以使用 AUTO_RANDOM 来将我们的主键数据打散。


好了,今天就先聊这些吧,后面会陆分享一些 TiDB 相关管理的内容,包括从 TiDB 生产集群部署到性能压测、高可用、运维等常见问题;


也欢迎关注作者的微信公众号:



用户头像

TiDB 社区官网:https://tidb.net/ 2021.12.15 加入

TiDB 社区干货传送门是由 TiDB 社区中布道师组委会自发组织的 TiDB 社区优质内容对外宣布的栏目,旨在加深 TiDBer 之间的交流和学习。一起构建有爱、互助、共创共建的 TiDB 社区 https://tidb.net/

评论

发布
暂无评论
TiDB 如何做到无限扩展和保证节点 id 唯一_TiDB 底层架构_TiDB 社区干货传送门_InfoQ写作社区