个人其它平台技术文章:
-
知乎ID:砖一块一块搬 -
小红书ID:码农有道
现在的大型系统在为大量用户提供服务时常常需要处理海量数据,为了应对这种挑战,工程师们通常会采用将数据“拆开”或“复制”的策略,这样既能分散压力,也能提高系统的可用性。
在这些策略中,有三个概念最为常见:分区(partitioning)、分片(sharding) 和 复制(replication)。它们听起来很相似,因为都涉及把数据分布到多台机器或多个存储位置上,但它们的实际含义和应用场景并不完全一样。
接下来,本文会用通俗的语言,结合生活中的类比(比如图书馆、披萨外卖、超市)来解释这些概念。同时,我们还会讨论在什么场景下该使用哪种策略、指出一些常见误区,并分析它们各自的优缺点。
聊聊分区(Partitioning)
什么是分区
分区指的是把一个庞大的数据集拆分成更小、更易于管理的部分,每一部分称为一个“分区”。与其把所有数据都放在一个巨大的桶里,不如把它们分散到几个小桶里,每个桶各自只存放其中的一部分数据。
分区是将数据拆分成不同部分(可以是单独的表,甚至是单独的数据库),核心思想在于:每条数据只会存放在某一个分区中,所有分区加起来才能构成完整的数据集。
分区是如何工作的
在进行分区时,需要先制定一条规则,用来决定每一条数据应该放到哪个分区里。
举个例子,一家公司有一个包含数百万条客户记录的数据库,他们可以按照地区来划分:把东部地区的客户数据放到一个分区,把西部地区的客户数据放到另一个分区。这样,每个分区只保存一部分客户数据,而所有的分区数据合起来就是完整的客户数据。
在数据库中,这通常是通过特定字段来实现的,比如根据邮编范围来划分,把某些范围的记录存到一个分区表里,其他范围的记录存到另一个分区表里。
生活中的类比 —— 图书馆分区
想象一座拥有上百万本藏书的大图书馆。如果所有书都堆在同一个巨大房间里,那么想找到某一本书会非常困难而且耗时。图书馆的解决办法就是把书分区管理:科学类的书放在科学区,历史类的书放在历史区,小说则放在小说区,依此类推。
这样一来,如果你要找历史类的书,只需直接去历史区,而不用在整个图书馆里翻找。这大大提高了查找和管理的效率。类似地,在数据库中,如果把客户数据按地区分区,那么查询东部地区的客户时,就只需要访问“东部”分区,而不必扫描整个数据集。
什么时候以及为什么要用分区
分区的价值主要体现在以下几个方面:
-
提升大数据量下的性能:当一张表的数据量过大时,查询就会变慢。通过分区,可以把数据拆成多个较小的部分。在一个小分区里搜索,比在整张大表中搜索要快得多。同时,分区还能减少索引的体积,从而加快数据检索速度。 -
便于维护和管理:把数据拆分成更小的部分,管理起来更方便。比如备份、删除或归档时,可以按分区进行操作。一个典型的例子是将日志数据按月份分区,当某个月的日志不再需要时,可以直接删除对应的分区。 -
分散系统负载:不同的分区可以分布在不同的硬件设备上(服务器或磁盘),从而把访问压力分散开。如果某个分区的流量很大,也不会轻易拖慢其他分区。 -
支持本地化访问模式:当不同类别的数据在使用上相对独立时,分区可以把它们隔离开来。比如在一个应用中,欧洲客户的数据主要被欧洲的服务器访问,亚洲客户的数据则主要被亚洲的服务器访问。按地区分区后,就能让访问更加本地化,减少跨区流量。
理解了分区之后,我们就更容易理解接下来要介绍的分片(Sharding),分片其实可以看作是分区的一种特殊形式。
聊聊分片
什么是分片
分片本质上就是一种特定的分区方式 —— 通常指的是横向分区,并且会把数据分布到多台服务器或多个数据库实例上。
在进行分片时,系统会把庞大的数据集拆成若干更小的部分(称为“分片”),并把每个分片存放在一台独立的数据库服务器上。所有分片上的数据合在一起,就构成了完整的数据集,但每个分片只负责其中的一部分数据。
需要注意的是,每个分片的表结构(Schema)是相同的,只是存放的数据行不同。可以把分片理解为“分区的升级版”:
-
分区可能只是把数据拆开,仍然放在同一个数据库实例里; -
而分片则进一步把这些拆分后的数据分布到不同的机器上,实现真正的分布式存储和计算。
分片是如何工作的
和分区类似,分片同样需要依赖一条规则来决定每条数据应该存放在哪个分片中。这条规则通常基于一个关键字段,称为 分片键(Shard Key)。
举个例子,一个社交媒体服务可能会根据用户 ID 来分片:
-
某个范围的用户 ID 存放在分片 1(服务器 1), -
下一个范围的用户 ID 存放在分片 2(服务器 2), -
依此类推。
这样,当有新用户注册时,系统会根据分片键的规则,把该用户的数据写入对应的分片;而当该用户再次登录时,系统就能通过用户 ID 确定要访问哪台服务器。
在实际应用中,分片规则的设计方式有很多种:
-
常见做法是对分片键进行 哈希运算,让数据比较均匀地分布在各个分片上; -
也可以采用更直观的策略,比如根据用户名首字母来划分:A–D 放在分片 1,E–H 放在分片 2,依此类推,类似于图书馆里按字母顺序来整理书籍。
无论采用哪种规则,关键在于:每个分片/服务器只存放唯一的一部分数据,彼此之间没有重叠,而所有分片合起来才能覆盖完整的数据集。
生活中的类比 —— 城市披萨外卖(按地区分片)
想象一座大城市里,最初只有一家披萨店负责全城的外卖。随着城市规模不断扩大,这家店渐渐无法应付所有订单,送餐速度也越来越慢。
为了解决这个问题,老板决定在不同区域开设多家分店,并规定每家分店只负责所在区域的订单:北部分店只处理北区的外卖,南部分店只处理南区的外卖,依此类推。这样一来,每家分店只需要服务一部分顾客,整体效率就大大提升了。
这就像数据库的分片:每台服务器(分店)根据某个规则(顾客所在区域)保存一部分数据(顾客/订单),而所有服务器加在一起,才能涵盖全部用户。如果城市继续扩张,还可以再开一家新分店(新增一个分片)来负责新的区域,这就是通过分片实现的扩展。
什么时候以及为什么要用分片
分片通常出现在数据规模和访问压力远超单机极限的场景下,它的价值主要体现在以下几个方面:
-
当数据量大到单台服务器放不下,或者单机无法承受过多请求时,分片就是常见的解决方案。许多大型互联网公司(如社交网络、电商平台)在单库不堪重负时,都会通过分片来管理用户数据。这样就可以通过增加服务器来实现横向扩展。 -
并行处理:分片通常分布在不同的服务器上,因此多个查询可以并行的在不同分片上执行。这能够显著提升整体吞吐量——例如,有 10 个分片时,理论上可以同时处理接近单库 10 倍的请求,因为每个分片都有独立的 CPU 和磁盘资源。 -
地理分布:如果用户遍布全球,可以按地区进行分片,并把数据存放在离用户更近的服务器上。比如,把欧洲用户的数据放在欧洲的服务器,亚洲用户的数据放在美国的服务器,这样可以减少访问延迟。 -
提升可管理性:每个分片本质上就是一个更小的数据库。对于索引优化、数据清理、归档或备份等运维操作,在分片层面执行往往比在一个庞大的单体数据库上更轻松、更高效。
到这里,我们已经介绍了两种通过“拆分数据”来应对大规模问题的方法:分区和分片。接下来要讨论另一种思路:通过复制数据来实现冗余,也就是复制(Replication)。
什么是复制(Replication)
复制指的是把同一份数据拷贝到多台机器或多个位置上。与分区或分片不同,分区/分片的核心是“拆分”,即每份数据只会存放在一个地方;而复制的核心是“冗余”,即在两个或多个地方保存相同的数据。
如果说分区/分片像是把一个大蛋糕切成几块,那复制就像是再烤出几份一模一样的蛋糕。
在数据库系统中,复制主要用于容灾和高可用。当一台数据库服务器宕机时,另一台服务器上的副本可以立刻接管服务,并且拥有相同的数据。为了做到这一点,复制机制会在多台服务器之间持续同步更新数据,从而让副本和主库在任意时刻都保持尽可能一致的状态。
复制是如何工作的
在大多数情况下,复制采用“主从模式”:系统会有一个主数据副本(主库),以及一个或多个从数据副本(从库)。当主库上的数据发生写入或修改时,这些变化会被传递并应用到从库上,从而保持数据一致。
举个例子,假设客户数据库部署在服务器 A 上,并在服务器 B 上也同时部署了一个副本。当在服务器 A 上的数据库新增一条客户数据,或者更新了某个客户的地址时,系统会把这个改动传递到服务器 B,从而保证 B 上的数据与 A 保持一致。
在实现方式上,复制可以是同步的(几乎实时完成更新),也可以是异步的(可能存在一定延迟)。但无论哪种方式,最终目标都是让每个副本都保存完整的数据集。这样,不论查询的是主库还是从库,都能得到相同的结果。
生活中的类比 —— 连锁超市(商品复制)
想象一家在城市里很受欢迎的连锁超市。为了方便顾客,他们在不同的社区开设了多家门店。关键在于,每家店里的商品都是相同的:无论你是在市中心店、北区店还是郊区店,都能买到同样的货品。
这就好比数据库中的复制:每家门店就是同一份库存和服务的副本。即使市中心店某个商品卖完了,或者临时闭店,顾客依然可以去其他门店买到同样的东西,因为不同门店之间的库存是被“复制”的。
当然,为了让顾客在不同门店体验一致,总部还会确保新品上架或价格调整能够同时应用到所有门店。这就对应数据库中的更新同步:一旦主库发生变更,系统会把改动传播到各个副本。通过这种方式,多家门店(副本)的存在既提升了服务的弹性(顾客有多个选择),也增强了系统的可用性(即使一店关门,其他门店仍能正常营业)。
什么时候以及为什么要用复制
-
高可用与容错:复制的首要目的就是保证系统在出现故障时依然能够运行。如果一台数据库服务器宕机,另一台副本可以立即接管,并且能够提供相同的数据,这样就能将停机时间降到最低。这就像备用发电机一样:一台停了,另一台马上顶上,既不断电,也不丢数据。 -
提升读取性能与扩展能力:当系统需要面对大量读请求时(但写入相对较少),可以把读取流量分散到多个副本上。许多大型网站会采用“主库处理写入、多个只读副本处理查询”的模式,这样查询响应速度更快。 -
地理分布加速访问:复制还可以应对 跨地域用户访问 的场景。通过在不同地区的数据中心保留副本,用户可以就近访问数据,减少延迟。 -
灾难恢复:复制相当于提供了一份实时更新的备份。如果某个数据中心遭遇火灾、洪水等灾难,另一处的副本依然保存着完整的数据。这大大提高了系统的容灾能力,避免了数据丢失。
常见的误区 —— 复制 vs 备份
复制和备份这2个概念常常容易被混淆,因为它们都涉及到数据副本。但实际上,这两者的目的和实现方式并不相同。
复制通常指的是一种 在线副本机制,它会实时或近实时地与主库保持同步。这样,当主库出现故障时,副本可以立即接管,实现快速故障切换;同时,多个副本还能分担读请求,实现负载均衡。
而备份更多是一种 离线副本机制。比如定期生成的数据快照,它并不会持续更新,主要用于长期的数据恢复:当系统遭遇严重故障甚至数据丢失时,我们可以通过备份把数据恢复到某个时间点。
换句话说,备份更像是为了“事后恢复”,而复制则是为了保证系统“不间断运行”
对比几种方式并澄清常见误解
前面我们已经分别介绍了分区、分片和复制,它们在实际应用中经常被混淆,因此有必要放在一起对比,先从“分区”和“分片”这两个最接近的概念说起。
分区 vs 分片
分区和分片是最容易混淆的两个概念。简单来说,分片是分区的一种特例:分区强调把数据拆分成独立部分,而分片则更进一步,把这些部分分布到多台服务器上,以此实现横向扩展。
换句话说,如果你把一张大表拆成两张小表,仍然放在同一台数据库服务器上,那只是做了分区,还不能算分片;但如果把这两张小表分别放到两台不同的服务器上,那就完成了分片。
因此,我们可以总结为一句话:所有的分片都是分区,但并不是所有的分区都是分片。
分片 vs 复制
分片和复制的区别非常明显:分片是把数据拆开存放,而复制是把数据拷贝多份。
在分片的情况下,每一条数据只会存放在一个地方(一个分区里);而在复制的情况下,每一条数据会同时存在于多个地方(多个副本里)。
分片通过把不同的数据子集分散到多台服务器上来承载更大的数据量和更高的并发;而复制的目的是通过让相同的数据保存多份,来防止单点故障或提升读请求的并发能力。
可以用图书馆类来类比理解:
-
分片 就好比把图书馆的馆藏按主题拆开,每个分馆只存放一部分书籍(单个分馆并不完整,但合在一起就覆盖了所有藏书)。 -
复制 则像是为某些热门书籍准备多个副本,放在不同的分馆中,这样无论读者去哪个分馆,都能借到这本书。
在实际系统中,这两者往往会结合使用。比如图书馆既会按主题把书籍存放在不同分馆(分片),同时也会为一些畅销书在所有分馆都准备一本(复制)。
常见误区
在讨论分区、分片和复制时,有一些容易让人疑惑的观点需要澄清:
-
“分片和分区完全不同” ——其实,分片只是分区的一种形式(分片是跨多台服务器的水平分区)。很多时候这两个词会被混用,因此理解时需要结合上下文。 -
“复制可以提升写入能力” ——并不完全正确。复制主要用于提升读取性能和容错能力。所有写入操作仍然需要落到主节点上,然后再同步到其他节点,因此它并不会像分片那样成倍增加写入能力。 -
“分区就等于有了备份” ——并不是这样。如果只做了分区而没有复制,那么每条数据仍然只存在于一个分区里。如果某个分区的数据丢失,那这部分数据就彻底没了。分区本身并不提供容错能力,要实现容错还得依赖复制。 -
“有多台服务器就是分片” ——不对。只有当每台服务器存储的是不同的数据子集时,才叫分片。如果所有服务器保存的都是同一份完整数据,那实际上是复制,而不是分片。
如何选择合适的方案
当数据库规模越来越大,单台机器已经难以承载时,通常会考虑”分区或分片“。通过把数据切分并分布到多台机器上,每台机器只需处理一部分数据,从而实现横向扩展。具体如何切分数据(按用户、按地区、按商品类别等),需要在设计阶段做好规划。需要注意的是,引入 分区或分片 技术会给系统带来额外的复杂度,因此通常只在规模确实需要时才会采用。
如果系统的重点在于 可用性和数据安全,或者面临大量读请求,那么就更适合采用 ”复制“。当然即使是小规模系统,复制也能带来好处,例如提供备用节点,或将读写请求分离,提高整体性能。因此,复制往往是实现高可用的基础手段。
在实际应用中,分片和复制往往会结合使用:需要提升读性能和容错能力时使用复制;需要扩展写能力或存储容量时使用分片。两者并不对立,反而常常形成互补,共同支撑大规模系统的稳定运行。
总结
分区(Partitioning)
|
|
|
|---|---|
| 查询更小更快
|
查询复杂
|
| 可扩展性
|
分区键选择困难
|
| 组织清晰
|
维护开销
|
| 隔离性
|
不能单独提供完整解决方案
|
分片(Sharding)
|
|
|
|---|---|
| 几乎无限的存储和吞吐量
|
复杂性增加
|
| 集中负载
|
重新平衡与热点问题
|
| 故障隔离
|
运维负担
|
| 每个分片逻辑更简单
|
开发限制
|
复制(Replication)
|
|
|
|---|---|
| 容错能力
|
一致性管理
|
| 提升读取吞吐量
|
写入开销
|
| 分布式系统中降低延迟
|
存储和成本增加
|
| 数据安全
|
恢复与冲突处理复杂
|
推荐阅读:
专注服务器后台技术栈知识总结分享
码农有道,和您聊技术,和您聊职场,和您聊互联网那些事!

