简介: 当表数据超过一定量级,就需要通过分表来解决单表的性能瓶颈问题;当数据库负载超过一定水平线,就需要通过分库来解决单库的连接数、性能负载的瓶颈问题。本文将阐述在不同情况下,让不同数量级表,在同一个业务ID的事务操作路由到同一分库中的方案,省去解决垮库事务的烦恼。

作者 | 雨庄
来源 | 阿里技术公众号

一 前言

技术同学都知道,当表数据超过一定量级,我们就需要通过分表来解决单表的性能瓶颈问题;当数据库负载超过一定水平线,我们就需要通过分库来解决单库的连接数、性能负载的瓶颈问题。

本文主要阐述在同时满足以下业务场景:

  • 分表分库存储
  • 需要对分表数量不同的表进行同事务操作
  • 这些表的分库分表策略依赖的Sharding业务ID一致

等情况下,让这些不同数量级表,在同一个业务ID的事务操作路由到同一分库中的方案,省去解决垮库事务的烦恼。

二 案例

1 背景

假设有2个数据库实例,需要保存商家订单明细和汇总2张表的数据,这2张表的 分库分表策略都用shop_id取模策略,按单表数据500w的原则进行分表分库:

(1)shop_order_detail 商家订单明细表,日均数据6000w

(2)shop_order_stat 商家订单统计表,日均数据2000w

配置完成后生成的库表:

然后我们要做这么一件事情:在同一个事务中,新增用户订单明细成功后,更新用户订单统计数据:

2 问题

此时,我要处理一笔 user_id = 3 的订单数据:

如图,执行新增shop_order_detail表操作的时候,操作被路由到了DB0中;执行更新shop_order_stat表操作的时候,操作被路由到了DB1。这时候 这两个操作跨库了,无法在同一个事务中执行, 流程异常中断。

如果用TDDL组件的话就会报这样的错:

### Cause: ERR-CODE: [TDDL-4603][ERR_ACCROSS_DB_TRANSACTION] Transaction accross db is not supported in current transaction policy

三 解决方案

解决多表跨库事务的方案有很多,本文阐述的是如下解决方案:

将shop_order_stat作为shop_order_detail的映射基础表,调整shop_order_detail的分表策略,让shop_order_detail和shop_order_stat的数据都路由到同一个库中。

但该方案的前提是目标表的表数量是映射基础表表数量的N倍数。比如shop_order_stat的总表数量是4,shop_order_detail的总表数量是12,故shop_order_detail的总表数是shop_order_stat总表数的3倍。

shop_order_detail新分表分库策略的推导思路如下:

1 调整分库策略

首先,我们看shop_id在0~11范围内,用shop_id % 4分库分表策略shop_order_stat的sharding分布图:

用shop_id % 12分库分表策略shop_order_detail的sharding分布图:

图中看出,两张表都是根据shop_id做sharding,但现有同一个shop_id有可能会被路由到不同的库中,导致跨库操作。

此时,我只需要把shop_order_detail的分库策略调整为跟shop_order_stat一致,保证同一个shop_id能路由到同一个DB分片中就能解决这个问题。调整后的sharding分布图:

但调整完分库策略后,原本的表映射策略就失效了:

原本的shop_id = 5数据可以通过shop % 12 = 5的取模策略映射到DB0的shop_order_detail_05表上。调整完分库策略后,shop_id = 9被路由到了DB0中,通过shop % 12 = 9的取模策略会映射到shop_order_detail_09这张表上,但shop_order_detail_09这张表不在DB0中,所以操作失败了。

这时候,我们需要调整分表策略,把shop_id = 9的数据既映射到DB0中的shop_order_detail_05表中。

2 分区取模策略

首先,以shop_order_stat的单库表数量2作为分块大小,总表数量4作为分区大小,对shop_id=[0~11]进行分区操作,并且将shop_id根据分块大小取模:

当前分库数量为2,shop_order_stat的单库表数量为6,计算出跨库步长=分库下标*单库表数量:

根据分区下标和分块大小,计算出分区步长=分区下标*分块大小,最后根据分块取模数+跨库步长+分区步长就能定位到最终的分表下标了:

这样就完成了把shop_id = 9的数据既映射到DB0中的shop_order_detail_05表中的工作。

四 计算公式

分表下标路由策略计算公式:

分表下标 = 业务ID取模 % 分块大小 + 业务ID取模 / 分块大小 单库表数量 + 业务ID取模 / 分区大小 分块大小

  • 业务ID取模 = 业务ID % 总表数量
  • 分区大小 = 目标映射表的总表数量
  • 分块大小 = 目标映射表的单库表数量

以上面的案例为例,调整shop_order_detail的分库分表路由策略:

(1)shop_order_stat 商家订单统计表

(2)shop_order_detail 商家订单明细表

TDDL sharding-rule配置代码示例:

Java代码示例:

long shopId = 9;
int dbs = 2;
int tables = 12;
int oneDbTables = 6;
int partitionSize = 4;
int blockSize = 2;
int sharding = (int) (shopId % tables);
// 目标分库
int dbIndex = (int) (shopId % partitionSize / dbs);
// 目标分表
int tableIndex = sharding % blockSize + sharding % partitionSize / blockSize * oneDbTables + sharding / partitionSize * blockSize;

五 结尾

