分库分表带来的问题

时间:2024-03-23 10:14:20

前言:分库分表虽然能带来性能提升,但同时会提出

问题一:跨库关联查询

我们有几种主要的解决方案:
1、字段冗余
比如我们查询合同库的合同表的时候需要关联客户库的客户表,我们可以直接把一
些经常关联查询的客户字段放到合同表,通过这种方式避免跨库关联查询的问题。
2、数据同步:比如商户系统要查询产品系统的产品表,我们干脆在商户系统创建一
张产品表,通过ETL 或者其他方式定时同步产品数据。
3、全局表(广播表) 比如行名行号信息被很多业务系统用到,如果我们放在核心
系统,每个系统都要去关联查询,这个时候我们可以在所有的数据库都存储相同的基础
数据。
4、ER 表(绑定表)
我们有些表的数据是存在逻辑的主外键关系的,比如订单表order_info,存的是汇
总的商品数,商品金额;订单明细表order_detail,是每个商品的价格,个数等等。或者
叫做从属关系,父表和子表的关系。他们之间会经常有关联查询的操作,如果父表的数
据和子表的数据分别存储在不同的数据库,跨库关联查询也比较麻烦。所以我们能不能
把父表和数据和从属于父表的数据落到一个节点上呢?
比如order_id=1001 的数据在node1 , 它所有的明细数据也放到node1 ;
order_id=1002 的数据在node2,它所有的明细数据都放到node2,这样在关联查询的
时候依然是在一个数据库。
上面的思路都是通过合理的数据分布避免跨库关联查询,实际上在我们的业务中,
也是尽量不要用跨库关联查询,如果出现了这种情况,就要分析一下业务或者数据拆分
是不是合理。如果还是出现了需要跨库关联的情况,那我们就只能用最后一种办法。
5、系统层组装
在不同的数据库节点把符合条件数据的数据查询出来,然后重新组装,返回给客户
端。


问题二:分布式事务


分布式事务有几种常见的解决方案:
1、全局事务(比如XA 两阶段提交;应用、事务管理器(TM)、资源管理器(DB)),
例如Atomikos
2、基于可靠消息服务的分布式事务
分库分表带来的问题分库分表带来的问题
3、柔性事务TCC(Try-Confirm-Cancel)tcc-transaction

分库分表带来的问题
4、最大努力通知,通过消息中间件向其他系统发送消息(重复投递+定期校对)


问题三: 排序、翻页、函数计算问题


跨节点多库进行查询时,会出现limit 分页,order by 排序的问题。比如有两个节点,
节点1 存的是奇数id=1,3,5,7,9……;节点2 存的是偶数id=2,4,6,8,10……
执行select * from user_info order by id limit 0,10
需要在两个节点上各取出10 条,然后合并数据,重新排序。
max、min、sum、count 之类的函数在进行计算的时候,也需要先在每个分片上执
行相应的函数,然后将各个分片的结果集进行汇总和再次计算,最终将结果返回。

问题四:全局主键避重问题
MySQL 的数据库里面字段有一个自增的属性,Oracle 也有Sequence 序列。如果
是一个数据库,那么可以保证ID 是不重复的,但是水平分表以后,每个表都按照自己的
规律自增,肯定会出现ID 重复的问题,这个时候我们就不能用本地自增的方式了。
我们有几种常见的解决方案:
1)UUID(Universally Unique Identifier 通用唯一识别码)
UUID 是主键是最简单的方案,本地生成,性能高,没有网络耗时。但缺点也很明显,
由于UUID 非常长,会占用大量的存储空间;另外,作为主键建立索引和基于索引进行
查询时都会存在性能问题,在InnoDB 中,UUID 的无序性会引起数据位置频繁变动,导
致分页。
2) 数据库
把序号维护在数据库的一张表中。这张表记录了全局主键的类型、位数、起始值,
当前值。当其他应用需要获得全局ID 时,先for update 锁行,取到值+1 后并且更新后
返回。并发性比较差。
3)Redis
基于Redis 的INT 自增的特性,使用批量的方式降低数据库的写压力,每次获取一
段区间的ID 号段,用完之后再去数据库获取,可以大大减轻数据库的压力。
4)雪花算法Snowflake(64bit)

分库分表带来的问题
核心思想:
a)使用41bit 作为毫秒数,可以使用69 年
b)10bit 作为机器的ID(5bit 是数据中心,5bit 的机器ID),支持1024 个
节点
c)12bit 作为毫秒内的流水号(每个节点在每毫秒可以产生4096 个ID)
d)最后还有一个符号位,永远是0。
代码:snowflake.SnowFlakeTest
优点:毫秒数在高位,生成的ID 整体上按时间趋势递增;不依赖第三方系统,稳定
性和效率较高,理论上QPS 约为409.6w/s(1000*2^12),并且整个分布式系统内不会
产生ID 碰撞;可根据自身业务灵活分配bit 位。
不足就在于:强依赖机器时钟,如果时钟回拨,则可能导致生成ID 重复。