mysql分布式数据库_Spring+Mybatis+Mysql搭建分布式数据库访问框架的方法

一、前言

用Java开发企业应用软件, 经常会采用Spring+MyBatis+Mysql搭建数据库框架。如果数据量很大,一个MYSQL库存储数据访问效率很低,往往会采用分库存储管理的方式。本文讲述如何通过Spring+Mybatis构建多数据库访问的架构,并采用多线程提升数据库的访问效率。

需要说明一下,这种方式只适合数据库数量、名称固定,且不是特别多的情况。针对数据库数量不固定的情况,后面再写一篇处理方案。

二、整体方案

b0836540e2bf555dbb3f98180f805b6a.png

三、开发环境准备

3.1 下载Spring、Mybatis、Mysql组件。

3.2 Eclipse:Java开发IDE。引入如下jar包:

980e33e2604b67f8dfb3dcdf16a9ada6.png

代码结构如下:

4322ae3acbe2241e852dc136a4056b4e.png

四、构建数据库集群

在MYSQL中创建11个数据库(test1/2/3/4/5/6/7/8/9/10/11)创建一个简单的表:

b6fef45f31e5511fdddf69335fdd542e.png

在test1的tbl_Demo表中插入5千万条数据,其它10个数据库的tbl_Demo表中分别插入5百万条数据(用函数)。

在test1的tbl_Demo表中插入5千万条数据,其它10个数据库的tbl_Demo表中分别插入5百万条数据(用函数)。

五、创建Mybatis数据库映射接口

/**

* Mybatis 映射接口

*

*

* @author elon

* @version 1.0, 2015年10月23日

*/

public interface IDemo

{

public void insertDemo(DemoDAO demo);

public List selectGroup();

}

/**

*

* Mybatis 映射服务接口

*

* @author elon

* @version 1.0, 2015年10月23日

*/

public interface IDemoService

{

public void insertDemo(DemoDAO demo);

public List selectGroup();

}

/**

*

* Mybatis 映射服务实现

*

* @author elon

* @version 1.0, 2015年10月23日

*/

public class DemoServiceImpl implements IDemoService

{

private IDemo idemo = null;

public void setIdemo(IDemo idemo) {

this.idemo = idemo;

}

@Override

public void insertDemo(DemoDAO demo)

{

idemo.insertDemo(demo);

}

@Override

public List selectGroup()

{

return idemo.selectGroup();

}

}

六、创建数据库标识管理和动态数据源

/**

*

* 保存数据库标识。每个线程由独立的对象存储

*

* @author elon

* @version 1.0, 2015年10月23日

*/

public class DBIndetifier

{

private static ThreadLocal dbKey = new ThreadLocal();

public static void setDBKey(final String dbKeyPara)

{

dbKey.set(dbKeyPara);

}

public static String getDBKey()

{

return dbKey.get();

}

}

/**

*

* 动态数据源。可根据不同的数据索引连接不同的数据库

*

* @author elon

* @version 1.0, 2015年10月23日

*/

public class DynamicDataSource extends AbstractRoutingDataSource

{

@Override

public Object determineCurrentLookupKey()

{

return DBIndetifier.getDBKey();

}

}

七、创建数据库访问对象

/**

*

* 数据库访问对象。用于插入数据。

*

* @author elon

* @version 1.0, 2015年10月23日

*/

public class DemoDAO

{

private int a;

private String b;

private int c;

public int getA()

{

return a;

}

public void setA(int a)

{

this.a = a;

}

public String getB()

{

return b;

}

public void setB(String b)

{

this.b = b;

}

public int getC()

{

return c;

}

public void setC(int c)

{

this.c = c;

}

}

/**

*

* 映射结果定义

*

* @author elon

* @version 1.0, 2015年10月23日

*/

public class DemoResult implements Serializable

{

/**

* Comment for serialVersionUID

*

*/

private static final long serialVersionUID = -413001138792531448L;

private long sum;

public long getSum()

{

return sum;

}

public void setSum(long sum)

{

this.sum = sum;

}

@Override

public String toString()

{

return String.valueOf(sum);

}

}

八、创建数据库访问任务

/**

* 数据库访问任务定义。将每一个对数据库访问的请求包装为一个任务对象,放到任务管理中,

* 然后等待任务执行完成,取出执行结果。

*

* @author elon

* @version 1.0, 2015年10月23日

*/

public class DBTask implements Runnable

{

// 操作数据库标识,用于指定访问的数据库。与spring配置文件中的数据动态数据源定义一致。

private final String dbKey;

// mybatis数据库访问对象

private final Object dbAccessObject;

// mysbatis数据库访问方法名称,用于反射调用

private final String methodName;

// 存储可变参数的值

private final Object[] paraArray;

// 存储可变参数类型

@SuppressWarnings("rawtypes")

private final Class[] paraClassArray;

// 数据库操作结果。查询操作返回查询结果; 插入、删除、修改操作返回null。

private Object operateResult;

// 操作数据库抛出的异常信息

private Exception exception;

// 标识任务是否已经执行

private boolean finish;

/**

* 构造函数

* @param dbKey 数据库标识

* @param dbAccessObject 数据库访问对象

* @param methodName 数据库访问方法名称

* @param paraArray 参数列表

*/

public DBTask(final String dbKey, final Object dbAccessObject, final String methodName,

final Object... paraArray)

{

this.dbKey = dbKey;

this.dbAccessObject = dbAccessObject;

this.methodName = methodName;

this.paraArray = paraArray;

finish = false;

exception = null;

paraClassArray = new Class[paraArray.length];

for (int index = 0; index < paraArray.length; ++index)

{

paraClassArray[index] = paraArray[index].getClass();

}

operateResult = null;

}

/**

*

* 任务执行函数

*

*/

@Override

public void run()

{

try

{

DBIndetifier.setDBKey(dbKey);

Method method = dbAccessObject.getClass().getMethod(methodName, paraClassArray);

// 查询操作返回查询结果; 插入、删除、修改操作返回null

operateResult = method.invoke(dbAccessObject, paraArray);

}

catch (Exception e)

{

exception = e;

e.printStackTrace();

}

finish = true;

}

/**

*

* 返回操作结果。查询操作返回查询结果; 插入、删除、修改操作返回null

*

* @return 操作结果

*/

public Object getRetValue()

{

return operateResult;

}

/**

* 抛出数据库操作异常

*

* @return 异常

*/

public Exception getException()

{

return exception;

}

/**

*

* 返回任务是否已执行

*

* @return 标记

*/

public boolean isFinish()

{

return finish;

}

}

