博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
一次分库分分表实践
阅读量:2402 次
发布时间:2019-05-10

本文共 4910 字,大约阅读时间需要 16 分钟。

用户中心 分库分表

接到一个项目,pm号称这个项目用户是千万级别,从来没接触过这么大用户,心里狂颤抖,借次机会玩一把分库分表,一直都是听人说,就是没有用过。

分库分表常用中间件

简单易用的组件:

当当sharding-jdbc

蘑菇街TSharding
强悍重量级的中间件:

sharding

TDDL Smart Client的方式(淘宝)
Atlas(Qihoo 360)
alibaba.cobar(是阿里巴巴(B2B)部门开发)
MyCAT(基于阿里开源的Cobar产品而研发)
Oceanus(58同城数据库中间件)
OneProxy(支付宝首席架构师楼方鑫开发)
vitess(谷歌开发的数据库中间件)
https://github.com/searchq=%E5%88%86%E5%BA%93%E5%88%86%E8%A1%A8
对比了一下,最后选择了 sharding-jdbc :

  • 对上次应用几乎是无感
  • 这家伙刚刚apache 毕业
  • 社区活跃
  • 评测数据

常用分库分表策略

水平和垂直分库,垂直分库一般不会台纠结,根据服务域都做相应的分库处理。而水平分库分表常用策略:

  • 取模法:ID取模、hash 取模,
  • 范围:根据日期、范围
  • 两者组合
    系统设计的用户和用户认证信息表
    User(id,tel,name,idcard)
    User_Auth(id,user_id,auth_tpye)
    用户登陆,根据手机号码登陆,多种人认证登陆;而且用户可以修改手机号码,信息等在设计分库分表用户User 和User_Auth 还是根据用户id 进行分库分表,在添加一个Tel_User_sharding (tel ,usrid) 根据手机号码进行分库分表 。
    User(id,tel,name,idcard) -----------usrid
    User_Auth(id,user_id,auth_tpye) -----------usrid
    Tel_User_sharding(tel ,usrid) -----------tel
    用户在变更手机号码,修改Tel_User_sharding 信息,而User,User_Auth
    不需要变化。这种设计代理弊端是要多访问一次数据库,也米有想到更好办法解决。

接入sharding-jdbc

项目用到是spring boot 2.2 mybatis-plus, 数据源用HikariDataSource

引入maven 依赖

org.apache.shardingsphere
sharding-jdbc-spring-boot-starter
4.1.0

配置配置文件

网上看到3.0 和4.0 配置文件很多都不一样,踩了很多坑,我们配置了一个默认数据源,读写分离,两个一主一从,贴出全部配置,

