点击展开正文内容

背景介绍

如果你的系统需要提高并发,那么你需要进行分库,如果你的系统需要支持海量数据,那么你需要进行分表。分库分表之后,应用这边如何才能做到跟单库单表一样简单。有很多开源软件来支持分库分表,现在比较常用的是 sharding-jdbc,mycat 框架。今天来讲讲 sharding-jdbc,示例实现了:数据分片、读写分离、数据分片 + 读写分离、数据治理的功能。

整体项目

imagepng
说明:
数据分片:两个数据库 uc0、uc1 每个数据库两种表 user0、user1
读写分离:一个主库,一个从库
数据分片 + 读写分离:两个主库、两个从库、每个库里存在两种表

pom 配置

<dependency>
	<groupId>org.mybatis.spring.boot</groupId>
	<artifactId>mybatis-spring-boot-starter</artifactId>
	<version>1.3.2</version>
</dependency>
<!--  使用数据治理需要加入 -->
<dependency>
	<groupId>io.shardingsphere</groupId>
	<artifactId>sharding-orchestration-reg-zookeeper-curator</artifactId>
	<version>${sharding-sphere.version}</version>
</dependency>
<dependency>
	<groupId>io.shardingsphere</groupId>
	<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
	<version>${sharding-sphere.version}</version>
</dependency>

核心代码

UserService:为 service 接口。
UserServiceImpl:为 service 实现类。
UserDao:

@Mapper
public interface UserDao {

  User getById(Long id);

 void insert(User user);

 void update(User user);

}

ShardingJdbcApplicationTests: 为测试类。

配置

UserDao.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cimu.shardingjdbc.mapper.UserDao">

  <resultMap id="BaseResultMap" type="com.cimu.shardingjdbc.entity.User" >
	  <id column="id" property="id" jdbcType="INTEGER" />
	  <result column="real_name" property="realName" jdbcType="VARCHAR" />
	  <result column="mobile" property="mobile" jdbcType="VARCHAR" />
	  <result column="password" property="password" jdbcType="VARCHAR" />
  </resultMap>

  <sql id="Base_Column_List">
	  id, real_name, mobile, password
  </sql>

  <select id="getById" resultMap="BaseResultMap" parameterType="java.lang.Long">
	  select
	  <include refid="Base_Column_List" />
	  from user
	  where id=#{id}
  </select>

  <insert id="insert" parameterType="com.cimu.shardingjdbc.entity.User" useGeneratedKeys="true" keyProperty="id">
	  insert into user
	  (
	  `id`,
	  `real_name`,
	  `mobile`,
	  `create_time`,
	  `update_time`,
	  `del_flag`
	  )
	  values
	  (
	  #{id},
	  #{realName},
	  #{mobile},
	  #{createTime},
	  #{updateTime},
	  #{delFlag}
	  )
  </insert>

  <update id="update" parameterType="com.cimu.shardingjdbc.entity.User">
	  update user
	  <set>
		  <if test="realName != null ">`real_name` = #{realName},</if>
		  <if test="mobile != null ">`mobile` = #{mobile},</if>
		  <if test="createTime != null ">`create_time` = #{createTime},</if>
		  <if test="updateTime != null ">`update_time` = #{updateTime},</if>
		  <if test="delFlag != null ">`del_flag` = #{delFlag},</if>
	  </set>
	  where id = #{id}
  </update>

</mapper>

application.properties

##==========================只支持分片配置=====start======================================
##数据源的名称,多个以短号隔开
#sharding.jdbc.datasource.names=uc0,uc1
##数据源的配置
#sharding.jdbc.datasource.uc0.type=com.zaxxer.hikari.HikariDataSource
#sharding.jdbc.datasource.uc0.driver-class-name=com.mysql.jdbc.Driver
#sharding.jdbc.datasource.uc0.jdbcUrl=jdbc:mysql://127.0.0.1:3306/uc0?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
#sharding.jdbc.datasource.uc0.username=root
#sharding.jdbc.datasource.uc0.password=
##数据源的配置
#sharding.jdbc.datasource.uc1.type=com.zaxxer.hikari.HikariDataSource
#sharding.jdbc.datasource.uc1.driver-class-name=com.mysql.jdbc.Driver
#sharding.jdbc.datasource.uc1.jdbcUrl=jdbc:mysql://127.0.0.1:3306/uc1?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
#sharding.jdbc.datasource.uc1.username=root
#sharding.jdbc.datasource.uc1.password=
##默认的数据库分片策略,如果没有指定具体某个数据库的分片策略,那么使用默认分片策略
#sharding.jdbc.config.sharding.default-database-strategy.inline.sharding-column=id
#sharding.jdbc.config.sharding.default-database-strategy.inline.algorithm-expression=uc$->{id % 2}
##id.intdiv(2) % 2 : 根据id进行分片,先对数据库数量进行取余,在对表数量进行取模。这个作用是让数据可以更加均匀的分布在不同表中。
##$->{0..1}  是行表达式标识符,uc$->{0..1}表示uc0,uc1
#sharding.jdbc.config.sharding.tables.user.actual-data-nodes=uc$->{0..1}.user$->{0..1}
#sharding.jdbc.config.sharding.tables.user.table-strategy.inline.sharding-column=id
#sharding.jdbc.config.sharding.tables.user.table-strategy.inline.algorithm-expression=user$->{id.intdiv(2) % 2}
##是否开启SQL显示,默认值: false
#sharding.jdbc.config.sharding.props.sql.show=true
##==========================只支持分片配置======end=====================================

