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