spring:
shardingsphere:
datasource:
names: mds0,sds0,mds1,sds1,mdsm
# 数据源ds0
mdsm:
type: com.zaxxer.hikari.HikariDataSource
driverClassName: com.mysql.cj.jdbc.Driver
jdbcUrl: jdbc:mysql://:3306/qinqing_dev?characterEncoding=utf8&useSSL=true&autoReconnect=true&serverTimezone=Asia/Shanghai
username: root
password:
minimumIdle: 5
maximumPoolSize: 30
maximumWait: 10000
isAutoCommit: true
idleTimeout: 30000
poolName: hikari-db0
maxLifetime: 900000
connectionTimeout: 15000
connectionTestQuery: SELECT 1
mds0:
type: com.zaxxer.hikari.HikariDataSource
driverClassName: com.mysql.cj.jdbc.Driver
jdbcUrl: jdbc:mysql:/:3306/test?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
username: spring
password:
minimumIdle: 5
maximumPoolSize: 30
maximumWait: 10000
isAutoCommit: true
idleTimeout: 30000
poolName: hikari-db0
maxLifetime: 900000
connectionTimeout: 15000
connectionTestQuery: SELECT 1
# 数据源ds1
sds0:
type: com.zaxxer.hikari.HikariDataSource
driverClassName: com.mysql.cj.jdbc.Driver
jdbcUrl: jdbc:mysql://:3306/test?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
username: spring
password:
minimumIdle: 5
maximumPoolSize: 30
maximumWait: 10000
isAutoCommit: true
idleTimeout: 30000
poolName: hikari-db0
maxLifetime: 900000
connectionTimeout: 15000
connectionTestQuery: SELECT 1
mds1:
type: com.zaxxer.hikari.HikariDataSource
driverClassName: com.mysql.cj.jdbc.Driver
jdbcUrl: jdbc:mysql://:3306/test1?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
username: spring
password:
minimumIdle: 5
maximumPoolSize: 30
maximumWait: 10000
isAutoCommit: true
idleTimeout: 30000
poolName: hikari-db0
maxLifetime: 900000
connectionTimeout: 15000
connectionTestQuery: SELECT 1
# 数据源ds1
sds1:
type: com.zaxxer.hikari.HikariDataSource
driverClassName: com.mysql.cj.jdbc.Driver
jdbcUrl: jdbc:mysql://:3306/test1?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
username: spring
password:
minimumIdle: 5
maximumPoolSize: 30
maximumWait: 10000
isAutoCommit: true
idleTimeout: 30000
poolName: hikari-db0
maxLifetime: 900000
connectionTimeout: 15000
connectionTestQuery: SELECT 1
props:
sql.show: true
sharding:
default-data-source-name: mdsm
tables:
dnstime: #t_user表
key-generator-column-name: id #主键
actual-data-nodes: mds − > 0..1. d n s t i m e ->{0..1}.dnstime >0..1.dnstime->{0…1} #数据节点,均匀分布
database-strategy: #分库策略
inline: #行表达式
sharding-column: id #列名称,多个列以逗号分隔
algorithm-expression: mdsKaTeX parse error: Expected '}', got '#' at position 50: …ble-strategy: #̲分表策略 …->{id % 2}
# t_address:
# key-generator-column-name: id
# actual-data-nodes: dsKaTeX parse error: Expected 'EOF', got '#' at position 22: ….t_address #̲ datab…{lit % 2}
master-slave-rules:
master-data-source-name:
mds0:
master-data-source-name: mds0
slave-data-source-names: sds0
mds1:
master-data-source-name: mds1
slave-data-source-names: sds1

spring @Transactional 在跨库是否生效?

完全支持非跨库事务,例如:仅分表,或分库但是路由的结果在单库中。

完全支持因逻辑异常导致的跨库事务。例如:同一事务中,跨两个库更新。更新完毕后,抛出空指针,则两个库的内容都能回滚。

不支持因网络、硬件异常导致的跨库事务。例如:同一事务中,跨两个库更新,更新完毕后、未提交之前,第一个库死机,则只有第二个库数据提交

TransactionInterceptor 中

public Object invoke(MethodInvocation invocation) throws Throwable 方法
在这里插入图片描述

Connection 已被shardingconnection 接管

最后由ForceExecuteTemplate 提交执行
public void execute(final Collection targets, final ForceExecuteCallback callback) throws SQLException {
Collection exceptions = new LinkedList<>();
for (T each : targets) {
try {
callback.execute(each);
} catch (final SQLException ex) {
exceptions.add(ex);
}
}
throwSQLExceptionIfNecessary(exceptions);
}

转载地址:http://ynpob.baihongyu.com/

你可能感兴趣的文章
将回收站变成保密站(转)
查看>>
制作Windows2000启动的“机密钥匙”(转)
查看>>
小心防范最易被黑客盯上的注册表位置(转)
查看>>
用注册表对系统进行全方位维护和管理(转)
查看>>
修改注册表阻止OfficeXP发送错误报告(转)
查看>>
不再费时费力两招快速定位注册表项(转)
查看>>
Win2K无盘终端网组建全攻略(6)(转)
查看>>
星期四(转)
查看>>
重装WinXP前必须进行的十大备份(转)
查看>>
企业容灾备份机制的建立--未雨绸缪的选择(转)
查看>>
rundll32.exe命令使用大法(转)
查看>>
Java 独占锁|共享锁|互斥锁
查看>>
Java 爬虫入门
查看>>
设计模式|七大原则及案例分析
查看>>
UML 介绍
查看>>
设计模式 单例模式的8种写法及分析
查看>>
添加,删除表单项
查看>>
makefile详解(5)
查看>>
makefile详解(6)
查看>>
运用autoconf和automake自动生成Makefile实例讲解
查看>>