##==========================只支持读写分离配置=====start======================================
##数据源的名称,多个以短号隔开
#sharding.jdbc.datasource.names=ucmaster,ucslave0
##数据源的配置
#sharding.jdbc.datasource.ucmaster.type=com.zaxxer.hikari.HikariDataSource
#sharding.jdbc.datasource.ucmaster.driver-class-name=com.mysql.jdbc.Driver
#sharding.jdbc.datasource.ucmaster.jdbcUrl=jdbc:mysql://127.0.0.1:3306/uc0?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
#sharding.jdbc.datasource.ucmaster.username=root
#sharding.jdbc.datasource.ucmaster.password=
##数据源的配置
#sharding.jdbc.datasource.ucslave0.type=com.zaxxer.hikari.HikariDataSource
#sharding.jdbc.datasource.ucslave0.driver-class-name=com.mysql.jdbc.Driver
#sharding.jdbc.datasource.ucslave0.jdbcUrl=jdbc:mysql://127.0.0.1:3306/uc1?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
#sharding.jdbc.datasource.ucslave0.username=root
#sharding.jdbc.datasource.ucslave0.password=
##从库负载均衡算法类型,可选值:ROUND_ROBIN,RANDOM。若`load-balance-algorithm-class-name`存在则忽略该配置
#sharding.jdbc.config.masterslave.load-balance-algorithm-type=round_robin
#sharding.jdbc.config.masterslave.name=ms
##主库数据源名称
#sharding.jdbc.config.masterslave.master-data-source-name=ucmaster
##从库数据源名称列表,多个以逗号隔开
#sharding.jdbc.config.masterslave.slave-data-source-names=ucslave0
##是否开启SQL显示,默认值: false
#sharding.jdbc.config.masterslave.props.sql.show=true
##==========================只支持读写分离配置======end=====================================

##==========================数据分片+读写分离配置=====start======================================
#数据源的名称,多个以短号隔开
sharding.jdbc.datasource.names=master0,master1,uc0slave0,uc1slave0
#master数据源的配置
sharding.jdbc.datasource.master0.type=com.zaxxer.hikari.HikariDataSource
sharding.jdbc.datasource.master0.driver-class-name=com.mysql.jdbc.Driver
sharding.jdbc.datasource.master0.jdbcUrl=jdbc:mysql://127.0.0.1:3306/uc0?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
sharding.jdbc.datasource.master0.username=root
sharding.jdbc.datasource.master0.password=
#slave数据源的配置
sharding.jdbc.datasource.uc0slave0.type=com.zaxxer.hikari.HikariDataSource
sharding.jdbc.datasource.uc0slave0.driver-class-name=com.mysql.jdbc.Driver
sharding.jdbc.datasource.uc0slave0.jdbcUrl=jdbc:mysql://127.0.0.1:3306/uc0slave0?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
sharding.jdbc.datasource.uc0slave0.username=root
sharding.jdbc.datasource.uc0slave0.password=
#master数据源的配置
sharding.jdbc.datasource.master1.type=com.zaxxer.hikari.HikariDataSource
sharding.jdbc.datasource.master1.driver-class-name=com.mysql.jdbc.Driver
sharding.jdbc.datasource.master1.jdbcUrl=jdbc:mysql://127.0.0.1:3306/uc1?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
sharding.jdbc.datasource.master1.username=root
sharding.jdbc.datasource.master1.password=
#slave数据源的配置
sharding.jdbc.datasource.uc1slave0.type=com.zaxxer.hikari.HikariDataSource
sharding.jdbc.datasource.uc1slave0.driver-class-name=com.mysql.jdbc.Driver
sharding.jdbc.datasource.uc1slave0.jdbcUrl=jdbc:mysql://127.0.0.1:3306/uc1slave0?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
sharding.jdbc.datasource.uc1slave0.username=root
sharding.jdbc.datasource.uc1slave0.password=

