`
一江春水邀明月
  • 浏览: 79011 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

DB 分库分表项目改造心得

 
阅读更多

 

http://wangbt5191-hotmail-com.iteye.com/blogs/1736589

 

目前笔者在主导公司一个已有产品的改造项目, 目前在方案讨论阶段。

先介绍下目前系统的现状, 目前系统中订单相关的数据日新增量已经到了百万级别,围绕订单相关的订单分拣, 打包,发货相关操作的transaction 达到近千万级别每日。 在做了历史归档以后, db 性能还是比较吃紧, 所以我们想到了分库分表的方案

 

这里是中间我所提出的问题和备选方案

 

问题1. 分库以后登录如何做?

或者说User 登录的User 表数据存储在什么地方。
   这里有两个方案:

    方案1:

  1.     所有User 表相关的CRUD 操作都在一个含有User 表的引导库上进行, 其他业务库不需要User 表;
  2.     高级权限用户的新建用户, 更新和删除用户操作都会根据操作类型被路由到引导库上进行
  3.     用户的登录操作(读 User 表操作) 也会被路由到引导库上进行

    Pros  and  crons
    pros: 实现简单
    crons: 存在单点, 一旦引导库挂了, 所有用户都不可登录

    方案2: 是方案1 的折中

  1.   所有写操作在引导库上发生, 写操作限定在引导库上是为了使用我们User 表中的ID sequence 保证ID唯一和便于同步
  2.   各业务库中也存在User 表, 业务库上User 表只做读操作, 引导库上和业务库之间使用DB 复制工具对User 表数据做同步复制。
  3.   登录操作可以任选引导库和业务库中的任何一个db 实例做登录操作

    Pros  and  crons
    pros:不存在登录的单点问题;
    corns:

  1. 需要对DB做额外的同步, 不过相对来说这个代价还不是太高;
  2. 新建用户后的时效性依赖于DB 复制的时效性;

 

   经过讨论定下了第二套方案

问题2. 分库分表对象ID 如何做到全局唯一?

     我们以前DB中各表中的primary Key都是以Numberic 作为表字段类型, 辅以对ID 字段建sequence 来保证自增长来做到唯一的; 那么分库以后问题来了, 不同库中根据seq 生成的ID 会出现重复的, 这个对业务上是不允许的, 会导致数据正确性的问题;
     这里有两个方案:

    方案1.

  1.     保留老的numberic 的ID 字段,
  2.     再新增char 类型的external_ID 字段,external_ID 字段对应用来说可读不可写, 
  3.     各库对各表建create trigger, 在新增完成以后 external_ID = ${db instance number}+ "_"+ ${table_postfix} + "_"+ ${ID},
  4.     应用根据external_ID 中的${db instance number} 做read,update 和delete 的db路由;
  5.     ${db instance number} 和 ${table_postfix}根据商户ID 和base 表名做规则匹配产生, 这个规则也就是固化在DB的trigger 中

    在cache 中使用external_ID 为key
    Pros  and  crons
    pros: 增加的冗余字段external_ID 不需要做复杂的业务逻辑
        crons:

  1. 今后如果要把 db1 中的部分数据迁移到新增的db 中去的时候需要对数据进行清洗(update external_ID)
  2.  需要新增大量的trigger, 会带来DBA 大量的工作
  3.  trigger 会带来插入操作额外的db 开销

  


    方案2.

  1.     保留老的numberic 的ID 字段, 为每个表新增Customer_ID的冗余字段,
  2.     业务上的新增操作由业务层指定Customer_ID, 作为App 中的唯一性ID external_ID 是由 ${Customer_ID} + "_" + ${table_postfix} +"_"+ ${ID} 产生的, 由App自己拼装, App 也可以根据Base 表名决定, 某些对象的ID只是 ${table_postfix} +"_"+ ${ID} 或者 ${Customer_ID} + "_" + ${ID}
  3.       在App中, app 以external_ID 作为cache 层的Key, DB 的read, update, delete 操作是做一次split, 拿到Customer_ID根据db 路由规则定位db和表, 路由到db中的表后后还是以原始id 来做底层的读写。

    Pros  and  crons
        pros:

  1. 不需要大量的trigger带来的额外开销
  2. 可以根据Customer_ID和db 的对应关系自由的建立db 路由规则, 今后如果把某个db 实例中的部分Customer_ID相关的数据迁移到新的实例中, 只要更改路由规则就可以了, 可以对DB 和应用的业务层透明

        crons:分库数据迁移过程中, 有若干业务表还没有Customer_ID字段冗余, 这个需要做前期的准备

 

经过讨论定下了第二套方案

 

 

问题3. 分库后跨DB实例的事务如何处理?

根据我们现在的业务模型, 按照Customer_ID 做水平切分以后, 让客户相关的操作在一个request 访问的生命周期的DB hit 都落在一个db 实例上, 从而规避掉这个问题。

 

 

 

代码演示

Talk is cheap, show me the code. 

好吧, 我来上代码, 这个Demo 是基于mybatis 官网上的jpetstore 的例子, 这个例子做了以下几个功能点的演示:

1. 根据规则hit 到不同的db 实例(实例0 和实例1)上

2. 在db 实例0 上, 我们对product 表做了分表处理, 根据规则hit 不同的表

 

 

它的实现思路是:

1. 分库实现: 是改写SqlSessionDaoSupport 和MapperFactory Bean , 在SqlSessionDaoSupport 中的 SqlSession sqlSession 属性换成   List<SqlSession> sqlSessions, 在拿getSqlSession() 方法中写入规则来动态获取SqlSession;

2. 分表实现: 使用开源框架shardbatis, 详细信息可以参考http://seanhe.iteye.com/ 的博客

 

 

 

 

 

 

 

分享到:
评论

相关推荐

    分库分表Sharding中间件Kamike.divide.zip

    前几天发布了kamike.db&gt;这个ORM中间件,这几天就把我之前写的分库分表功能裁剪一下,然后基于kamike.db进行重构。 现在发布一个基本算法实现完毕的版本,模拟了jdbc的操作过程,实现分库分表。具体使用例子我还...

    创建DB 分库分表脚本

    一个 mysql 分库 分表的脚本程序,用于自动划分mysql 库表。

    SpringBoot + ShardingSphere分库分表实战(附完整代码)

    【SpringBoot + ShardingSphere分库分表实战】 在应对大数据量的系统中,分库分表是一种常见的解决策略,可以有效地分散数据库压力,提高系统的处理能力。在Java开发领域,ShardingSphere是一个广泛使用的开源...

    数据库分库分表

    例如,`common-db-route`可能是一个通用的数据库路由模块,它负责根据业务逻辑和分库分表策略,将SQL语句路由到正确的数据库和表上。`db-route-demo`可能是这个路由机制的示例代码,展示了如何在实际项目中实现数据...

    MYCAT分库分表

    ### MYCAT分库分表详解 #### 一、概述 在大数据时代,单一数据库服务器往往难以满足日益增长的数据处理需求。为了提高数据处理能力、优化系统性能,分库分表技术逐渐成为解决这一问题的有效手段之一。Mycat作为一...

    spring+mybatis+sharding-jdbc 1.3.1实现分库分表案例(可直接运行)

    在现代企业级应用中,随着数据量的增长,单表存储可能会遇到性能瓶颈,这时就需要引入分库分表策略来优化数据库架构。本案例基于Spring、MyBatis和Sharding-JDBC 1.3.1版本,提供了一个可以直接运行的分库分表实现,...

    mysql大数据分库和分表 php解决方案

    在这种背景下,单一数据库往往难以承受巨大的数据处理压力,因此,采用分库分表技术成为了提高数据库性能的有效手段之一。本文主要探讨MySQL大数据分库和分表的PHP解决方案,并通过具体的案例分析来加深理解。 ####...

    MySQL分库分表.doc

    MySQL分库分表是一种应对大数据量和高并发场景下的数据库优化策略,旨在提高数据库系统的性能、可用性和可扩展性。MYCAT(曾用名:Maatkit)是一款开源的数据库中间件,它允许开发者将MySQL数据库集群化,实现分库...

    SpringBoot(49) 整合sharding-jdbc实现自定义分库分表

    在本教程中,我们将深入探讨如何使用SpringBoot与Sharding-JDBC进行集成,以实现自定义的数据库分库分表策略。Sharding-JDBC是Apache软件基金会下的一个轻量级Java框架,它允许开发者在不改变原有业务代码和数据库...

    NewSQL以及基于mysql分库分表的中间件的分析-DB-Analyse.zip

    在现代大数据和高并发的背景下,数据库技术的发展不断推陈出新,NewSQL与MySQL的分库分表中间件成为了应对挑战的重要手段。本分析主要探讨这两种技术,并深入理解它们在实际应用中的优缺点。 首先,让我们来了解...

    ShardingJDBC5.1.1按月分库分表、读写分离、自动创表完整demo

    《使用ShardingJDBC5.1.1实现按月分库分表、读写分离与自动创表的全面实战》 在现代企业级应用中,数据量的快速增长使得数据库的性能优化成为至关重要的环节。ShardingJDBC作为一款轻量级的Java框架,能够有效地...

    分库分表-zdal

    ### 分库分表-zdal #### 一、概述与需求背景 **Zdal**作为一款由支付宝自主研发的数据中间件产品,其设计初衷是为了应对日益增长的海量数据处理需求以及传统数据库面临的性能瓶颈问题。该产品遵循JDBC规范,能够在...

    根据最新版本4.1.1实现的分库分表案例

    "分库分表"是一种有效的数据库架构优化策略,它可以将一个大型单一数据库分解为多个小型数据库,以提高查询效率,降低单表压力。在这个"根据最新版本4.1.1实现的分库分表案例"中,我们将重点探讨如何利用Sharding...

    mysql读写分离,分库分表-MysqlSample.zip

    MySQL数据库在面临高并发、大数据量的业务场景时,为了保证系统的稳定性和性能,通常会采用读写分离和分库分表的技术策略。本篇将详细介绍这两种技术,并结合"mysql读写分离,分库分表-MysqlSample"的示例进行讲解。...

    spring boot整合sharding jdbc5.2.0分库分表demo

    本文将深入探讨如何在Spring Boot项目中集成ShardingSphere 5.2.0,并演示其实现分库分表的全过程。 ### 1. ShardingSphere简介 ShardingSphere 是一个分布式数据库解决方案的集合,包含Sharding-JDBC、Sharding-...

    sharding-db按月分表分库

    本文将深入探讨“sharding-db按月分表分库”这一主题,结合SpringBoot的整合应用,来阐述如何设计和实现这样一个分布式数据库系统。 首先,我们需要理解“分库分表”的概念。当单个数据库无法承受大量的数据存储和...

    03-Mycat分库分表.pdf

    Mycat是一个开源的数据库中间件,它在MySQL集群架构下提供高可用性、分库分表、读写分离等功能,是数据库架构分库分表的优秀解决方案。Mycat能够实现数据的水平切分(Sharding),即将一个数据库切分成多个分片,...

    基于分布式事务seata+分库分表shardingspherejdbc+nacos+dubbo项目源码.zip

    基于分布式事务seata+分库分表shardingspherejdbc+nacos+dubbo项目源码.zip 1. 环境准备 - nacos: `sh ./docker/nacos/startup.sh` - seata-server - 导入配置: `sh ./docker/seata-server/conf/nacos-config.sh ...

Global site tag (gtag.js) - Google Analytics