分库分表能有效的缓解单机和单库带来的性能瓶颈和压力,突破网络IO、硬件资源、连接数的瓶颈,同时也带来了一些问题。
下面将描述这些技术挑战以及对应的解决思路。
1、事务一致性问题
分布式事务
当更新内容同时分布在不同库中,不可避免会带来跨库事务问题。跨分片事务也是分布式事务,没有简单的方案,一般可使用"XA协议"和"两阶段提交"处理。
分布式事务能最大限度保证了数据库操作的原子性。
但在提交事务时需要协调多个节点,推后了提交事务的时间点,延长了事务的执行时间。
导致事务在访问共享资源时发生冲突或死锁的概率增高。
随着数据库节点的增多,这种趋势会越来越严重,从而成为系统在数据库层面上水平扩展的枷锁。
最终一致性
对于那些性能要求很高,但对一致性要求不高的系统,往往不苛求系统的实时一致性,只要在允许的时间段内达到最终一致性即可,可采用事务补偿的方式。
与事务在执行中发生错误后立即回滚的方式不同,事务补偿是一种事后检查补救的措施,一些常见的实现方法有:对数据进行对账检查,基于日志进行对比,定期同标准数据来源进行同步等等。
事务补偿还要结合业务系统来考虑。
2、跨节点关联查询 join 问题
切分之前,系统中很多数据是通过sql join 来完成的。
而切分之后,数据可能分布在不同的节点上,此时join带来的问题就比较麻烦,考虑到性能,尽量避免join查询。
解决这个问题的一些办法:
1、全局表
全局表也可以看做是数据字典表,就是系统中所有模块都可能以来的一些表,为了避免跨库join查询,可以将这类表在每一个数据库中都保存一份,这些数据通常很少会进行修改,不必担心一致性的问题。
2、字段冗余
一种典型的反范式设计,利用空间换时间,为了性能而避免跨库join查询。这种适用于以来字段比较少的情况。
3、数据组装
系统层面,分两次查询,第一次查询结果中找到关联id,然后根据id发起第二次请求,组装数据返回
4、ER分片
关系型数据库中,如果可以先确定表之间的关联关系,并将那些存在关联关系的表记录存放在同一个分片上,那么就能较好的避免跨分片join问题。