This commit is contained in:
by931
2022-09-06 22:30:37 +08:00
parent 66970f3e38
commit 3d6528675a
796 changed files with 3382 additions and 3382 deletions

View File

@@ -261,7 +261,7 @@ function hide_canvas() {
<h4>1. 哈希取模的方式</h4>
<p>哈希取模是分库分表中最常见的一种方案,也就是根据不同的业务主键输入,对数据库进行取模,得到插入数据的位置。</p>
<p>6000 万的数据规模,我们按照单表承载百万数量级来拆分,拆分成 64 张表,进一步可以把 64 张表拆分到两个数据库中,每个库中配置 32 张表。当新订单创建时,首先生成订单 ID对数据库个数取模计算对应访问的数据库接下来对数据表取模计算路由到的数据表当处理查询操作时也通过同样的规则处理这样就实现了通过订单 ID 定位到具体数据表。</p>
<p><img src="assets/CgqCHl7x0eOAWkmIAACs_WhYNh0680.png" alt="3.png" />
<p><img src="assets/CgqCHl7x0eOAWkmIAACs_WhYNh0680.png" alt="png" />
规则示意图</p>
<p>通过哈希取模的方式进行路由,优点是数据拆分比较均匀,但缺点是不利于后面的扩容。假设我们的订单增长速度超出预估,数据规模很快达到了几亿的数量级,原先的数据表已经不满足性能要求,数据库需要继续进行拆分。</p>
<p>数据库拆分以后,订单库和表的数量都需要调整,路由规则也需要调整,为了适配新的分库分表规则,保证数据的读写正常,不可避免地要进行数据迁移,具体的操作,可以分为<strong>停机迁移</strong><strong>不停机迁移</strong>两种方式。</p>
@@ -285,14 +285,14 @@ function hide_canvas() {
<h4>2. 基于数据范围进行拆分</h4>
<p>基于数据范围进行路由,通常是根据特定的字段进行划分不同区间,对订单表进行拆分中,如果基于数据范围路由,可以按照订单 ID 进行范围的划分。</p>
<p>同样是拆分成 64 张数据表,可以把订单 ID 在 3000万 以下的数据划分到第一个订单库3000 万以上的数据划分到第二个订单库,在每个数据库中,继续按照每张表 100万 的范围进行划分。</p>
<p><img src="assets/Ciqc1F7x0fSADRFMAACumaYaTOo201.png" alt="4.png" />
<p><img src="assets/Ciqc1F7x0fSADRFMAACumaYaTOo201.png" alt="png" />
规则示意图</p>
<p>可以看到,基于数据范围进行路由的规则,当进行扩容时,可以直接增加新的存储,将新生成的数据区间映射到新添加的存储节点中,不需要进行节点之间的调整,也不需要迁移历史数据。</p>
<p>但是这种方式的缺点就是数据访问不均匀。如果按照这种规则,另外一个数据库在很长一段时间内都得不到应用,导致数据节点负荷不均,在极端情况下,当前热点库可能出现性能瓶颈,无法发挥分库分表带来的性能优势。</p>
<h4>3. 结合数据范围和哈希取模</h4>
<p>现在考虑,如果结合以上两种方式数据范围和哈希取模,那么是不是可以实现数据均匀分布,也可以更好地进行扩容?</p>
<p>我们设计这样的一个路由规则,首先对订单 ID 进行哈希取模,然后对取模后的数据再次进行范围分区。</p>
<p><img src="assets/CgqCHl7x0gGARLrYAAEBoh985X0406.png" alt="5.png" />
<p><img src="assets/CgqCHl7x0gGARLrYAAEBoh985X0406.png" alt="png" />
订单数据库进一步拆分</p>
<p>可以看到,通过哈希取模结合数据区间的方式,可以比较好地平衡两种路由方案的优缺点。当数据写入时,首先通过一次取模,计算出一个数据库,然后使用订单 ID 的范围,进行二次计算,将数据分散到不同的数据表中。</p>
<p>这种方式避免了单纯基于数据范围可能出现的热点存储,并且在后期扩展时,可以直接增加对应的扩展表,避免了复杂的数据迁移工作。</p>