Skip to content

Commit

Permalink
fix: update lint (#609)
Browse files Browse the repository at this point in the history
* fix: update lint

* fix: update lint

* fix: update link format
  • Loading branch information
YiniXu9506 authored Sep 26, 2021
1 parent e2d9ad2 commit c461120
Show file tree
Hide file tree
Showing 311 changed files with 1,413 additions and 1,893 deletions.
4 changes: 2 additions & 2 deletions .github/markdownlint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ heading-style:
style: atx

# MD010
no-hard-tabs: true
no-hard-tabs: false

# MD012
no-multiple-blanks: true
Expand Down Expand Up @@ -58,7 +58,7 @@ no-space-in-links: true
no-empty-links: true

# MD045
no-alt-text: true
no-alt-text: false

# MD046
code-block-style:
Expand Down
21 changes: 9 additions & 12 deletions 10-questions-tidb-structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ tags: ['TiDB','架构']

>“我希望能够把 TiDB 的设计的一些理念能够更好的传达给大家,相信大家理解了背后原因后,就能够把 TiDB 用的更好。”

做 TiDB 的缘起是从思考一个问题开始的:为什么在数据库领域有这么多永远也躲不开的坑?从 2015 年我们写下第一行代码,3 年以来我们迎面遇到无数个问题,一边思考一边做,尽量用最小的代价来快速奔跑。

作为一个开源项目,TiDB 是我们基础架构工程师和社区一起努力的结果,TiDB 已经发版到 2.0,有了一个比较稳定的形态,大量在生产环境使用的伙伴们。可以负责任的说,我们做的任何决定都经过了非常慎重的思考和实践,是经过内部和社区一起论证产生的结果。它未必是最好的,但是在这个阶段应该是最适合我们的,而且大家也可以看到 TiDB 在快速迭代进化。
Expand All @@ -19,22 +18,21 @@ tags: ['TiDB','架构']

## 一、为什么分布式系统并不是银弹

其实并没有什么技术是完美和包治百病的,在存储领域更是如此,如果你的数据能够在一个 MySQL 装下并且服务器的压力不大,或者对复杂查询性能要求不高,其实分布式数据库并不是一个特别好的选择。 选用分布式的架构就意味着引入额外的维护成本,而且这个成本对于特别小的业务来说是不太划算的,即使你说需要高可用的能力,那 MySQL 的主从复制 + GTID 的方案可能也基本够用,这不够的话,还有最近引入的 Group Replication。而且 MySQL 的社区足够庞大,你能 Google 找到几乎一切常见问题的答案。
其实并没有什么技术是完美和包治百病的,在存储领域更是如此,如果你的数据能够在一个 MySQL 装下并且服务器的压力不大,或者对复杂查询性能要求不高,其实分布式数据库并不是一个特别好的选择。 选用分布式的架构就意味着引入额外的维护成本,而且这个成本对于特别小的业务来说是不太划算的,即使你说需要高可用的能力,那 MySQL 的主从复制 + GTID 的方案可能也基本够用,这不够的话,还有最近引入的 Group Replication。而且 MySQL 的社区足够庞大,你能 Google 找到几乎一切常见问题的答案。

**我们做 TiDB 的初衷并不是想要在小数据量下取代 MySQL,而是尝试去解决基于单机数据库解决不了的一些本质的问题。**

有很多朋友问我选择分布式数据库的一个比较合适的时机是什么?我觉得对于每个公司或者每个业务都不太一样,我并不希望一刀切的给个普适的标准(也可能这个标准并不存在),但是有一些事件开始出现的时候:比如是当你发现你的数据库已经到了你每天开始绞尽脑汁思考数据备份迁移扩容,开始隔三差五的想着优化存储空间和复杂的慢查询,或者你开始不自觉的调研数据库中间件方案时,或者人肉在代码里面做 sharding 的时候,这时给自己提个醒,看看 TiDB 是否能够帮助你,我相信大多数时候应该是可以的。
有很多朋友问我选择分布式数据库的一个比较合适的时机是什么?我觉得对于每个公司或者每个业务都不太一样,我并不希望一刀切的给个普适的标准(也可能这个标准并不存在),但是有一些事件开始出现的时候:比如是当你发现你的数据库已经到了你每天开始绞尽脑汁思考数据备份迁移扩容,开始隔三差五的想着优化存储空间和复杂的慢查询,或者你开始不自觉的调研数据库中间件方案时,或者人肉在代码里面做 sharding 的时候,这时给自己提个醒,看看 TiDB 是否能够帮助你,我相信大多数时候应该是可以的。

而且另一方面,选择 TiDB 和选择 MySQL 并不是一刀切的有你没他的过程,我们为了能让 MySQL 的用户尽可能减小迁移和改造成本,做了大量的工具能让整个数据迁移和灰度上线变得平滑,甚至从 TiDB 无缝的迁移回来,而且有些小数据量的业务你仍然可以继续使用 MySQL。**所以一开始如果你的业务和数据量还小,大胆放心的用 MySQL 吧,MySQL still rocks,TiDB 在未来等你。**


## 二、为什么是 MySQL

和上面提到的一样,并不是 MySQL 不好我们要取代他,而是选择兼容 MySQL 的生态对我们来说是最贴近用户实际场景的选择:

1. MySQL 的社区足够大,有着特别良好的群众基础,作为一个新的数据库来说,如果需要用户去学习一套新的语法,同时伴随很重的业务迁移的话,是很不利于新项目冷启动的。
1. MySQL 的社区足够大,有着特别良好的群众基础,作为一个新的数据库来说,如果需要用户去学习一套新的语法,同时伴随很重的业务迁移的话,是很不利于新项目冷启动的。

2. MySQL 那么长时间积累下来大量的测试用例和各种依赖 MySQL 的第三方框架和工具的测试用例是我们一个很重要的测试资源,特别是在早期,你如何证明你的数据库是对的,MySQL 的测试就是我们的一把尺子。
2. MySQL 那么长时间积累下来大量的测试用例和各种依赖 MySQL 的第三方框架和工具的测试用例是我们一个很重要的测试资源,特别是在早期,你如何证明你的数据库是对的,MySQL 的测试就是我们的一把尺子。

3. 已经有大量的已有业务正在使用 MySQL,同时也遇到了扩展性的问题,如果放弃这部分有直接痛点的场景和用户,也是不明智的。

Expand All @@ -44,13 +42,13 @@ tags: ['TiDB','架构']

一个显而易见的原因是对运维的友好性。很多人觉得这个地方稍微有点反直觉,多一个组件不就会增加部署的复杂度吗?

其实在实际生产环境中,运维并不仅仅包含部署。举个例子,如果在 SQL 层发现了一个 BUG 需要紧急的更新,如果所有部件都是耦合在一起的话,你面临的就是一次整个集群的滚动更新,如果分层得当的话,你可能需要的只是更新无状态的 SQL 层,反之亦然。
其实在实际生产环境中,运维并不仅仅包含部署。举个例子,如果在 SQL 层发现了一个 BUG 需要紧急的更新,如果所有部件都是耦合在一起的话,你面临的就是一次整个集群的滚动更新,如果分层得当的话,你可能需要的只是更新无状态的 SQL 层,反之亦然。

另外一个更深层次的原因是成本。存储和 SQL 所依赖的计算资源是不一样的,存储会依赖 IO,而计算对 CPU 以及内存的要求会更高,无需配置 PCIe/NVMe/Optane 等磁盘,而且这两者是不一定对等的,如果全部耦合在一起的话,对于资源调度是不友好的。 对于 TiDB 来说,目标定位是支持 HTAP,即 OLTP 和 OLAP 需要在同一个系统内部完成。显然,不同的 workload 即使对于 SQL 层的物理资源需求也是不一样的,OLAP 请求更多的是吞吐偏好型以及长 query,部分请求会占用大量内存,而 OLTP 面向的是短平快的请求,优化的是延迟和 OPS (operation per second),在 TiDB 中 SQL 层是无状态的,所以你可以将不同的 workload 定向到不同的物理资源上做到隔离。**还是那句话,对调度器友好,同时调度期的升级也不需要把整个集群全部升级一遍。**

另一方面,底层存储使用 KV 对数据进行抽象,是一个更加灵活的选择。

一个好处是简单。对于 Scale-out 的需求,对 KV 键值对进行分片的难度远小于对带有复杂的表结构的结构化数据,另外,存储层抽象出来后也可以给计算带来新的选择,比如可以对接其他的计算引擎,和 TiDB SQL 层同时平行使用,TiSpark 就是一个很好的例子。
一个好处是简单。对于 Scale-out 的需求,对 KV 键值对进行分片的难度远小于对带有复杂的表结构的结构化数据,另外,存储层抽象出来后也可以给计算带来新的选择,比如可以对接其他的计算引擎,和 TiDB SQL 层同时平行使用,TiSpark 就是一个很好的例子。

从开发角度来说,这个拆分带来的灵活度还体现在可以选择不同的编程语言来开发。对于无状态的计算层来说,我们选择了 Go 这样开发效率极高的语言,而对于存储层项目 TiKV 来说,是更贴近系统底层,对于性能更加敏感,所以我们选择了 Rust,如果所有组件都耦合在一起很难进行这样的按需多语言的开发,对于开发团队而言,也可以实现专业的人干专业的事情,存储引擎的开发者和 SQL 优化器的开发者能够并行的开发。 另外对于分布式系统来说,所有的通信几乎都是 RPC,所以更明确的分层是一个很自然的而且代价不大的选择。

Expand Down Expand Up @@ -94,9 +92,9 @@ Hash-based 的问题是实现有序的 Scan API 会比较困难,我们的目

* 静态分片对于根据 workload 实时调度是不友好的,例如如果数据存在访问热点,系统需要能够快速进行数据迁移以便于将热点分散在不同的物理服务商上。

回到刚才提到的基于 Range 分片的问题,刚才我说过,对于顺序写入热点的问题确实存在,但也不是不可解。对于大压力的顺序写入的场景大多数是日志或者类似的场景,这类场景的典型特点是读写比悬殊(读 << 写),几乎没有 Update 和随机删除,针对这种场景,写入压力其实可以通过 Partition Table 解决,这个已经在 TiDB 的开发路线图里面,今年之内会和大家见面。
回到刚才提到的基于 Range 分片的问题,刚才我说过,对于顺序写入热点的问题确实存在,但也不是不可解。对于大压力的顺序写入的场景大多数是日志或者类似的场景,这类场景的典型特点是读写比悬殊(读 << 写),几乎没有 Update 和随机删除,针对这种场景,写入压力其实可以通过 Partition Table 解决,这个已经在 TiDB 的开发路线图里面,今年之内会和大家见面。

另外还有一个频繁读写小表造成的热点问题。这个原因是,在底层,TiDB 的数据调度的最小单位是 Region,也就是一段段按字节序排序的键值 Key-Value Pairs (默认大小 96M),假设如果一个小表,总大小连 96M 都不到,访问还特别频繁,按照目前的机制,如果不强制的手动 Split,调度系统无论将这块数据调度到什么位置,新的位置都会出现热点,所以这个问题本质上是无解的。因此建议如果有类似的访问 pattern,尽可能的将通用的小表放到 Redis 之类的内存缓存中,或者甚至直接放在业务服务的内存里面(反正小)。
另外还有一个频繁读写小表造成的热点问题。这个原因是,在底层,TiDB 的数据调度的最小单位是 Region,也就是一段段按字节序排序的键值 Key-Value Pairs (默认大小 96M),假设如果一个小表,总大小连 96M 都不到,访问还特别频繁,按照目前的机制,如果不强制的手动 Split,调度系统无论将这块数据调度到什么位置,新的位置都会出现热点,所以这个问题本质上是无解的。因此建议如果有类似的访问 pattern,尽可能的将通用的小表放到 Redis 之类的内存缓存中,或者甚至直接放在业务服务的内存里面(反正小)。

## 八、为什么性能(延迟)不是唯一的评价标准

Expand All @@ -106,7 +104,6 @@ Hash-based 的问题是实现有序的 Scan API 会比较困难,我们的目

**我们公司内部有一句话:Make it right before making it fast。正确性和可靠性的位置是在性能之前的,毕竟在一个不稳定的系统上谈性能是没有意义的。**


## 九、为什么弹性伸缩能力如此重要

在业务初期,数据量不大,业务流量和压力不大的时候,基本随便什么数据库都能够搞定,但很多时候业务的爆发性增长可能是没有办法预期的,特别是一些 ToC 端的应用。早期的 Twitter 用户一定对时不时的大鲸鱼(服务不可用)深恶痛绝,近一点还有前两年有一段时间爆红的足记 App,很短的时间之内业务和数据量爆发性增长,数据库几乎是所有这些案例中的核心瓶颈。 很多互联网的 DBA 和年轻的架构师会低估重构业务代码带来的隐形成本,在业务早期快速搞定功能和需求是最重要的。想象一下,业务快速增长,服务器每天都因为数据库过载停止服务的时候,DBA 告诉你没办法,先让你重新去把你的业务全改写成分库分表的形式,在代码里到处加 Sharding key,牺牲一切非 Sharding key 的多维关联查询和相关的跨 Shard 的强一致事务,然后数据复制好多份……这种时候是真正的时间等于金钱,决定这个公司生死存亡的时候不是去写业务和功能代码,而是因为基础设施的限制被迫重构,其实是非常不好的。 如果这个时候,有一个方案,能够让你几乎无成本的,不修改业务代码的时候对数据库吞吐进行线性扩展(无脑加机器其实是最便宜的),最关键的是为了业务的进化争取了时间,我相信这个选择其实一点都不难做。
Expand All @@ -121,4 +118,4 @@ Hash-based 的问题是实现有序的 Scan API 会比较困难,我们的目

TiDB 是一个通用的数据库,甚至希望比一般的数据库更加通用,TiDB 是很早就尝试融合 OLTP 和 OLAP 的边界的数据库产品,我们是最早将 HTAP 这个概念从实验室和论文里带到现实的产品之一。这类通用基础软件面临的一个问题就是我们在早期其实很难去指导垂直行业的用户把 TiDB 用好,毕竟各自领域都有各自的使用场景和特点,TiDB 的开发团队的背景大部分是互联网行业,所以天然的会对互联网领域的架构和场景更熟悉,但是比如在金融,游戏,电商,传统制造业这些行业里其实我们不是专家,不过现在都已经有很多的行业专家和开发者已经能将 TiDB 在各自领域用得很好。

**我们的 Blog,公众号,官网等平台会作为一个案例分享的中心,欢迎各位正在使用 TiDB 的用户,将你们的思考和使用经验分享给我们,就像现在已有案例背后的许多公司一样,我们会将你们的经验变成一篇篇的用户案例,通过我们的平台分享给其他的正在选型的公司。**
**我们的 Blog,公众号,官网等平台会作为一个案例分享的中心,欢迎各位正在使用 TiDB 的用户,将你们的思考和使用经验分享给我们,就像现在已有案例背后的许多公司一样,我们会将你们的经验变成一篇篇的用户案例,通过我们的平台分享给其他的正在选型的公司。**
Loading

0 comments on commit c461120

Please sign in to comment.