java分布式框架_java分布式架构搭建

一、前言

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

二、整体方案

5f44669d9023f819b9cfa4031178418d.png

三、开发环境准备

3.1 下载Spring、Mybatis、Mysql组件。

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

5f44669d9023f819b9cfa4031178418d.png

代码结构如下:

5f44669d9023f819b9cfa4031178418d.png

四、构建数据库集群

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

5f44669d9023f819b9cfa4031178418d.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<?xml version="1.0" encoding="UTF-8" ?>

/p>

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

10.2 demoMapper.xml<?xml version="1.0" encoding="UTF-8" ?>

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<?xml version="1.0" encoding="UTF-8"?>

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()));

}

}

十三、测试结果

5f44669d9023f819b9cfa4031178418d.png

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

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
搭建一个Java分布式框架需要考虑以下几个步骤: 1.确定架构:根据应用场景和需求选择适合的架构,如客户端-服务器模型、对等网络模型、集群模型等。 2.选择通信协议:根据架构设计通信协议,需要定义数据格式、数据传输方式、传输协议等。 3.实现分布式算法:根据应用场景和需求实现分布式算法,如分布式锁、分布式事务等。 4.选择合适的技术和框架:选择合适的技术和框架可以简化开发和维护工作。常用的Java分布式框架有Dubbo、Spring Cloud、Apache Hadoop等。 5.搭建环境和部署:搭建分布式环境,部署应用程序。如果需要使用集群模型,可以使用负载均衡器(如Nginx、HaProxy)和分布式存储(如HDFS)等工具进行部署。 6.测试和优化:进行全面的测试和优化,保证程序的正确性和性能。 下面是一个简单的分布式框架的示例代码: ```java // 定义通信协议 public interface DistributedProtocol { String call(String data); } // 实现分布式算法 public class DistributedAlgorithm { public void lock() { // 分布式锁算法实现 } } // 使用Dubbo框架实现分布式服务 @Service public class DistributedService implements DistributedProtocol { @Override public String call(String data) { // 服务实现 } } // 客户端调用 public class DistributedClient { @Reference private DistributedProtocol protocol; public void call(String data) { protocol.call(data); } } ``` 以上是一个简单的分布式框架的示例代码,实现了分布式服务的定义和实现,以及分布式算法的调用。具体实现需要根据应用场景和需求进行调整和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值