内容简介:为了提升数据库的处理能力,我们把单库扩展成多库,并通过更新同步机制(即Replication)来保证多份数据的一致性。如此这般,数据库的扩展难题似乎已经顺利解决了然而,在 Replication 方案下,每个数据库都持有一份完整数据,基于全量数据提供增删改查服务,单机的硬件资源是有限的,因此单库的处理能力也是有限的:
写在前面
为了提升数据库的处理能力,我们把单库扩展成多库,并通过更新同步机制(即Replication)来保证多份数据的一致性。如此这般,数据库的扩展难题似乎已经顺利解决了
然而,在 Replication 方案下,每个数据库都持有一份完整数据,基于全量数据提供增删改查服务, 单库的性能瓶颈仍然存在 ,并将成为限制系统扩展性的关键因素
一.单库的性能瓶颈
单机的硬件资源是有限的,因此单库的处理能力也是有限的:
-
容量有限:数据量可能大到单库无法容纳
-
性能有限:单库的读写性能同样受数据量影响,查询/更新越来越慢
单靠加机器/加库显然无法直接解决单机/单库的性能问题, 除非进一步打破库的边界,把单库拆分成多库 (而不只是复制多份)
P.S.理论上,Web 应用层也面临同样的问题,却不曾听说过一个 Web 服务庞大到单机无法部署,这是因为 Web 服务在设计之初就会考虑职责划分与解耦 ,以便各部分能够独立部署、独立扩展,从 20 年前的 SOA(即面向服务架构,包括 微服务架构(Microservices) 等变体)起便是如此
二.分区(Partitioning)
为了避免单库性能成为系统可扩展性的瓶颈,通常把逻辑数据库(或其组成元素,例如数据表)拆分成各个独立部分,这种做法称为 分区(Partitioning) :
A partition is a division of a logical database or its constituent elements into distinct independent parts.
(摘自 Partition (database) )
就像微服务架构中把单体应用(Monolithic application)拆分成一组小型服务一样,我们通过分区把单库拆分成一组(数据规模)更小的库,各自处理一部分数据,共同分担流量,主要优势体现在:
-
可扩展性:把单库数据拆分到多库后,系统的可扩展性不再受限于单库性能,数据库层“无限”扩展成为了可能
-
性能:单库数据量减少,数据操作更快,甚至允许多库并行操作
-
安全性:可以针对(拆出去的)敏感数据,采取更强的安全控制
-
灵活性:可以对不同的库(比如按数据重要性)采用不同的监控、备份策略,以缩减成本,提升管理效率。或者对不同类型的数据选用不同的存储服务,比如大型二进制内容放到 blob 存储中,更复杂的数据可以存放在文档数据库中
-
可用性:把数据分散放到多个篮子里,能够避免单点故障,并且单库故障仅影响一部分数据
具体的,有 3 种拆分策略:
-
水平分区(Horizontal partitioning,也叫 Sharding):按行拆分,把不同的行放入不同的表中
-
垂直分区(Vertical partitioning):按列拆分,把一些列放到其它表中
-
按功能分区(Functional partitioning,有时也叫 Federation):按业务功能拆分,把业务领域中属于相同界限上下文(Bounded Context)的数据放在一起
当然,这 3 种策略并不冲突,可以结合使用
P.S.关于领域驱动设计(Domain-Driven Design),以及界限上下文的更多信息,见 去中心化数据管理(Decentralized Data Management)
三.水平分区
水平分区,即 分片(Sharding) 。每片(shard)都是原数据的一个子集,共同构成完整的数据集:
A database shard is a horizontal partition of data in a database or search engine. Each individual partition (or server) acts as the single source for this subset of data.
(摘自 Shard (database architecture) )
与垂直分区相比,水平分区最大的特点是 schema 保持不变 :
Each partition is a separate data store, but all partitions have the same schema.
就像把一张表横向切几刀,分成几段小表,它们的表结构(字段等)完全一致
这种横向切分减少了单库所需存储的数据量,以及所需承载的流量/操作,另一方面,还减少了资源争用(contention),有助于提升性能
shard key 的选取
具体操作上, 关键在于如何选取 shard key (按哪个字段的什么特征来分片),尽可能保证负载被均匀地分散到每一片上
注意,均匀并不意味着要求每一片的数据量均等,重点是均分流量(有些片可能数据量很大,但访问量却很低)
同时还要避免产生“热点”,比如按姓氏首字母对用户信息进行分片实际上是不均匀的,因为有些字母更常见,此时按用户 ID 哈希值来分片可能更均匀些
四.垂直分区
另一种拆分方式是垂直分区,将一些列(字段)拆分到其它表中:
多用于减少 I/O、降低性能成本,比如,按使用频率把常用字段和不常用的字段分开
比起水平分区,垂直分区的关键优势在于 把信息拆的更细,进而允许一些针对性的优化 ,比如把不经常变化的数据拆分出来,丢到缓存中,把照片等大型二进制内容拆出去单独存放,或者对部分敏感数据进行针对性的安全控制,另一方面,细粒度的数据划分也能够消除一些并发访问,降低并发访问量
五.按功能分区
此外,还可以结合具体应用场景,按业务功能拆分:
把不相干的数据剔除出去(把紧密相关的数据放到一起),有助于加强数据隔离,提升数据访问性能,比如把客户信息和商品库存信息分开
六.分区的代价
把单库拆成多库,虽然能够解决数据库的扩展性难题,但也引发了一些新问题:
-
连表查询慢:尽量避免跨分区 join、或者考虑并行查询
-
全表查询慢:对于需要扫描全量数据的查询操作,即便有并行优化也慢,可以通过垂直分区、按功能分区来定位目标分区,避免全表查询,至于水平分区,可以在应用层维护一张映射表,加快分区定位
-
不支持事务操作:将事务操作交由应用层来处理
-
负载不匀导致分区效果大打折扣:考虑增加监控,并根据分析预测定期调整
诚然,其中有些问题没有非常漂亮的解决方案,实际应用中更多的是面向特定场景的权衡取舍
参考资料
以上所述就是小编给大家介绍的《Database Partitioning_系统设计笔记10》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
构建高可用Linux服务器
余洪春 / 机械工业出版社华章公司 / 2011-11-1 / 79.00元
资深Linux/Unix系统管理专家兼架构师多年一线工作经验结晶,51CTO和ChinaUnix等知名社区联袂推荐。结合实际生产环境,从Linux虚拟化、集群、服务器故障诊断与排除、系统安全性等多角度阐述构建高可用Linux服务器的最佳实践。本书实践性非常强,包含大量企业级的应用案例及相应的解决方案,读者可以直接用这些方案解决在实际工作中遇到的问题。 全书一共10章。第1章以作者的项目实践为......一起来看看 《构建高可用Linux服务器》 这本书的介绍吧!