数据库分库分表可扩展及数据倾斜/热点问题
“ 在高并发、业务数据规模庞大、数据库服务负载高 的场景中,数据库分库分表是必不可少的手段之一。如何建立高效的分配策略,确保良好的可扩展性,解决数据倾斜等问题呢?”
上周看到一篇关于,数据库分库分表的文章,文中除了提到垂直维度分割,还说到水平维度的两种分割策略:分别是 Range 和 Hash ,详细描述可点 这里。
https://blog.csdn.net/qq_34417408/article/details/123658625?spm=1001.2014.3001.5502
这里着重依据实际项目落地经验,提出一种兼容 Range 和 Hash 的分割手段,我也称它为 ” 山前车 “ 策略。
当业务数据规模到 1TB+/表的时候,你就要着手准备分库分表的备案了。
以 市场占有率靠前的 数据库 Mysql 为例,数据库数据的操作离不开索引,而其索引结构为 B+ 数。数据量不断膨胀,意味着树结构不断延长,时间复杂度 logN 和 树的高度呈正相关,数据检索性能下降;在数据库管理和维护方面,数据规模膨胀代表着数据迁移、备份、容灾…等操作复杂度上升,可维护性、灵活性逐步下降;在业务开发方面,研发人员需要考虑更多性能问题及不同数据之间复杂的关联关系等等;资源成本投入相对增加……
针对数据量增长的不同业务属性,可将分库分表统筹到两个分组中,垂直 和 水平。
垂直,通常在切分业务,数据解耦的时候用到。比如,业务起步初期,一张表赋予了很多功能,包含了用户信息、地域信息、用户购买记录、用户运动行为等等……,随着业务增长,这张表数据膨胀飞起,开发及维护的成本不断加大,这个时候就需要依据数据的业务属性进行切割,可以将 用户基本信息、地域信息、商品信息、运动行为等单独制表,完成数据的垂直区分。
水平,在面对最小数据属性集,数据量增长的问题时用到的策略。比如,用户的消费信息,通常会以 uid 或 唯一id[自增] 为分段字段。将范围在 0–1kw 作为一个 range 进行落地,1kw—2kw 间隔进行另外落地……;或 uid % 2 进行分库的命中,依据奇偶来定位数据库位置,然后 uid % 1024,对数据库表数进行 mod 定位表…..等等一系列的路由关系。
在设计数据库分库分表之初,需要考虑方案的可扩展性及成本。
在 Range 中,数据规模再次增加,直接对 range 区间进行新增即可。但此模式下,或出现热点数据的问题,会导致数据库负载不均衡,高负载下,单节点拉垮的情景。毕竟数据十分密集的集中在一个或几个数据库表中,缺乏 hash 的负载分散优势能力。
在 Hash 中,在完全可以避免热点问题,将负载均匀或按权重进行打散分配;但数据量膨胀,再次扩展时,新的路由规则无法保证原数据的落地位置不变,需要进行数据的迁移。当然数据的迁移可以在备库或者负载谷底进行,但或多或少对服务有影响,数据一致性的风险也不能说完全没有。
有没有权衡两种模式利弊的方案呢?答案是有的,而且很简单…...
“ 山前车 ” ,顾名思义,车到山前必有路。
世上原本没有路,都是走着走着就有了。有些技术方案也是如此,正应了 “ 车到山前必有路 ” 的这句老话。
以 Hash 策略为例,当需要再次进行扩展时,为保证原数据完整性,不进行迁移操作;依据分段字段的自增性,预估一段时间的扩展阈值,确保阈值范围内的数据走老路由,范围外的走新路由即可。
在 Range 策略中,区间范围内对多表新增 Hash 策略,补充合适的路由规则,将数据均衡分配,避免数据热点等问题。
方案很简单,回过头来进行思考,不管是哪种方案 ,都是对 两种策略 权衡之后的各自变形落地。在实际实践中,数据的可扩展性往往是后话,面对业务第一次的拆分会兼容到数据规模膨胀到问题,到二次扩展的场景不多,真正到的时候,才需要上述 “ 山前车 “ 的策略解决问题。
作为一名架构师,需要充分的考虑问题。在设计之初,需要确保最大的 ROI ,考虑更多的扩展、运维、效率、等等方面….
其实在做分库分表备案的时候,就可以先设计好 二次扩展的自增阈值,在阈值限定的数据规模内,更精细的进行路由制定,在问题来临前做好万全之策。
猜你喜欢
#架构|高可用|高性能|高并发|高容错|HTTP|TLS|网络|加密算法|面试|同步|异步#