我是本地生活外卖商家运营研发团队中的一员,在实际业务场景的设计中遇到了多表事务分库内闭环的问题,没有找到适合的案例参考,才孵化出这个解决方案。

目前该方案已经在落地上线,有相同业务场景需求的同学可直接套用计算公式既可,欢迎大家交流沟通。

原文链接

本文为阿里云原创内容,未经允许不得转载。

分区取模分库分表策略:多表事务分库内闭环解决方案相关推荐

  1. 组合数学 —— 组合数取模 —— 逆元与递推打表

    [逆元求法] 1.要求:p 是质数 2.时间复杂度:O(n) 3.求解  的步骤: 1)通过循环,预先算好所有小于 N 的阶乘(%p)的结果,存到数组 fac[] 中 (fac[i] = i!%p) ...

  2. MySQL数据库知识学习(五)读写分离与分库分表策略

    通过数据库锁及存储引擎的学习,我们知道数据库在数据操作过程中为了保证数据的一致性是会给表或行加锁的,在网站发展的初期,由于没有太多访问量,一般来讲只需要一台服务器就够了,这的操作也不会有什么问题.但随 ...

  3. ShardingSphere(二) 水平分表配置搭建,实现分表写入读取

    概述:本章内容分将搭建一个ShardingSphere工程环境,并实现最简单的单库下的水平分表配置演示.通过解读配置文件我们来了解ShardingSphere中是如何实现他的路由操作. 环境:Spri ...

  4. Mycat之——取模分片

    转载请注明出处:http://blog.csdn.net/l1028386804/article/details/77150670 一.简单描述 取模分片,就是根据数据表的某一个字段,通常是某一个整数 ...

  5. mysql分库分表取模扩容_MyCat分库分表策略——范围取模

    范围取模分片的优点在于,既拥有范围分片的固定范围数据不做迁移的优点,也拥有了取模分片对于热点数据均匀分布的优点.首先我们还是以一个示例进行讲解: id rang-mod 0 files/partiti ...

  6. mysql取余 和 取模_java 取模运算% 实则取余 简述 例子 应用在数据库分库分表

    java 取模运算%  实则取余 简述 例子 应用在数据库分库分表 求模运算与求余运算不同."模"是"Mod"的音译,模运算多应用于程序编写中. Mod的含义为 ...

  7. 【数据库】分库分表策略

    关系型数据库本身比较容易成为系统瓶颈,单机存储容量.连接数.处理能力都有限.当单表的数据量达到1000W或100G以后,由于查询维度较多,即使添加从库.优化索引,做很多操作时性能仍下降严重.此时就要考 ...

  8. mysql 分库分表策略_【数据库】分库分表策略

    关系型数据库本身比较容易成为系统瓶颈,单机存储容量.连接数.处理能力都有限.当单表的数据量达到1000W或100G以后,由于查询维度较多,即使添加从库.优化索引,做很多操作时性能仍下降严重.此时就要考 ...

  9. mycat 分表子查询_MyCat分库分表策略详解

    在我们的项目发展到一定阶段之后,随着数据量的增大,分库分表就变成了一件非常自然的事情.常见的分库分表方式有两种:客户端模式和服务器模式,这两种的典型代表有sharding-jdbc和MyCat.所谓的 ...

最新文章

  1. 人声提取工具Spleeter安装教程(linux)
  2. ​清华大学智能产业研究院AI医疗团队招聘知识图谱方向实习生
  3. greenplum 安装笔记
  4. Python的一些技巧
  5. 个人计算机使用的标准键盘,计算机键盘的基本用法!
  6. Taro+react开发(72):Taro.createSelectorQuery
  7. 干货:通过双十一等项目实战看架构技术
  8. matlab中如何将视频保存成图像
  9. 区块链的一些名词解释
  10. [译]R语言——Shiny框架之构建(一):1.结构——1.独立应用程序——2.双文件式Shiny应用
  11. python实现将文件下内每张图片按顺序命名为txt文本文件中的内容
  12. 随机取 数据库中的 记录
  13. 精明的程序员——节奏大师乐谱破解
  14. OpenWrt开发必备软件模块——进程管理服务procd
  15. 伦敦金走势图与顾比均线
  16. android线程改变布局,震惊!Android子线程也能修改UI?(第二篇)
  17. 关于个人电脑C盘清理的一些小整合
  18. 【01背包记录路径】东东开车了
  19. Html5 移动游戏开发
  20. iOS 开发者一定要知道的 14 个知识点

热门文章

  1. python中range 函数_pythonrange,range函数的用法
  2. vue修改计算属性的值_Vue语法高级之计算属性和侦听器
  3. python删除txt指定内容_python删除文件中指定内容
  4. 已知三角形三点坐标求角度_细心研磨椭圆焦点三角形,这肯定是最全的解释。...
  5. 华为手机如何固定横屏_华为手机如何录屏?原来方法这么简单,手把手教你学会...
  6. Java编程开发中高效编码的7个技巧?你应该知道……
  7. python3 gui tk代码_【基础】学习笔记30-python3 tkinter GUI编程-实操12
  8. perl python json_Perl解析JSON数据精解
  9. python和arduino串口通信_利用串行通信实现python与arduino的同步
  10. u2020 华为_华为MateBook X Pro 2020款评测:全面屏商务旗舰再升级