基于mybatis的shard方案(分表分库、读写分离)

m-shard是本人近日完成一个基于mybatis、spring的分表分库插件,以下将对该插件做详细说明。

MShard是什么
MShard是一个定位于orm层shard方案,支持分表分库(跨库分表)、读写分离,支持分布式事务,它是一个基于于mybatis3.x的扩展,依赖于spring。


功能要点
1、分库分表(跨库)
2、读取分享
3、事务控制
基于spring管理事务,处理方式:将一个大的事务拆成多个小的事务
4、主键策略
mysql 利用第三方表、函数来完成,因为我们可能会在同一个mysql实例中部署多个库,而increment_offset、increment_increment是全局性的,所以mysql不能用自带的auto_increment方案;
相对而言,oracle就好办了,为每个库、每张库定义一个sequence,保证increment一致,错开offset即可


基础流程
MShard 被设计成一个 mybatis 的插件,重写了 MethodProxy、Environment、SqlSessionFactory等类,总体的sql执行步骤如下:
1、根据mapper xml生成sql
由于自定义了 methodProxy 和 MapperFactoryBean,所以我们可以在不依赖于sqlSession的情况下根据mapper.xml生成待执行的sql语句
2、sql 解析  
利用 mybatis 自身的 api 获取分表字段的值 
3、sql 路由
根据分表字段的值取模,找到对应的数据源
4、到指定的数据源执行sql
此时才根据数据源生成sqlSession,然后执行相应的语句


使用说明
1、shard-config.xml
该配置文件位于 classpath 根路径,用于配置数据源信息、分库的表及字段信息、数据源的读写分离信息。
a、数据源配置如下,目前只直接mysql,name为唯一标识符
	
		jdbc:mysql://10.1.4.241:3306/sample_db1?useUnicode=true&characterEncoding=UTF-8
		root
		123456
	
	
		jdbc:mysql://10.1.4.242:3306/sample_db1?useUnicode=true&characterEncoding=UTF-8
		root
		123456
	
        ....

b、以下是数据结点配置,用于将数据源分组,并区分哪些源用于读,哪些源用于写
(注意:每个节点对应逻辑上的一个数据库;如果某结点物理部署时采用多主热备,即多master,则在writeNodes将master一一配上即可;main=true代表该结点为主库,因为不是所有的表都需要分库处理;readNodes中的数据源将不会用写操作,同一事务中如有先写后读取的操作,那么该操作会在同一个writeNode上执行,从而保证一致性)

	
		
			ds1
			ds1_rep1, ds1_rep2
		
		
			ds2
			ds2_rep1, ds2_rep2
		
		
			ds3
			ds3_rep1, ds3_rep2
		
	



c、最后就是分库的表、字段配置了,注意:字段类型必须是数值型,且不能为空
	
		


2、建立数据库表、函数
本文以3个节点为例,每个节点有1个读库,2个写库。
注意:sequence表为主键辅助表,需设置为 MyIsam 引擎,因为该引擎下锁是以表为单位的,故不会出现并发问题。

CREATE TABLE `sample_blog` (
  `id` int(11) NOT NULL DEFAULT '0' COMMENT '主键',
  `user_id` int(11) DEFAULT NULL COMMENT '用户ID',
  `title` varchar(255) DEFAULT NULL COMMENT '标题',
  `context` mediumtext COMMENT '内容',
  `create_time` datetime DEFAULT NULL COMMENT '发表时间',
  `is_use` tinyint(1) DEFAULT NULL COMMENT '是否启用',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='博文';


CREATE TABLE `sequence` (
  `tbl_name` varchar(32) NOT NULL DEFAULT '',
  `next_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`tbl_name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;


CREATE FUNCTION `get_new_id`( tblName varchar(32) ) RETURNS int(11)
BEGIN
     DECLARE idOffset int default 1;
     DECLARE idIncrement int default 3;
     DECLARE nextID int default 0;
     select next_id into nextID from sequence where tbl_name=tblName limit 1;
     if(nextID<=0) then 
            insert into sequence(tbl_name, next_id) values(tblName, idOffset+idIncrement) ;                          
            return idOffset;
     else
            update sequence set next_id=nextID+idIncrement where tbl_name=tblName;
            RETURN nextID;
     end if;
END;




3、编写测试代码
本例中采用mapper映射机制。
测试类 BlogMapper.java  映射文件 BlogMapper.xml
以数据插入为例,

int insert(Blog record);


insert into sample_blog (id, user_id, title,
create_time, is_use, context
)
values (get_new_id('sample_blog'), #{userId,jdbcType=INTEGER},
#{title,jdbcType=VARCHAR},
#{createTime,jdbcType=TIMESTAMP}, #{isUse,jdbcType=BIT}, #{context,jdbcType=LONGVARCHAR}
)


测试代码:
	@Test
	public void testMapper() {
		BlogMapper mapper = factory.getBean(BlogMapper.class);
		BlogExample ex = new BlogExample();
		ex.createCriteria().andTitleLike("%").andIdIsNotNull();

		Blog record = new Blog();
		record.setContext("aaaaaa");
		
		for(int i=0 ; i< 100; i++){
			mapper.insert(record);
		}
	}


执行该测试用例后,100条数据以userId为分库字段,分别存储到了 3个数据源中。

4、事务控制
a、在 spring 配置中加入以下配置即:



b、在需要用到事务的业务方法头部或者类的头部加上 @Transactional 即可


写在最后
本插件目前还处于测试阶段,不能用于生产环境;
在这里写这篇文章只是想把自己的设计思想传达给大家,与大家一起分享一下,希望能让大家眼前一亮,但不足之处难免,也希望得到指证;
至于代码,目前只是为了完成基础功能,还有很大的优化空间。



依赖包:
aopalliance-1.0.jar
asm-3.3.jar
asm-commons-3.3.jar
aspectj-1.6.12.jar
commons-beanutils-1.8.3.jar
commons-codec-1.4.jar
commons-collections-3.2.1.jar
commons-dbcp-1.4.jar
commons-io-2.0.1.jar
commons-logging-1.1.1.jar
commons-pool-1.5.4.jar
junit-4.9-SNAPSHOT-20100512-0041.jar
spring.aop-3.0.5.RELEASE.jar
spring.asm-3.0.5.RELEASE.jar
spring.beans-3.0.5.RELEASE.jar
spring.context-3.0.5.RELEASE.jar
spring.context.support-3.0.5.RELEASE.jar
spring.core-3.0.5.RELEASE.jar
spring.expression-3.0.5.RELEASE.jar
spring.jdbc-3.0.5.RELEASE.jar
spring.transaction-3.0.5.RELEASE.jar
aspectjweaver-1.6.9.jar


下载链接:
mshard-demo-0.1.jar   http://pan.baidu.com/s/1dDj6QBn
mshard-0.1-beta.jar   http://pan.baidu.com/s/1kTqMnor

你可能感兴趣的:(基于mybatis的shard方案(分表分库、读写分离))