##默认的数据库分片策略,如果没有指定具体某个数据库的分片策略,那么使用默认分片策略
sharding.jdbc.config.sharding.default-database-strategy.inline.sharding-column=id
sharding.jdbc.config.sharding.default-database-strategy.inline.algorithm-expression=aa$->{id % 2}

#id.intdiv(2) % 2 : 根据id进行分片,先对数据库数量进行取余,在对表数量进行取模。这个作用是让数据可以更加均匀的分布在不同表中。
#$->{0..1}  是行表达式标识符,aa$->{0..1}表示aa0,aa1
sharding.jdbc.config.sharding.tables.user.actual-data-nodes=aa$->{0..1}.user$->{0..1}
sharding.jdbc.config.sharding.tables.user.table-strategy.inline.sharding-column=id
sharding.jdbc.config.sharding.tables.user.table-strategy.inline.algorithm-expression=user$->{id.intdiv(2) % 2}
sharding.jdbc.config.sharding.tables.user.key-generator-column-name=id

#这里的aa0需要和上面的default-database-strategy.inline.algorithm-expression,sharding.tables.user.actual-data-nodes的对应
sharding.jdbc.config.sharding.master-slave-rules.aa0.master-data-source-name=master0
sharding.jdbc.config.sharding.master-slave-rules.aa0.slave-data-source-names=uc0slave0
sharding.jdbc.config.sharding.master-slave-rules.aa1.master-data-source-name=master1
sharding.jdbc.config.sharding.master-slave-rules.aa1.slave-data-source-names=uc1slave0
##==========================数据分片+读写分离配置======end=====================================

##==========================数据治理配置======start===================================
sharding.jdbc.config.sharding.orchestration.name=demo-orchestration
#本地配置是否覆盖注册中心配置。如果可覆盖,每次启动都以本地配置为准
sharding.jdbc.config.sharding.orchestration.overwrite=true
sharding.jdbc.config.sharding.orchestration.registry.server-lists=xxxx:2181
sharding.jdbc.config.sharding.orchestration.registry.namespace=demo-orchestration
##==========================数据治理配置======end=====================================

mybatis.typeAliasesPackage=com.cimu.shardingjdbc.entity
mybatis.mapperLocations=classpath:mapper/*.xml

user.sql

CREATE TABLE `user0` (
  `id` BIGINT(64) NOT NULL PRIMARY KEY COMMENT '主键ID',
  `real_name` VARCHAR(100) DEFAULT NULL COMMENT '真实名称',
  `mobile` VARCHAR(11) DEFAULT NULL COMMENT '手机号码',
  `password` VARCHAR(20) DEFAULT NULL COMMENT '密码',
  `create_time` DATETIME DEFAULT NULL COMMENT '创建日期',
  `update_time` DATETIME DEFAULT NULL COMMENT '修改日期',
  `del_flag` CHAR(1) NOT NULL DEFAULT '0' COMMENT '删除标记 1:删除;0:未删除'
)COMMENT='用户表';

CREATE TABLE `user1` (
  `id` BIGINT(64) NOT NULL PRIMARY KEY COMMENT '主键ID',
  `real_name` VARCHAR(100) DEFAULT NULL COMMENT '真实名称',
  `mobile` VARCHAR(11) DEFAULT NULL COMMENT '手机号码',
  `password` VARCHAR(20) DEFAULT NULL COMMENT '密码',
  `create_time` DATETIME DEFAULT NULL COMMENT '创建日期',
  `update_time` DATETIME DEFAULT NULL COMMENT '修改日期',
  `del_flag` CHAR(1) NOT NULL DEFAULT '0' COMMENT '删除标记 1:删除;0:未删除'
)COMMENT='用户表';

  • B3log

    B3log 是一个开源组织,名字来源于“Bulletin Board Blog”缩写,目标是将独立博客与论坛结合,形成一种新的网络社区体验,详细请看 B3log 构思。目前 B3log 已经开源了多款产品:PipeSoloSymWide 等,欢迎大家加入,贡献开源。

    2824 引用 • 4214 回帖 • 645 关注
  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    493 引用 • 1095 回帖 • 970 关注
  • MyBatis

    MyBatis 本是 Apache 软件基金会 的一个开源项目 iBatis,2010 年这个项目由 Apache 软件基金会迁移到了 google code,并且改名为 MyBatis ,2013 年 11 月再次迁移到了 GitHub。

    94 引用 • 351 回帖 • 824 关注
感谢    关注    收藏    赞同    反对    举报    分享