透明的分库分表方案

简介:

问题提出

随着应用规模的不断扩大,单机数据库就慢慢无法满足应用的需要了,这主要表现在如下方面:

  1. 存量数据越来越大,查询速度越来越慢
  2. 访问并发越来越大,磁盘IO、网络IO、CPU都慢慢成为瓶颈
  3. 事务数越来越多,事务冲突越来越严重,导致TPS越来越少

这个时候,有的人采用了换商用数据库的方案比如Oracle,然后用Oracle的RAC方式进行水平扩展。但是带来的缺点也比较明显,第一是成本太高,一般人吃不消;第二,管理复杂度较单节点有非常大的提升,风险及管理成本也相应增加;第三,对人员的水平要求更高,如果做不好,在某些场景下甚至不如单节点来得快;第四,随着集群规模的变大,性能提升幅度与加入的节点数非正比关系,所以经济性也不太好。

因此,本人的结论是,短时间内采用Oracle等商用大型数据库阶段性的解决一段问题是可以的,但是从长久来说,还是治标不治本的。

因此当数据库处理能力不足的时候,还是要想办法对现有数据库进行的扩展为好。

解决方案

数据库处理性能不足的时候,一般有两种解决方案,一种是垂直扩展,一种是水平扩展。

  • 垂直扩展方案

        优势:业务代码不需要进行任何附加处理

        劣势:费用增加远超过扩展的处理能力
                通过增加硬件扩展的性能最终有其极
                限
网络IO处理瓶颈无法解决
                随着数据量的增加,性能下降加快

  • 水平扩展方案

        优势:磁盘IO、网络IO、CPU、内存分散到不同的机器上

                水平扩展处理能力与花费的成本成正比
                可以接近无限的对处理能力进行扩展

        劣势:对于业务有一定的限制条件
                跨库关联查询不被支持
                对于分库分表及应用需求要有系统的分析

简单的总结一下就是,采用垂直扩展方式,只能短时间解决问题,由于其能增加的性能最终是有极限的,因此不是终极解决方案;而水平扩展方案则几乎有无限的扩展能力,但是对设计人员的设计能力有要求,对于数据库中一些极特殊的SQL语句不支持。

需求分析

Tiny框架设计者当然不会做暂时的方案,当然想得是长久之计,于是毫无疑问要做水平扩展方案(当然,垂直扩展方案和软件几乎没有什么关系,咱也做不了),做之前首先扩展以下的需求:

  • 采用Java技术来实现
  • 要支持常见数据库,主要是能支持所有有JDBC Driver的数据库
  • 支持自增长主键,这样原来依赖自增长主键的数据库应用就不需要在这方面做特殊处理了
  • 支持数据库分页语句,这样原来依赖数据库分页语句的数据库应用就不需要在这方面做特殊处理了
  • 能支持绝大多数的SQL语句
  • 在性能方面最好能接近JDBC驱动
  • 有良好的扩展性,数据库设计者可以方便的进行定制扩展
  • 支持读写分离,负载均衡实现算法可定制
  • 支持分库
  • 支持分表
  • 对事务有良好的支持
  • 对统计及排序有良好的支持

系统设计与实现

实现方案及比较

数据库分区分表方案的实现方式有多种:

  • DAO层:实现难度低、业务代码耦合程度高、业务开发成本高、重构成本高,可复用性较差
  • DataSource层:实现难度中,业务代码耦合程度低、业务开发成本低、重构成本低、可复用性中
  • JDBC层:实现难度高,业务代码耦合程度低、业务开发成本低、重构成本、可复用性好
  • 代理层:实现难度高,业务代码耦合程度低、业务开发成本低、重构成本、可复用性好

Tiny框架采用了在JDBC层实现的方案,这种方案较代理层方面,可以少了网络通信方面的实现,所以代码量少、稳定性高,同时性能方面少一倍的网络通信,所以性能更高。

