http://wangbt5191-hotmail-com.iteye.com/blogs/1736589
目前笔者在主导公司一个已有产品的改造项目, 目前在方案讨论阶段。
先介绍下目前系统的现状, 目前系统中订单相关的数据日新增量已经到了百万级别,围绕订单相关的订单分拣, 打包,发货相关操作的transaction 达到近千万级别每日。 在做了历史归档以后, db 性能还是比较吃紧, 所以我们想到了分库分表的方案
这里是中间我所提出的问题和备选方案
问题1. 分库以后登录如何做?
或者说User 登录的User 表数据存储在什么地方。
这里有两个方案:
方案1:
-
所有User 表相关的CRUD 操作都在一个含有User 表的引导库上进行, 其他业务库不需要User 表;
-
高级权限用户的新建用户, 更新和删除用户操作都会根据操作类型被路由到引导库上进行
-
用户的登录操作(读 User 表操作) 也会被路由到引导库上进行
Pros and crons
pros: 实现简单
crons: 存在单点, 一旦引导库挂了, 所有用户都不可登录
方案2: 是方案1 的折中
-
所有写操作在引导库上发生, 写操作限定在引导库上是为了使用我们User 表中的ID sequence 保证ID唯一和便于同步
-
各业务库中也存在User 表, 业务库上User 表只做读操作, 引导库上和业务库之间使用DB 复制工具对User 表数据做同步复制。
-
登录操作可以任选引导库和业务库中的任何一个db 实例做登录操作
Pros and crons
pros:不存在登录的单点问题;
corns:
- 需要对DB做额外的同步, 不过相对来说这个代价还不是太高;
- 新建用户后的时效性依赖于DB 复制的时效性;
经过讨论定下了第二套方案
问题2. 分库分表对象ID 如何做到全局唯一?
我们以前DB中各表中的primary Key都是以Numberic 作为表字段类型, 辅以对ID 字段建sequence 来保证自增长来做到唯一的; 那么分库以后问题来了, 不同库中根据seq 生成的ID 会出现重复的, 这个对业务上是不允许的, 会导致数据正确性的问题;
这里有两个方案:
方案1.
-
保留老的numberic 的ID 字段,
-
再新增char 类型的external_ID 字段,external_ID 字段对应用来说可读不可写,
-
各库对各表建create trigger, 在新增完成以后 external_ID = ${db instance number}+ "_"+ ${table_postfix} + "_"+ ${ID},
-
应用根据external_ID 中的${db instance number} 做read,update 和delete 的db路由;
- ${db instance number} 和 ${table_postfix}根据商户ID 和base 表名做规则匹配产生, 这个规则也就是固化在DB的trigger 中
在cache 中使用external_ID 为key
Pros and crons
pros: 增加的冗余字段external_ID 不需要做复杂的业务逻辑
crons:
- 今后如果要把 db1 中的部分数据迁移到新增的db 中去的时候需要对数据进行清洗(update external_ID)
- 需要新增大量的trigger, 会带来DBA 大量的工作
- trigger 会带来插入操作额外的db 开销
方案2.
-
保留老的numberic 的ID 字段, 为每个表新增Customer_ID的冗余字段,
-
业务上的新增操作由业务层指定Customer_ID, 作为App 中的唯一性ID external_ID 是由 ${Customer_ID} + "_" + ${table_postfix} +"_"+ ${ID} 产生的, 由App自己拼装, App 也可以根据Base 表名决定, 某些对象的ID只是 ${table_postfix} +"_"+ ${ID} 或者 ${Customer_ID} + "_" + ${ID}
-
在App中, app 以external_ID 作为cache 层的Key, DB 的read, update, delete 操作是做一次split, 拿到Customer_ID根据db 路由规则定位db和表, 路由到db中的表后后还是以原始id 来做底层的读写。
Pros and crons
pros:
-
不需要大量的trigger带来的额外开销
-
可以根据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/ 的博客
分享到:
相关推荐
前几天发布了kamike.db>这个ORM中间件,这几天就把我之前写的分库分表功能裁剪一下,然后基于kamike.db进行重构。 现在发布一个基本算法实现完毕的版本,模拟了jdbc的操作过程,实现分库分表。具体使用例子我还...
一个 mysql 分库 分表的脚本程序,用于自动划分mysql 库表。
NewSQL以及基于mysql分库分表的中间件的分析-DB-Analyse
基于分布式事务seata+分库分表shardingspherejdbc+nacos+dubbo项目源码.zip 1. 环境准备 - nacos: `sh ./docker/nacos/startup.sh` - seata-server - 导入配置: `sh ./docker/seata-server/conf/nacos-config.sh ...
springboot整合sharding-db按月分表分库
下面是对项目中分库分表的一些总结: 单库单表 单库单表是最常见的数据库设计,例如,有一张用户(user)表放在数据库db中,所有的用户都可以在db库中的user表中查到。 单库多表 随着用户数量的
有关ShardingSphere实现分库分表前面写了7篇博客作为该项目做详细说明。 1、 2、 3、 4、 5、 6、 7、 该项目拉下后配置数据库地址,和创建相应的库和表后就可以运行成功。 一、项目概述 1、技术架构 项目总体技术...
DB9 DB15 DB25 DB37 DB50 直型弯型针型孔型封装大全Altium库 PCB封装库90个合集(AD库): 封装型号列表: Component Count : 90 Component Name ----------------------------------------------- DB9 DB9 公 90° ...
DB9 DB15 DB25 DB37 DB50 AltiumAD元件库PCB封装库。包括90个DB9~50接插件全系列封装文件,孔型、针型、直型,90度弯型,DB9/M,DB9/F,DB15/M,DB15/F,DB25/M,DB25/F,DB37/M,DB37/F,DB50/M,DB50/F等,可以...
复制代码 代码如下://分库分表算法 function calc_hash_db($u, $s = 4) { $h = sprintf(“%u”, crc32($u)); $h1 = intval(fmod($h, $s)); return $h1; } for($i=1;$i”; } function calc_hash_tbl($u, $n = 256, $m...
• 前台、后台系统web/service/db分离解耦,避免后台低效查询引发前台查询抖动 • 可以采用数据冗余的设计方式 • 可以采用“外置索引”(例如ES搜索系统)或者“大数据处理”(例如HIVE)来满足后台变态的查询需求
DB9 DB15 DB25 等各种DB接口封装库 ,库都是经过项目验证的,能够节省不少开发时间,与大家分享。
DB9 DB15 DB25 DB37 D型公头母头连接器3D封装库(STEP后缀)文件: Connector - d-sub.STEP DB-Female.STEP DB-Male.STEP DB15RA_F.STEP DB15RA_M.STEP DB15_F.STEP DB15_M.STEP DB25 .STEP DB25-F.STEP DB25-M.STEP...
DB9/DB15/DB25/DB37/DB50/DB62/DB78封装PDF
sharding-jdbc 目录结构 sjdbc-read-write-springboot:Spring Boot版 Sharding JDBC 读写分离示列 ...sjdbc-db-sharding-table-springboot:Spring Boot版 Sharding JDBC 分库分表案例 sjdbc-db-sharding-table-rea
最后我们把order表放在了8个分库中(编号1到8,分别对应DB1到DB8),每个分库中10个分表(编号0到9,分别对应order_0到 order_9),部署结构如下图所⽰: 根据uid计算数据库编号: 数据库编号 = (uid / 10) % 8 + 1...
使用netty4.X实现的手机游戏服务器,支持tcp,udp,http,websocket链接,采用protobuf自定义协议栈进行网络通信,支持rpc远程调用,使用mybatis3支持db存储分库分表,支持异步mysql存储,db保存时同步更新reids缓存。...
DB接口(AD软件封装库)
直接执行activiti-engine-x.jar 中 /org/activiti/db/create下的DDL语句脚本 方法二: 把activiti-engine的jar放到classpath下 添加对应的数据库驱动 把Activiti配置文件 (activiti.cfg.xml) 放到 ...