从分库分表后遗症,总结数据库表拆分策略
副标题[/!--empirenews.page--]
技术沙龙 | 邀您于8月25日与国美/AWS/转转三位专家共同探讨小程序电商实战
本文将主要从背景、分库分表带来的后遗症、分表策略以及一些注意事项等方面对数据库分表来进行小结。 一、背景 最近一段时间内结束了数据库表拆分项目,本次拆分主要包括订单和优惠券两大块,这两块都是覆盖全集团所有分子公司所有业务线。随着公司的业务飞速发展,不管是存储的要求,还是写入、读取的性能都基本上到了警戒水位。 订单是交易的核心,优惠券是营销的核心,这两块基本上是整个平台的正向最核心部分。为了支持未来三到五年的快速发展,我们需要对数据进行拆分。 数据库表拆分业内已经有很多成熟方案,已经不是什么高深的技术,基本上是纯工程化的流程,但是能有机会进行实际的操刀一把,机会还是难得,所以非常有必要做个总结。 由于分库分表包含的技术选型和方式方法多种多样,这篇文章不是罗列和汇总介绍各种方法,而是总结我们在实施分库分表过程中的一些经验。 根据业务场景判断,我们主要是做水平拆分,做逻辑DB拆分,考虑到未来数据库写入瓶颈可以将一组Sharding表直接迁移进分库中。 二、分库、分表带来的后遗症 分库、分表会带来很多的后遗症,会使整个系统架构变的复杂。分的好与不好最关键就是如何寻找那个Sharding key,如果这个Sharding key刚好是业务维度上的分界线就会直接提升性能和改善复杂度,否则就会有各种脚手架来支撑,系统也就会变得复杂。 比如订单系统中的用户__ID__、订单__type__、商家__ID__、渠道__ID__,优惠券系统中的批次__ID__、渠道__ID__、机构__ID__ 等,这些都是潜在的Sharding key。 如果刚好有这么一个Sharding key存在后面处理路由(routing)就会很方便,否则就需要一些大而全的索引表来处理OLAP的查询。 一旦Sharding之后首先要面对的问题就是查询时排序分页问题。 1、归并排序 原来在一个数据库表中处理排序分页是比较方便的,Sharding之后就会存在多个数据源,这里我们将多个数据源统称为分片。 想要实现多分片排序分页就需要将各个片的数据都汇集起来进行排序,就需要用到归并排序算法。这些数据在各个分片中可以做到有序的(输出有序),但是整体上是无序的。 我们看个简单的例子:
这是做奇偶Sharding 的两个分片,我们假设分页参数设置为每页4条,当前第1页,参数如下:
最乐观情况下我们需要分别读取两个分片节点中的前两条:
排序完刚好是{1、2、3、4},但是这种场景基本上不太可能出现,假设如下分片节点数据:
我们还是按照读取每个节点前两条肯定是错误的,因为最悲观情况下(也是最真实的情况)就是排序完后所有的数据都来自一个分片。所以我们需要读取每个节点的pageSize大小的数据出来才有可能保证数据的正确性。 这个例子只是假设我们的查询条件输出的数据刚好是均等的,真实的情况一定是各种各样的查询条件筛选出来的数据集合,此时这个数据一定不是这样的排列方式,最真实的就是最后者这种结构。 我们以此类推,如果我们的currentPage:1000,那么会出现什么问题?我们需要每个Sharding node读取 __4000(1000*4=4000)__ 条数据出来排序,因为最悲观情况下有可能所有的数据均来自一个Sharding node 。 这样无限制的翻页下去,处理排序分页的机器肯定会内存撑爆,就算不撑爆一定会触发性能瓶颈。 这个简单的例子用来说明分片之后,排序分页带来的现实问题,这也有助于我们理解分布式系统在做多节点排序分页时为什么有最大分页限制。 2、深分页性能问题 面对这种问题,我们需要改变查询条件重新分页。一个庞大的数据集会通过多种方式进行数据拆分,按机构、按时间、按渠道等等,拆分在不同的数据源中。一般的深分页问题我们可以通过改变查询条件来平滑解决,但是这种方案并不能解决所有的业务场景。 比如,我们有一个订单列表,从C端用户来查询自己的订单列表数据量不会很大,但是运营后台系统可能面对全平台的所有订单数据量,所以数据量会很大。 改变查询条件有两种:
(编辑:好传媒网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |