mysql分表分库选型

三个方向:

一、应用中自己实现,可直连数据库,自己实现因目前使用的Mybatis框架可以使用两种做法:

1、在SQL中直接分表逻辑,我查了一下代码中的sql,发现join的千姿百态,不大动这些sql这事基本不现实,优点是定制化,针对性比较高,性能方面损耗比较低,调试调优简单,但是扩展性要差一些。

2、在Mybatis的拦截器里对SQL进行截取拼装,如果能对指定表做的并对相关表的join sql调整一下的话,就是需要规划下占位符及分表jion策略,另外需要对多种情况进行大量测试,这个策略要比手改sql通用所以也复杂很多,相对于上一条,优缺点都相对模糊一点。

二、直接购买云服务DRDS,DRDS基于TDDL,但是与我们目前的RDS是不同的产品,切换时可能需要停机,TDDL的重点部分并未开源,对关键点的实现不好评估。DRDS分共享版和专享版两种,价格差别是数量级层面的,共享版比我们目前用的RDS要便宜很多,专享版要贵差不多一倍。据说已经有P2P公司在使用这个产品,推测使用的是最大送达模型,这个模型需要保证幂等,协调者(重试服务)必须高可用。

RDS迁移DRDS需要注意什么?

DRDS用的是最大努力送达?

分页如何处理的,会不会存在每次都是查询0到当前,越翻越慢的问题?

 

  • 暂不支持非 WHERE 条件的 Correlate Subquery。
  • 暂不支持 SQL 中带聚合条件的 Correlate Subquery。

https://help.aliyun.com/document_detail/49249.html?spm=5176.7947010.211449.2.4oyoNx

 

https://help.aliyun.com/document_detail/29669.html?spm=5176.7752178.6.586.xoHQwR

另外,阿里云还有全局事务服务,正在公测:https://www.aliyun.com/aliware/txc

三、通过中间件

首先排除掉收费的,之后考察了

MyCAT(https://github.com/MyCATApache):

社区爱好者在阿里cobar基础上进行二次开发,发现对我们公司不适合分库和多节点情况下使用,然而感觉单库单节点(单RDS主多从,拦截器实现读写分离)情况下,还要为它支出服务器和运维资源有些不值得,而且它本身没有提供高可用,需要另外部署haproxy,还要保证haproxy的高可用。多节点情况下,分页的sql在非第一页的情况下会被改写:

改写的原因应该是多节点数据混合排序,但是每次都是查0到当前最后对我们的应用情况来看,压力有些过,如果只用一个节点,看上去倒是不错

关于分表发现了这么一句注释:

这倒应该不是说不能join,说的应该是不能随意join,我并没花时间细致在代码里证明,它本身提供了一些说明,在join情况下有两种方式可用,一种是全局表,另外一种是join关联条件的数据要保证在同一库上,如果被jion的结果集中有部分数据没在当前SQL执行的所在库上,那么查询结果就是错的

第二个问题是分布式事务,也是多节点,无法保证强一致性:

循环执行收到的请求,如果是提交则执行CommitNodeHandler,如果是回滚则执行RollbackNodeHandler:

public void rollback() {
        final int initCount = session.getTargetCount();
        lock.lock();
        try {
            reset(initCount);
        } finally {
            lock.unlock();
        }
        if (session.closed()) {
            decrementCountToZero();
            return;
        }

        // 执行
        int started = 0;
        for (final RouteResultsetNode node : session.getTargetKeys()) {
            if (node == null) {
                    LOGGER.error("null is contained in RoutResultsetNodes, source = "
                            + session.getSource());
                continue;
            }
            final BackendConnection conn = session.getTarget(node);

            if (conn != null) {
                boolean isClosed=conn.isClosedOrQuit();
                    if(isClosed)
                    {
                        session.getSource().writeErrMessage(ErrorCode.ER_UNKNOWN_ERROR,
                                "receive rollback,but find backend con is closed or quit");
                        LOGGER.error( conn+"receive rollback,but fond backend con is closed or quit");
                    }
                if (LOGGER.isDebugEnabled()) {
                    LOGGER.debug("rollback job run for " + conn);
                }
                if (clearIfSessionClosed(session)) {
                    return;
                }
                conn.setResponseHandler(RollbackNodeHandler.this);

                //support the XA rollback
                if(session.getXaTXID()!=null && conn instanceof  MySQLConnection) {
                    MySQLConnection mysqlCon = (MySQLConnection) conn;
                    String xaTxId = session.getXaTXID();
                    //exeBatch cmd issue : the 2nd package can not receive the response
                    mysqlCon.execCmd("XA END " + xaTxId + ";");
                    mysqlCon.execCmd("XA ROLLBACK " + xaTxId + ";");
                }else {
                    conn.rollback();
                }


                ++started;
            }
        }

但问题是已经成功的提交无法回滚,就会造成分库或多节点间数据不一致。

 

Vitess:

Youtube出的与我们现有架构中需要注入的接口对应不上,需要改造现有接口,不太满足要求

Atlas(https://github.com/Qihoo360/Atlas):

360开源的,但是在github上发现他们似乎不太会花精力维护了,最近一次代码的更新时两年前了,另外启了事务似乎不分读写都会走主库,关于跨库方面似乎也不是很符合我们的需求。

Oceanus(https://github.com/58code/Oceanus):已经很久没维护了,而且只有37个提交。

 

DBProxy (https://github.com/Meituan-Dianping/DBProxy)

美团,C语言开发的,独立部署式的,还是希望能有一个直连的,并且有问题可以自己改的

 

sharding-jdbc https://github.com/dangdangdotcom/sharding-jdbc

当当直连数据库式的,下面是2017-03-30截的图,大版本改动太大稳定性如何,感觉还是要看一段时间再入场比较好,

最大努力送达模型,其他方面目前感觉是最合适的,分片配置成一个就是不分库

 

==========================================================

咱最近用的github:https://github.com/saaavsaaa

微信公众号:

                      

转载于:https://www.cnblogs.com/saaav/p/6651952.html

<think>嗯,用户想了解MySQL分库分表的最佳实践和设计方案。首先,我需要回忆一下分库分表的基本概念。根据引用[4],分库分表有三种方案:只分库分表、只分表分库、既分库分表。用户可能需要了解这些不同方案的适用场景。 然后,用户提到了最佳实践,引用[2]中提到不要过早优化,应该先尝试其他优化方法,比如硬件升级、读写分离、索引优化等。所以,在回答时需要强调分库分表是最后的手段,避免过度设计。 接下来,分库分表的实施步骤。可能需要包括数据评估、分片键选择、分片策略(比如范围、哈希、地理位置等)、分布式事务处理,如引用[3]提到的柔性事务,如TCC或可靠消息最终一致性。同时,动态扩容也是需要考虑的,引用[3]提到这一点,可能需要使用一致性哈希或者中间件辅助。 还要考虑分库分表的挑战,比如跨库查询、分布式事务、全局主键生成,这些都需要在设计中解决。比如,跨库查询可以通过冗余字段或拆分查询来解决,主键生成可以用雪花算法或者UUID。 另外,引用[4]提到分库分表后的维护成本增加,比如数据迁移和监控。可能需要提到工具,如ShardingSphere或MyCat,来简化管理。 用户可能还想知道具体的设计方案,比如垂直拆分和水平拆分的区别,以及如何选择分片键。例如,订单表按用户ID哈希分片,日志按时间范围分片。 最后,需要总结最佳实践,比如分片键的选择原则、避免跨分片操作、监控机制等。同时,推荐一些工具和框架,帮助用户实际应用。</think>### MySQL分库分表最佳实践与设计方案 #### 一、适用场景与前置条件 1. **适用场景** - 单表数据量超过$10^8$级别且增长迅速 - 单库QPS超过$5000$或连接数达到瓶颈 - 需要隔离业务模块(如订单、用户分离)[^4] 2. **前置优化** 分库分表前需尝试: - 硬件升级(SSD、内存扩展) - 索引优化(覆盖索引、联合索引) - 读写分离(主从架构) - 查询缓存与热点数据拆分[^2] #### 二、核心设计方案 1. **拆分维度** $$拆分类型 = \begin{cases} \text{垂直拆分(按业务模块)} \\ \text{水平拆分(按数据分布)} \end{cases}$$ - **垂直分库**:将用户表、订单表分离到不同数据库 - **水平分表**:将订单表按用户ID哈希拆分为1024个子表[^4] 2. **分片策略对比** | 策略类型 | 示例 | 优点 | 缺点 | |----------------|----------------------|--------------------|--------------------| | 哈希取模 | `user_id % 1024` | 数据均匀分布 | 扩容复杂 | | 范围分片 | 按时间区间划分 | 易于范围查询 | 可能产生热点 | | 一致性哈希 | 环形哈希空间 | 扩容影响小 | 实现复杂度高 | | 地理位置分片 | 按地域划分数据中心 | 降低跨区域延迟 | 数据分布可能不均衡 | 3. **分布式事务方案** - **柔性事务**: - TCC模式(Try-Confirm-Cancel) - 最大努力通知(异步补偿) - 可靠消息队列(最终一致性)[^3] - **刚性事务**:XA协议(性能影响较大) #### 三、实施关键步骤 1. **数据评估** 统计表增长率:$$年增长率 = \frac{\Delta data}{T} \quad (T=1年)$$ 若预测3年后数据量超过单表存储极限,则需拆分[^2] 2. **分片键选择原则** - 高频查询条件字段(如`user_id`) - 数据分布均匀(避免热点) - 业务关联性强(减少跨库JOIN) 3. **路由中间件选型** ```java // ShardingSphere示例 ShardingRuleConfiguration shardingRule = new ShardingRuleConfiguration(); shardingRule.getTableRuleConfigs().add(orderTableRule); ``` 4. **动态扩容方案** - **双倍扩容法**:新库数量=旧库×2,迁移50%数据 - **一致性哈希环**:仅迁移$\frac{1}{n+1}$数据(n为新节点数) - 工具支持:Vitess、ShardingSphere-Scaling[^3] #### 四、挑战与解决方案 1. **全局唯一ID** - Snowflake算法:$$ID = 时间戳 + 机器ID + 序列号$$ - 数据库分段发号:每次申请号段范围(如1000-2000) 2. **跨库查询** - 基因法:将关联字段嵌入分片键 - 异构索引表:创建全局搜索专用表 - 并行查询聚合:`SELECT * FROM node1_table UNION SELECT * FROM node2_table` 3. **数据迁移** 分阶段实施: ```mermaid graph LR 双写-->数据校验 数据校验-->流量切换 流量切换-->旧数据清理 ``` #### 五、最佳实践总结 1. **设计原则** - 分片粒度控制在$10^6$~$10^7$条/表 - 预留30%容量缓冲 - 避免跨分片事务(可通过冗余字段降级) 2. **监控指标** - 分片倾斜率:$$\eta = \frac{\max(count(shard_i)) - \min(count(shard_j))}{\text{总数据量}}$$ - 跨库查询比例超过5%需优化 3. **工具推荐** - 开源方案:ShardingSphere、MyCAT - 云服务:AWS Aurora、阿里云DRDS
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值