九、创建数据库任务管理器

/**

* 数据库访问任务管理。将数据库访问任务放到线程池中执行。

*

*

* @author elon

* @version 1.0, 2015年10月23日

*/

public class DBTaskMgr

{

private static class DBTaskMgrInstance

{

public static final DBTaskMgr instance = new DBTaskMgr();

}

public static DBTaskMgr instance()

{

return DBTaskMgrInstance.instance;

}

private ThreadPoolExecutor pool;

public DBTaskMgr()

{

pool = new ThreadPoolExecutor(10, 50, 60, TimeUnit.SECONDS,

new ArrayBlockingQueue(10000),

new ThreadPoolExecutor.CallerRunsPolicy());

}

public void excute(Runnable task)

{

pool.execute(task);

}

}

十、创建MyBatis配置文件

10.1 mybatis.xml

/p>

"http://mybatis.org/dtd/mybatis-3-config.dtd">

10.2 demoMapper.xml

insert into tbl_demo(a, b, c) values(#{a}, #{b}, #{c});

select sum(a) as sumColum from tbl_demo group by c;

十一、创建Spring配置文件

11.1 spring.xml

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

十二、测试代码

public class TestMain

{

/**

* 测试代码

*

*

* @param args

*/

public static void main(String[] args)

{

@SuppressWarnings("resource")

ApplicationContext context = new ClassPathXmlApplicationContext("cfg/spring.xml");

IDemoService service1 = (IDemoService)context.getBean("iDemoService");

// 创建任务对象

DBTask task1 = new DBTask("test1", service1, "selectGroup");

DBTask task2 = new DBTask("test2", service1, "selectGroup");

DBTask task3 = new DBTask("test3", service1, "selectGroup");

DBTask task4 = new DBTask("test4", service1, "selectGroup");

DBTask task5 = new DBTask("test5", service1, "selectGroup");

DBTask task6 = new DBTask("test6", service1, "selectGroup");

DBTask task7 = new DBTask("test7", service1, "selectGroup");

DBTask task8 = new DBTask("test8", service1, "selectGroup");

DBTask task9 = new DBTask("test9", service1, "selectGroup");

DBTask task10 = new DBTask("test10", service1, "selectGroup");

DBTask task11 = new DBTask("test11", service1, "selectGroup");

DemoDAO demo = new DemoDAO();

demo.setA(10000000);

demo.setB("12121212");

demo.setC(100);

DBTask taskInsert = new DBTask("test2", service1, "insertDemo", demo);

SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

System.out.println("开始插入数据:" + format.format(new Date()));

DBTaskMgr.instance().excute(taskInsert);

while (true)

{

if (!taskInsert.isFinish())

{

try

{

Thread.sleep(1000);

}

catch (InterruptedException e)

{

e.printStackTrace();

}

}

else

{

break;

}

}

System.out.println("插入数据结束:" + format.format(new Date()));

System.out.println("开始查询5千万数据表:" + format.format(new Date()));

DBTaskMgr.instance().excute(task1);

while (true)

{

if (!task1.isFinish())

{

try

{

Thread.sleep(1000);

}

catch (InterruptedException e)

{

e.printStackTrace();

}

}

else

{

break;

}

}

System.out.println(task1.getRetValue());

System.out.println("查询5千万数据表结束:" + format.format(new Date()));

List taskList = new ArrayList();

taskList.add(task2);

taskList.add(task3);

taskList.add(task4);

taskList.add(task5);

taskList.add(task6);

taskList.add(task7);

taskList.add(task8);

taskList.add(task9);

taskList.add(task10);

taskList.add(task11);

System.out.println("开始查询10个5百万数据表:" + format.format(new Date()));

for (DBTask task : taskList)

{

DBTaskMgr.instance().excute(task);

}

while (true)

{

int success = 0;

for (DBTask task : taskList)

{

if (!task.isFinish())

{

try

{

Thread.sleep(1000);

}

catch (InterruptedException e)

{

e.printStackTrace();

}

}

else

{

++success;

}

}

if (success == 10)

{

break;

}

}

for (DBTask task : taskList)

{

System.out.println(task.getRetValue());;

}

System.out.println("10个5百万数据表查询结束:" +format.format(new Date()));

}

}

十三、测试结果

e73d9e033c41fb1acc5037b35b81ab4e.png

直接查询一个5千万条数据的数据库用时:45s。

多线程同步查询10个5百万数据的数据库用时: 22s。

由于10个数据库放在两台服务器上,一个服务器5个数据库。如果将10个数据分别部署到10个服务器,效率将更高。

总结

以上所述是小编给大家介绍的Spring+Mybatis+Mysql搭建分布式数据库访问框架,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值