假如您有一个应用程序,随着业务越来越有起色,系统所牵涉到的数据量也 就越来越大,此时您要涉及到对系统进行伸缩(Scale)的问题了。一种典型的 扩展方法叫做“向上伸缩(Scale Up)”,它的意思是通过使用更好的硬件来提 高系统的性能参数。而另一种方法则叫做“向外伸缩(Scale Out)”,它是指 通过增加额外的硬件(如服务器)来达到相同的效果。从“硬件成本”还是“系 统极限”的角度来说,“向外伸缩”一般都会优于“向上伸缩”,因此大部分上 规模的系统都会在一定程度上考虑“向外”的方式。由于许多系统的瓶颈都处在 数据存储上,因此一种叫做“数据分片(Database Sharding)”的数据架构方 式应运而生,本文便会讨论这种数据架构方式的一种比较典型的实现方式。
简介
数据分片,自然便是将整体数据分摊在多个存储设备(下文统称为“数据分 区”或“分区”)上,这样每个存储设备的数据量相对就会小很多,以此满足系 统的性能需求。值得注意的是,系统分片的策略有很多,例如常见的有以下几种 :
根据ID特征:例如对记录的ID取模,得到的结果是几,那么这条记录就放在 编号为几的数据分区上。
根据时间范围:例如前100万个用户数据在第1个分区中,第二个100万用户数 据放在第2个分区中。
基于检索表:根据ID先去一个表内找到它所在的分区,然后再去目标分区进 行查找。
……
在这些数据分片策略之中没有哪个有绝对的优势,选择哪种策略完全是根据 系统的业务或是数据特征来确定的。值得强调的是:数据分片不是银弹,它对系 统的性能和伸缩性(Scalability)带来一定好处的同时,也会对系统开发带来 许多复杂度。例如,有两条记录分别处在不同的服务器上,那么如果有一个业务 是为它们建立一个“关联”,那么很可能表示“关联”的记录就必须在两个分区 内各放一条。另外,如果您重视数据的完整性,那么跨数据分区的事务又立即变 成了性能杀手。最后,如果有一些需要进行全局查找的业务,光有数据分片策略 也很难对系统性能带来什么优势。
数据分片虽然重要,但在使用之前一定要三思而后行。一旦踏上这艘贼船, 往往不成功便成仁,很难回头。在我的经验里,一个滥用数据分片策略而事倍功 半的项目给我留下了非常深刻的印象(当然也有成功的啦),因此目前我对待数 据分片策略变得愈发谨慎。
那么现在,我们便来讨论一种比较常见的数据分片策略。
策略描述
这里我先描述一个极其简单的业务:
系统中有用户,用户可以发表文章,文章会有评论
可以根据用户查找文章
可以根据文章查找评论
那么,如果我要对这样一个系统进行数据分片又该怎么做呢?这里我们可以 使用上面提到的第一种方式,即对记录的ID取模,并根据结果选择数据所在的分 区。根据后两条业务中描述的查询要求,我们会为分区策略补充这样的规则:
某个用户的所有文章,与这个用户处在同一数据分区内。
某篇文章的所有评论,与这篇文章处在用一数据分区内。
您可能会说,似乎只要保证“相同用户文章在同一个数据分区内”就行了, 不是吗?没错,不过我这里让文章和用户在同一个分区内,也是为了方便许多额 外的操作(例如在关系数据库中进行连接)。那么假设我们有4个数据分区,那 么它们内部的条目可能便是:
分区0 | 分区1 |
User 4 Article 8 Article 12 Comment 4 Comment 16 User 12 Article 4 |
User 1 Article 5 Article 9 Comment 13 Comment 17 User 5 Article 13 |
分区2 | 分区3 |
User 2 Article 10 Article 14 Comment 6 Comment 10 User 10 Article 4 |
User 7 Article 7 Article 11 Comment 3 Comment 15 User 11 Article 4 |