Tiny分库分表设计方案


    稍解释一下:

    当TinyDBRouter收到一个SQL时,首先对SQL进行解析,然后根据分库和分表规则路由到合适的真实数据库去执行,然后把执行的结果进行处理,然后把结果正确的提供给数据库请求者,一次交互就完整的完成了。

    当然,实际的处理过程则远比这个要复杂得多,因为要考虑到事务的一致性、处理的高效性、结果的正确性,这里面的道道就多了,说起来比较漫长,这里就简单略过。

    应用实例

    使用方法

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    Class.forName( "org.tinygroup.dbRouterjdbc3.jdbc.TinyDriver" );
    Connection conn = DriverManager.getConnection( "jdbc:dbRouter://Router1" , “username ", “password" );
    Statement stmt = conn.createStatement();
    String sql;
    for ( int i = 0 ; i < 10 ; i++) {
         sql = "insert into aaa(aaa) values ('ppp')" ;
         stmt.execute(sql);
    }



    嗯嗯,上面就是使用方式了,熟悉JDBC的同学们马上就可以发现,这个和普通的JDBC程序没有什么不同么?确实是这样,使用TinyDBRouter,实际开发过程,与原来没有任何不同,不管是你用JDBC,还是Spring JDBC Template,还是iBatis、Hibernate,不管是任何的Java ORM框架,统统都可以使用。

    唯一需要注意的就是,要把原来的URL和Driver改成Tiny的。

    那其它的数据库管理工具,可以使用么?当然可以,只要是基于Java做的数据库管理工具,只要把Tiny的Driver相关的Jar包放入其ClassPath路径,就可以使用了。

    其实对于统计方面的支持,对于所有的分库分表框架来说都是极具挑战性的,比如许多的分库分表框架要求每次SQL只能落在一个分片上执行,才能保证结果的正确性;比如许多的分库分表框架都要求统计时不能有排序等等,甚至有的直接就不支持,欢迎同学们让他们对号入座。

    TinyDBRouter唯一的限制是:

    不支持跨库关联查询

    当然,几乎所有的都不支持这个特性,少量号称支持,实际上没有可用性---因为性能实在是太慢了,数据量如果大一点就死翘翘了。

    常见问题问答

    1. 像MySQL、SQL Server中的自增长主键需要特殊处理么?答案:不需要,原有程序照样使用就好
    2. 像M ySQL、SQL Server中的分页SQL可以原样使用么?答案:必须可以
    3. TinyDBRouter支持的SQL语句支持的多么?答案:支持SQL92规范的绝大部分SQL语句(极少量不支持)
    4. 支持Having语句不?答案:支持
    5. 原有项目的代码重构成本高么?答案:这个和DBA制订的数据分区方案有关,只要不违反上面的限制条件都可以不修改。
    6. 我把主表和从表都分到一个分片中,关联只在相同分片中发生,这种情况下,代码需要修改吗?答案:不需要。

    总结

    Tiny框架的所有部件或子项目,我们从来不加吸引眼球的“最”字,我们相信只要我们扎扎实实的努力加上轻灵优雅的设计,一定会是相关问题领域中一个相当不错的解。

    相关文章
    |
    安全 Windows
    Win10/Win11如何获取最高管理员权限
    Win10/Win11如何获取最高管理员权限
    4665 0
    |
    8月前
    |
    XML Java 数据格式
    《深入理解Spring》:AOP面向切面编程深度解析
    Spring AOP通过代理模式实现面向切面编程,将日志、事务等横切关注点与业务逻辑分离。支持注解、XML和编程式配置,提供五种通知类型及丰富切点表达式,助力构建高内聚、低耦合的可维护系统。
    |
    8月前
    |
    存储 缓存 Kubernetes
    Kubernetes 场景下的 StarRocks 灾备体系:Cluster Snapshot 实践解析
    在 3.5 版本 中,StarRocks 推出了全新的 Cluster Snapshot 快照恢复机制,进一步完善了数据安全与灾备体系。 Snapshot 提供了一种高效、低成本、自动化的数据保护方式,显著提升系统的可用性与容灾能力,弥补了此前存算分离架构在备份与恢复方面的空缺。 当系统发生故障、误操作或区域性宕机时,Snapshot 可在分钟级完成快速恢复,最大限度减少数据丢失与业务中断风险。通过将完整集群状态进行快照化并备份至对象存储,Snapshot 简化了传统灾备方案的复杂流程,使灾难恢复更加高效与便捷。这一机制尤其适用于 金融、零售、SaaS 等对系统稳定性要求极高的关键业务场景。
    |
    6月前
    |
    人工智能 自然语言处理 搜索推荐
    企业 AI 客服系统怎么建?免费工具推荐、成本测算与选型攻略
    2025年,AI客服系统成为企业提升服务效率与客户体验的核心工具。面对用户对7×24小时响应、个性化交互的高要求,传统客服难以应对。AI客服通过自然语言处理与自动化技术,实现高效应答、降本增效,并释放人力处理复杂问题。超60%企业已在客户触点部署AI能力,智能客服正从“可选”变为“必备”。
    |
    6月前
    |
    SQL 关系型数据库 MySQL
    聊下几次线上删除MySQL导致的故障
    本文通过真实案例解析MySQL中删除大表数据的高危操作及底层原理,揭示DROP TABLE和批量DELETE引发的IO风暴与主从延迟问题,并提供6种可落地的优化方案,涵盖分批删除、并行复制、分区表设计等,助力研发与DBA安全高效处理大数据量删除。
    448 2
    聊下几次线上删除MySQL导致的故障
    |
    6月前
    |
    SQL 人工智能 数据可视化
    用Coze搭建四阶工作流:AI赋能测试全链路提效实战
    在现代软件开发中,测试常成瓶颈。本文介绍如何利用Coze平台,结合大语言模型,打造“测试提效大师”AI助手,构建覆盖需求解析、用例设计、执行辅助与缺陷管理的四阶智能工作流。通过可视化流程、知识库集成与系统联动,实现测试全链路提效,助力测试工程师从执行者迈向策略师。
    |
    安全 网络安全 Python
    应对requests 2.28.x版本中SSL证书验证失败的错误处理方法。
    在你安全地解决了这一切之后,你的请求就能够在HTTPS的加持下,犹如骑士横扫战场,高枕无忧地传递信息了。记住,网络的世界里,安全永远是你的头号任务。遵循正道,才能让你的代码在数据的草原上,驰骋千里。
    586 16
    |
    Python
    md文件格式转成word文档
    md文件格式转成word文档
    1704 1
    |
    SQL 缓存 关系型数据库
    MySQL 深潜 - Semijoin 丛林小道全览
    作者深入内核讲述了 MySQL semijoin 从识别到优化器根据代价决定最优执行策略,以及执行方式的全过程,掌握 MySQL semijoin 这一篇就够了!
    |
    安全 网络安全
    SSH——云服务器SSH经常断开如何处理
    SSH——云服务器SSH经常断开如何处理
    1615 0

    热门文章

    最新文章