java簡單搭建分散式架構
阿新 • • 發佈:2020-12-14
一般來說,資料庫的資料過多,查詢效率就很慢,這時候我們如果把表分庫到不同的資料庫,這時候訪問速度就會快很多,如果並且採用多執行緒去訪問的話,查詢速度也會提高的更快,我這裡是執行記憶體8核電腦進行測試的單個訪問mysql資料庫的200萬資料,時間在8秒左右,但是把表分到10個數據庫裡面,每張表20萬,總共也是200萬,並且採用多執行緒訪問,這裡只需要3-5秒左右,下面是程式碼:
jar包
資料庫:這裡我們知道我是把所有資料庫都放到一個一個伺服器裡面,當我們有兩個伺服器,相當於每個伺服器是5個數據庫,訪問效率會更高,如果在往上加,效率就會更低,但是伺服器成本也高。
- /**
- *
- */
- package com.liuchaojun;
- /**
- * @author liuchaojun 資料庫訪問物件。用於插入資料。
- * @date 2018-3-20 上午10:06:11
- */
- 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;
- }
- }
- /*
- */
-
package com.liuchaojun;
- /**
- * @author liuchaojun 儲存資料庫標識。每個執行緒由獨立的物件儲存
- * @date 2018-3-20 上午10:05:13
- */
- public class DBIndetifier
- {
- private static ThreadLocal<String> dbKey = new ThreadLocal<String>();
- public static void setDBKey(final String dbKeyPara)
- {
- dbKey.set(dbKeyPara);
- }
- public static String getDBKey()
- {
- return dbKey.get();
- }
- }
- /**
- *
- */
- package com.liuchaojun;
- import java.lang.reflect.Method;
- /**
- * 資料庫訪問任務定義。將每一個對資料庫訪問的請求包裝為一個任務物件,放到任務管理中, 然後等待任務執行完成,取出執行結果。
- *
- * @author liuchaojun
- */
- public class DBTask implements Runnable {
- // 操作資料庫標識,用於指定訪問的資料庫。與spring配置檔案中的資料動態資料來源定義一致。
- private final String dbKey;
- // mybatis資料庫訪問物件
- private final Object dbAccessObject;
- // mysbatis資料庫訪問方法名稱,用於反射呼叫
- private final String methodName;
- // 儲存可變引數的值
- private final Object[] paraArray;
- // 儲存可變引數型別
- 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;
- }
- /**
- *
- * 任務執行函式
- *
- */
- 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;
- }
- }
- /**
- *
- */
- package com.liuchaojun;
- import java.util.concurrent.ArrayBlockingQueue;
- import java.util.concurrent.ThreadPoolExecutor;
- import java.util.concurrent.TimeUnit;
- /**
- * @author liuchaojun 資料庫訪問任務管理。將資料庫訪問任務放到執行緒池中執行。
- * @date 2018-3-20 上午10:07:58
- */
- 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<Runnable>(10000),
- new ThreadPoolExecutor.CallerRunsPolicy());
- }
- public void excute(Runnable task) {
- pool.execute(task);
- }
- }
- /**
- *
- */
- package com.liuchaojun;
- import java.io.Serializable;
- /**
- * @author liuchaojun 對映結果定義
- * @date 2018-3-20 上午10:06:39
- */
- public class DemoResult implements Serializable
- {
- /**
- * Comment for <code>serialVersionUID</code><br>
- *
- */
- private static final long serialVersionUID = -413001138792531448L;
- private DemoDAO demoDAO;
- /**
- * @return the demoDAO
- */
- public DemoDAO getDemoDAO() {
- return demoDAO;
- }
- /**
- * @param demoDAO the demoDAO to set
- */
- public void setDemoDAO(DemoDAO demoDAO) {
- this.demoDAO = demoDAO;
- }
- }
- package com.liuchaojun;
- import java.util.List;
- /**
- * @author liuchaojun Mybatis 對映服務實現
- * @date 2018-3-20 上午09:50:26
- */
- 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<Integer> selectGroup()
- {
- return idemo.selectGroup();
- }
- }
- package com.liuchaojun;
- import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
- /**
- * @author liuchaojun 動態資料來源。可根據不同的資料索引連線不同的資料庫
- * @date 2018-3-20 上午10:05:48
- */
- public class DynamicDataSource extends AbstractRoutingDataSource
- {
- public Object determineCurrentLookupKey()
- {
- return DBIndetifier.getDBKey();
- }
- }
- package com.liuchaojun;
- import java.util.List;
- /**
- * @author liuchaojun Mybatis 對映介面
- * @date 2018-3-20 上午09:44:03
- */
- public interface IDemo
- {
- public void insertDemo(DemoDAO demo);
- public List<Integer> selectGroup();
- }
- package com.liuchaojun;
- import java.util.List;
- /**
- * @author liuchaojun Mybatis 對映服務介面
- * @date 2018-3-20 上午09:45:34
- */
- public interface IDemoService
- {
- public void insertDemo(DemoDAO demo);
- public List<Integer> selectGroup();
- }
- package com.liuchaojun;
- import java.text.SimpleDateFormat;
- import java.util.ArrayList;
- import java.util.Date;
- import java.util.List;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- /**
- * @author liuchaojun
- * @date 2018-3-20 上午10:09:12
- */
- public class TestMain {
- /**
- * 測試程式碼
- *
- * @param args
- */
- public static void main(String[] args) {
- 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 task_single = new DBTask("test_single", service1, "selectGroup");
- // 單個執行緒直接查詢單表
- SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- DBTaskMgr.instance().excute(task_single);
- System.out.println("開始查詢test_single表中的200萬資料:"+ format.format(new Date()));
- while (true) {
- if (!task_single.isFinish()) {
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- } else {
- break;
- }
- }
- System.out.println("結束查詢test_single表中的200萬資料結束:"+ format.format(new Date()));
- // 多個執行緒查詢多個數據庫中的表資料
- List<DBTask> taskList = new ArrayList<DBTask>();
- taskList.add(task1);
- 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);
- for (DBTask task : taskList) {
- DBTaskMgr.instance().excute(task);
- }
- System.out.println("開始查詢10個數據庫中的t_test_table表中的20萬資料表:"+ format.format(new Date()));
- while (true) {
- int success = 0;
- for (DBTask task : taskList) {
- if (!task.isFinish()) { // 執行執行緒run方法這裡為false,沒有執行擇true
- continue;
- } else {
- ++success;
- }
- }
- if (success == 10) {
- break;
- }
- }
- System.out.println("結束查詢10個數據庫中的t_test_table表中的20萬資料表:"+ format.format(new Date()));
- }
- }
demoMapper.xml
- <mapper namespace="com.liuchaojun.IDemo">
- <insert id="insertDemo" parameterType="com.liuchaojun.DemoDAO">
- insert into t_test_table(a, b, c) values(#{a}, #{b}, #{c});
- </insert>
- <resultMap id="demoDAO" type="com.liuchaojun.DemoDAO">
- <id column="a" property="a" />
- <result column="b" property="b" />
- <result column="c" property="c" />
- </resultMap>
- <select id="selectGroup" resultMap="demoDAO">
- select * from t_test_table
- </select>
- </mapper>
mybatis.xml
- <mapper namespace="com.liuchaojun.IDemo">
- <insert id="insertDemo" parameterType="com.liuchaojun.DemoDAO">
- insert into t_test_table(a, b, c) values(#{a}, #{b}, #{c});
- </insert>
- <resultMap id="demoDAO" type="com.liuchaojun.DemoDAO">
- <id column="a" property="a" />
- <result column="b" property="b" />
- <result column="c" property="c" />
- </resultMap>
- <select id="selectGroup" resultMap="demoDAO">
- select * from t_test_table
- </select>
- </mapper>
spring.xml
- <configuration>
- <mappers>
- <mapper resource="cfg/demoMapper.xml"/>
- </mappers>
- </configuration>
- <beans xmlns="http://www.springframework.org/schema/beans"
- 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">
- <bean id="dataSource_1" class="org.apache.commons.dbcp.BasicDataSource">
- <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
- <property name="url" value="jdbc:mysql://localhost:3306/test1"></property>
- <property name="username" value="root"></property>
- <property name="password" value="root"></property>
- <property name="maxActive" value="100"></property>
- <property name="maxIdle" value="30"></property>
- <property name="maxWait" value="500"></property>
- <property name="defaultAutoCommit" value="true"></property>
- </bean>
- <bean id="dataSource_2" class="org.apache.commons.dbcp.BasicDataSource">
- <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
- <property name="url" value="jdbc:mysql://localhost:3306/test2"></property>
- <property name="username" value="root"></property>
- <property name="password" value="root"></property>
- <property name="maxActive" value="100"></property>
- <property name="maxIdle" value="30"></property>
- <property name="maxWait" value="500"></property>
- <property name="defaultAutoCommit" value="true"></property>
- </bean>
- <bean id="dataSource_3" class="org.apache.commons.dbcp.BasicDataSource">
- <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
- <property name="url" value="jdbc:mysql://localhost:3306/test3"></property>
- <property name="username" value="root"></property>
- <property name="password" value="root"></property>
- <property name="maxActive" value="100"></property>
- <property name="maxIdle" value="30"></property>
- <property name="maxWait" value="500"></property>
- <property name="defaultAutoCommit" value="true"></property>
- </bean>
- <bean id="dataSource_4" class="org.apache.commons.dbcp.BasicDataSource">
- <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
- <property name="url" value="jdbc:mysql://localhost:3306/test4"></property>
- <property name="username" value="root"></property>
- <property name="password" value="root"></property>
- <property name="maxActive" value="100"></property>
- <property name="maxIdle" value="30"></property>
- <property name="maxWait" value="500"></property>
- <property name="defaultAutoCommit" value="true"></property>
- </bean>
- <bean id="dataSource_5" class="org.apache.commons.dbcp.BasicDataSource">
- <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
- <property name="url" value="jdbc:mysql://localhost:3306/test5"></property>
- <property name="username" value="root"></property>
- <property name="password" value="root"></property>
- <property name="maxActive" value="100"></property>
- <property name="maxIdle" value="30"></property>
- <property name="maxWait" value="500"></property>
- <property name="defaultAutoCommit" value="true"></property>
- </bean>
- <bean id="dataSource_6" class="org.apache.commons.dbcp.BasicDataSource">
- <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
- <property name="url" value="jdbc:mysql://localhost:3306/test6"></property>
- <property name="username" value="root"></property>
- <property name="password" value="root"></property>
- <property name="maxActive" value="100"></property>
- <property name="maxIdle" value="30"></property>
- <property name="maxWait" value="500"></property>
- <property name="defaultAutoCommit" value="true"></property>
- </bean>
- <bean id="dataSource_7" class="org.apache.commons.dbcp.BasicDataSource">
- <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
- <property name="url" value="jdbc:mysql://localhost:3306/test7"></property>
- <property name="username" value="root"></property>
- <property name="password" value="root"></property>
- <property name="maxActive" value="100"></property>
- <property name="maxIdle" value="30"></property>
- <property name="maxWait" value="500"></property>
- <property name="defaultAutoCommit" value="true"></property>
- </bean>
- <bean id="dataSource_8" class="org.apache.commons.dbcp.BasicDataSource">
- <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
- <property name="url" value="jdbc:mysql://localhost:3306/test8"></property>
- <property name="username" value="root"></property>
- <property name="password" value="root"></property>
- <property name="maxActive" value="100"></property>
- <property name="maxIdle" value="30"></property>
- <property name="maxWait" value="500"></property>
- <property name="defaultAutoCommit" value="true"></property>
- </bean>
- <bean id="dataSource_9" class="org.apache.commons.dbcp.BasicDataSource">
- <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
- <property name="url" value="jdbc:mysql://localhost:3306/test9"></property>
- <property name="username" value="root"></property>
- <property name="password" value="root"></property>
- <property name="maxActive" value="100"></property>
- <property name="maxIdle" value="30"></property>
- <property name="maxWait" value="500"></property>
- <property name="defaultAutoCommit" value="true"></property>
- </bean>
- <bean id="dataSource_10" class="org.apache.commons.dbcp.BasicDataSource">
- <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
- <property name="url" value="jdbc:mysql://localhost:3306/test10"></property>
- <property name="username" value="root"></property>
- <property name="password" value="root"></property>
- <property name="maxActive" value="100"></property>
- <property name="maxIdle" value="30"></property>
- <property name="maxWait" value="500"></property>
- <property name="defaultAutoCommit" value="true"></property>
- </bean>
- <bean id="dataSource_single" class="org.apache.commons.dbcp.BasicDataSource">
- <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
- <property name="url" value="jdbc:mysql://localhost:3306/test_single"></property>
- <property name="username" value="root"></property>
- <property name="password" value="root"></property>
- <property name="maxActive" value="100"></property>
- <property name="maxIdle" value="30"></property>
- <property name="maxWait" value="500"></property>
- <property name="defaultAutoCommit" value="true"></property>
- </bean>
- <bean id="dataSource" class="com.liuchaojun.DynamicDataSource">
- <property name="targetDataSources">
- <map>
- <entry key="test1" value-ref="dataSource_1"/>
- <entry key="test2" value-ref="dataSource_2"/>
- <entry key="test3" value-ref="dataSource_3"/>
- <entry key="test4" value-ref="dataSource_4"/>
- <entry key="test5" value-ref="dataSource_5"/>
- <entry key="test6" value-ref="dataSource_6"/>
- <entry key="test7" value-ref="dataSource_7"/>
- <entry key="test8" value-ref="dataSource_8"/>
- <entry key="test9" value-ref="dataSource_9"/>
- <entry key="test10" value-ref="dataSource_10"/>
- <entry key="test_single" value-ref="dataSource_single"/>
- </map>
- </property>
- </bean>
- <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
- <property name="configLocation" value="classpath:cfg/mybatis.xml"></property>
- <property name="dataSource" ref="dataSource" />
- </bean>
- <bean id="iDemo" class="org.mybatis.spring.mapper.MapperFactoryBean">
- <property name="mapperInterface" value="com.liuchaojun.IDemo"></property>
- <property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
- </bean>
- <bean id="iDemoService" class="com.liuchaojun.DemoServiceImpl">
- <property name="idemo" ref="iDemo"></property>
- </bean>
- </beans>
資料表的批量插入資料儲存過程:
DROP PROCEDURE IF EXISTS pro_test1_insert;
DELIMITER //
CREATE PROCEDURE pro_test1_insert(cnt int)
BEGIN
DECLARE i int DEFAULT 0;
START TRANSACTION;
WHILE i<cnt
DO
INSERT INTO t_test_table(b,c) VALUES(i,'168');
set i=i+1;
end WHILE;
COMMIT;
end //
DELIMITER;
CALL pro_test1_insert(1000000);
- <span style="color:#454545">
- </span>
專案原始碼資源下載地址:https://download.csdn.net/download/qq_27026603/10298566