1. 程式人生 > 實用技巧 >java簡單搭建分散式架構

java簡單搭建分散式架構

一般來說,資料庫的資料過多,查詢效率就很慢,這時候我們如果把表分庫到不同的資料庫,這時候訪問速度就會快很多,如果並且採用多執行緒去訪問的話,查詢速度也會提高的更快,我這裡是執行記憶體8核電腦進行測試的單個訪問mysql資料庫的200萬資料,時間在8秒左右,但是把表分到10個數據庫裡面,每張表20萬,總共也是200萬,並且採用多執行緒訪問,這裡只需要3-5秒左右,下面是程式碼:

jar包

資料庫:這裡我們知道我是把所有資料庫都放到一個一個伺服器裡面,當我們有兩個伺服器,相當於每個伺服器是5個數據庫,訪問效率會更高,如果在往上加,效率就會更低,但是伺服器成本也高。


  1. /**
  2. *
  3. */
  4. package com.liuchaojun;
  5. /**
  6. * @author liuchaojun 資料庫訪問物件。用於插入資料。
  7. * @date 2018-3-20 上午10:06:11
  8. */
  9. public class DemoDAO
  10. {
  11. private int a;
  12. private String b;
  13. private int c;
  14. public int getA()
  15. {
  16. return a;
  17. }
  18. public void setA(int a)
  19. {
  20. this.a = a;
  21. }
  22. public String getB()
  23. {
  24. return b;
  25. }
  26. public void setB(String b)
  27. {
  28. this.b = b;
  29. }
  30. public int getC()
  31. {
  32. return c;
  33. }
  34. public void setC(int c)
  35. {
  36. this.c = c;
  37. }
  38. }
  1. /*
  2. */
  3. package com.liuchaojun;
  4. /**
  5. * @author liuchaojun 儲存資料庫標識。每個執行緒由獨立的物件儲存
  6. * @date 2018-3-20 上午10:05:13
  7. */
  8. public class DBIndetifier
  9. {
  10. private static ThreadLocal<String> dbKey = new ThreadLocal<String>();
  11. public static void setDBKey(final String dbKeyPara)
  12. {
  13. dbKey.set(dbKeyPara);
  14. }
  15. public static String getDBKey()
  16. {
  17. return dbKey.get();
  18. }
  19. }

  1. /**
  2. *
  3. */
  4. package com.liuchaojun;
  5. import java.lang.reflect.Method;
  6. /**
  7. * 資料庫訪問任務定義。將每一個對資料庫訪問的請求包裝為一個任務物件,放到任務管理中, 然後等待任務執行完成,取出執行結果。
  8. *
  9. * @author liuchaojun
  10. */
  11. public class DBTask implements Runnable {
  12. // 操作資料庫標識,用於指定訪問的資料庫。與spring配置檔案中的資料動態資料來源定義一致。
  13. private final String dbKey;
  14. // mybatis資料庫訪問物件
  15. private final Object dbAccessObject;
  16. // mysbatis資料庫訪問方法名稱,用於反射呼叫
  17. private final String methodName;
  18. // 儲存可變引數的值
  19. private final Object[] paraArray;
  20. // 儲存可變引數型別
  21. @SuppressWarnings("rawtypes")
  22. private final Class[] paraClassArray;
  23. // 資料庫操作結果。查詢操作返回查詢結果; 插入、刪除、修改操作返回null。
  24. private Object operateResult;
  25. // 操作資料庫丟擲的異常資訊
  26. private Exception exception;
  27. // 標識任務是否已經執行
  28. private boolean finish;
  29. /**
  30. * 建構函式
  31. *
  32. * @param dbKey
  33. * 資料庫標識
  34. * @param dbAccessObject
  35. * 資料庫訪問物件
  36. * @param methodName
  37. * 資料庫訪問方法名稱
  38. * @param paraArray
  39. * 引數列表
  40. */
  41. public DBTask(final String dbKey, final Object dbAccessObject,
  42. final String methodName, final Object... paraArray) {
  43. this.dbKey = dbKey;
  44. this.dbAccessObject = dbAccessObject;
  45. this.methodName = methodName;
  46. this.paraArray = paraArray;
  47. finish = false;
  48. exception = null;
  49. paraClassArray = new Class[paraArray.length];
  50. for (int index = 0; index < paraArray.length; ++index) {
  51. paraClassArray[index] = paraArray[index].getClass();
  52. }
  53. operateResult = null;
  54. }
  55. /**
  56. *
  57. * 任務執行函式
  58. *
  59. */
  60. @Override
  61. public void run() {
  62. try {
  63. DBIndetifier.setDBKey(dbKey);
  64. Method method = dbAccessObject.getClass().getMethod(methodName,
  65. paraClassArray);
  66. // 查詢操作返回查詢結果; 插入、刪除、修改操作返回null
  67. operateResult = method.invoke(dbAccessObject, paraArray);
  68. } catch (Exception e) {
  69. exception = e;
  70. e.printStackTrace();
  71. }
  72. finish = true;
  73. }
  74. /**
  75. *
  76. * 返回操作結果。查詢操作返回查詢結果; 插入、刪除、修改操作返回null
  77. *
  78. * @return 操作結果
  79. */
  80. public Object getRetValue() {
  81. return operateResult;
  82. }
  83. /**
  84. * 丟擲資料庫操作異常
  85. *
  86. * @return 異常
  87. */
  88. public Exception getException() {
  89. return exception;
  90. }
  91. /**
  92. *
  93. * 返回任務是否已執行
  94. *
  95. * @return 標記
  96. */
  97. public boolean isFinish() {
  98. return finish;
  99. }
  100. }

  1. /**
  2. *
  3. */
  4. package com.liuchaojun;
  5. import java.util.concurrent.ArrayBlockingQueue;
  6. import java.util.concurrent.ThreadPoolExecutor;
  7. import java.util.concurrent.TimeUnit;
  8. /**
  9. * @author liuchaojun 資料庫訪問任務管理。將資料庫訪問任務放到執行緒池中執行。
  10. * @date 2018-3-20 上午10:07:58
  11. */
  12. public class DBTaskMgr {
  13. private static class DBTaskMgrInstance {
  14. public static final DBTaskMgr instance = new DBTaskMgr();
  15. }
  16. public static DBTaskMgr instance() {
  17. return DBTaskMgrInstance.instance;
  18. }
  19. private ThreadPoolExecutor pool;
  20. public DBTaskMgr() {
  21. pool = new ThreadPoolExecutor(10, 50, 60, TimeUnit.SECONDS,
  22. new ArrayBlockingQueue<Runnable>(10000),
  23. new ThreadPoolExecutor.CallerRunsPolicy());
  24. }
  25. public void excute(Runnable task) {
  26. pool.execute(task);
  27. }
  28. }

  1. /**
  2. *
  3. */
  4. package com.liuchaojun;
  5. import java.io.Serializable;
  6. /**
  7. * @author liuchaojun 對映結果定義
  8. * @date 2018-3-20 上午10:06:39
  9. */
  10. public class DemoResult implements Serializable
  11. {
  12. /**
  13. * Comment for <code>serialVersionUID</code><br>
  14. *
  15. */
  16. private static final long serialVersionUID = -413001138792531448L;
  17. private DemoDAO demoDAO;
  18. /**
  19. * @return the demoDAO
  20. */
  21. public DemoDAO getDemoDAO() {
  22. return demoDAO;
  23. }
  24. /**
  25. * @param demoDAO the demoDAO to set
  26. */
  27. public void setDemoDAO(DemoDAO demoDAO) {
  28. this.demoDAO = demoDAO;
  29. }
  30. }

  1. package com.liuchaojun;
  2. import java.util.List;
  3. /**
  4. * @author liuchaojun Mybatis 對映服務實現
  5. * @date 2018-3-20 上午09:50:26
  6. */
  7. public class DemoServiceImpl implements IDemoService
  8. {
  9. private IDemo idemo = null;
  10. public void setIdemo(IDemo idemo) {
  11. this.idemo = idemo;
  12. }
  13. @Override
  14. public void insertDemo(DemoDAO demo)
  15. {
  16. idemo.insertDemo(demo);
  17. }
  18. @Override
  19. public List<Integer> selectGroup()
  20. {
  21. return idemo.selectGroup();
  22. }
  23. }

  1. package com.liuchaojun;
  2. import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
  3. /**
  4. * @author liuchaojun 動態資料來源。可根據不同的資料索引連線不同的資料庫
  5. * @date 2018-3-20 上午10:05:48
  6. */
  7. public class DynamicDataSource extends AbstractRoutingDataSource
  8. {
  9. @Override
  10. public Object determineCurrentLookupKey()
  11. {
  12. return DBIndetifier.getDBKey();
  13. }
  14. }
  1. package com.liuchaojun;
  2. import java.util.List;
  3. /**
  4. * @author liuchaojun Mybatis 對映介面
  5. * @date 2018-3-20 上午09:44:03
  6. */
  7. public interface IDemo
  8. {
  9. public void insertDemo(DemoDAO demo);
  10. public List<Integer> selectGroup();
  11. }
  1. package com.liuchaojun;
  2. import java.util.List;
  3. /**
  4. * @author liuchaojun Mybatis 對映服務介面
  5. * @date 2018-3-20 上午09:45:34
  6. */
  7. public interface IDemoService
  8. {
  9. public void insertDemo(DemoDAO demo);
  10. public List<Integer> selectGroup();
  11. }
  1. package com.liuchaojun;
  2. import java.text.SimpleDateFormat;
  3. import java.util.ArrayList;
  4. import java.util.Date;
  5. import java.util.List;
  6. import org.springframework.context.ApplicationContext;
  7. import org.springframework.context.support.ClassPathXmlApplicationContext;
  8. /**
  9. * @author liuchaojun
  10. * @date 2018-3-20 上午10:09:12
  11. */
  12. public class TestMain {
  13. /**
  14. * 測試程式碼
  15. *
  16. * @param args
  17. */
  18. public static void main(String[] args) {
  19. ApplicationContext context = new ClassPathXmlApplicationContext(
  20. "cfg/spring.xml");
  21. IDemoService service1 = (IDemoService) context.getBean("iDemoService");
  22. // 建立任務物件
  23. DBTask task1 = new DBTask("test1", service1, "selectGroup");
  24. DBTask task2 = new DBTask("test2", service1, "selectGroup");
  25. DBTask task3 = new DBTask("test3", service1, "selectGroup");
  26. DBTask task4 = new DBTask("test4", service1, "selectGroup");
  27. DBTask task5 = new DBTask("test5", service1, "selectGroup");
  28. DBTask task6 = new DBTask("test6", service1, "selectGroup");
  29. DBTask task7 = new DBTask("test7", service1, "selectGroup");
  30. DBTask task8 = new DBTask("test8", service1, "selectGroup");
  31. DBTask task9 = new DBTask("test9", service1, "selectGroup");
  32. DBTask task10 = new DBTask("test10", service1, "selectGroup");
  33. DBTask task_single = new DBTask("test_single", service1, "selectGroup");
  34. // 單個執行緒直接查詢單表
  35. SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  36. DBTaskMgr.instance().excute(task_single);
  37. System.out.println("開始查詢test_single表中的200萬資料:"+ format.format(new Date()));
  38. while (true) {
  39. if (!task_single.isFinish()) {
  40. try {
  41. Thread.sleep(1000);
  42. } catch (InterruptedException e) {
  43. e.printStackTrace();
  44. }
  45. } else {
  46. break;
  47. }
  48. }
  49. System.out.println("結束查詢test_single表中的200萬資料結束:"+ format.format(new Date()));
  50. // 多個執行緒查詢多個數據庫中的表資料
  51. List<DBTask> taskList = new ArrayList<DBTask>();
  52. taskList.add(task1);
  53. taskList.add(task2);
  54. taskList.add(task3);
  55. taskList.add(task4);
  56. taskList.add(task5);
  57. taskList.add(task6);
  58. taskList.add(task7);
  59. taskList.add(task8);
  60. taskList.add(task9);
  61. taskList.add(task10);
  62. for (DBTask task : taskList) {
  63. DBTaskMgr.instance().excute(task);
  64. }
  65. System.out.println("開始查詢10個數據庫中的t_test_table表中的20萬資料表:"+ format.format(new Date()));
  66. while (true) {
  67. int success = 0;
  68. for (DBTask task : taskList) {
  69. if (!task.isFinish()) { // 執行執行緒run方法這裡為false,沒有執行擇true
  70. continue;
  71. } else {
  72. ++success;
  73. }
  74. }
  75. if (success == 10) {
  76. break;
  77. }
  78. }
  79. System.out.println("結束查詢10個數據庫中的t_test_table表中的20萬資料表:"+ format.format(new Date()));
  80. }
  81. }

demoMapper.xml



  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  3. <mapper namespace="com.liuchaojun.IDemo">
  4. <insert id="insertDemo" parameterType="com.liuchaojun.DemoDAO">
  5. insert into t_test_table(a, b, c) values(#{a}, #{b}, #{c});
  6. </insert>
  7. <resultMap id="demoDAO" type="com.liuchaojun.DemoDAO">
  8. <id column="a" property="a" />
  9. <result column="b" property="b" />
  10. <result column="c" property="c" />
  11. </resultMap>
  12. <select id="selectGroup" resultMap="demoDAO">
  13. select * from t_test_table
  14. </select>
  15. </mapper>

mybatis.xml

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  3. <mapper namespace="com.liuchaojun.IDemo">
  4. <insert id="insertDemo" parameterType="com.liuchaojun.DemoDAO">
  5. insert into t_test_table(a, b, c) values(#{a}, #{b}, #{c});
  6. </insert>
  7. <resultMap id="demoDAO" type="com.liuchaojun.DemoDAO">
  8. <id column="a" property="a" />
  9. <result column="b" property="b" />
  10. <result column="c" property="c" />
  11. </resultMap>
  12. <select id="selectGroup" resultMap="demoDAO">
  13. select * from t_test_table
  14. </select>
  15. </mapper>

spring.xml

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  3. "http://mybatis.org/dtd/mybatis-3-config.dtd">
  4. <configuration>
  5. <mappers>
  6. <mapper resource="cfg/demoMapper.xml"/>
  7. </mappers>
  8. </configuration>
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
  5. <bean id="dataSource_1" class="org.apache.commons.dbcp.BasicDataSource">
  6. <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
  7. <property name="url" value="jdbc:mysql://localhost:3306/test1"></property>
  8. <property name="username" value="root"></property>
  9. <property name="password" value="root"></property>
  10. <property name="maxActive" value="100"></property>
  11. <property name="maxIdle" value="30"></property>
  12. <property name="maxWait" value="500"></property>
  13. <property name="defaultAutoCommit" value="true"></property>
  14. </bean>
  15. <bean id="dataSource_2" class="org.apache.commons.dbcp.BasicDataSource">
  16. <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
  17. <property name="url" value="jdbc:mysql://localhost:3306/test2"></property>
  18. <property name="username" value="root"></property>
  19. <property name="password" value="root"></property>
  20. <property name="maxActive" value="100"></property>
  21. <property name="maxIdle" value="30"></property>
  22. <property name="maxWait" value="500"></property>
  23. <property name="defaultAutoCommit" value="true"></property>
  24. </bean>
  25. <bean id="dataSource_3" class="org.apache.commons.dbcp.BasicDataSource">
  26. <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
  27. <property name="url" value="jdbc:mysql://localhost:3306/test3"></property>
  28. <property name="username" value="root"></property>
  29. <property name="password" value="root"></property>
  30. <property name="maxActive" value="100"></property>
  31. <property name="maxIdle" value="30"></property>
  32. <property name="maxWait" value="500"></property>
  33. <property name="defaultAutoCommit" value="true"></property>
  34. </bean>
  35. <bean id="dataSource_4" class="org.apache.commons.dbcp.BasicDataSource">
  36. <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
  37. <property name="url" value="jdbc:mysql://localhost:3306/test4"></property>
  38. <property name="username" value="root"></property>
  39. <property name="password" value="root"></property>
  40. <property name="maxActive" value="100"></property>
  41. <property name="maxIdle" value="30"></property>
  42. <property name="maxWait" value="500"></property>
  43. <property name="defaultAutoCommit" value="true"></property>
  44. </bean>
  45. <bean id="dataSource_5" class="org.apache.commons.dbcp.BasicDataSource">
  46. <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
  47. <property name="url" value="jdbc:mysql://localhost:3306/test5"></property>
  48. <property name="username" value="root"></property>
  49. <property name="password" value="root"></property>
  50. <property name="maxActive" value="100"></property>
  51. <property name="maxIdle" value="30"></property>
  52. <property name="maxWait" value="500"></property>
  53. <property name="defaultAutoCommit" value="true"></property>
  54. </bean>
  55. <bean id="dataSource_6" class="org.apache.commons.dbcp.BasicDataSource">
  56. <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
  57. <property name="url" value="jdbc:mysql://localhost:3306/test6"></property>
  58. <property name="username" value="root"></property>
  59. <property name="password" value="root"></property>
  60. <property name="maxActive" value="100"></property>
  61. <property name="maxIdle" value="30"></property>
  62. <property name="maxWait" value="500"></property>
  63. <property name="defaultAutoCommit" value="true"></property>
  64. </bean>
  65. <bean id="dataSource_7" class="org.apache.commons.dbcp.BasicDataSource">
  66. <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
  67. <property name="url" value="jdbc:mysql://localhost:3306/test7"></property>
  68. <property name="username" value="root"></property>
  69. <property name="password" value="root"></property>
  70. <property name="maxActive" value="100"></property>
  71. <property name="maxIdle" value="30"></property>
  72. <property name="maxWait" value="500"></property>
  73. <property name="defaultAutoCommit" value="true"></property>
  74. </bean>
  75. <bean id="dataSource_8" class="org.apache.commons.dbcp.BasicDataSource">
  76. <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
  77. <property name="url" value="jdbc:mysql://localhost:3306/test8"></property>
  78. <property name="username" value="root"></property>
  79. <property name="password" value="root"></property>
  80. <property name="maxActive" value="100"></property>
  81. <property name="maxIdle" value="30"></property>
  82. <property name="maxWait" value="500"></property>
  83. <property name="defaultAutoCommit" value="true"></property>
  84. </bean>
  85. <bean id="dataSource_9" class="org.apache.commons.dbcp.BasicDataSource">
  86. <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
  87. <property name="url" value="jdbc:mysql://localhost:3306/test9"></property>
  88. <property name="username" value="root"></property>
  89. <property name="password" value="root"></property>
  90. <property name="maxActive" value="100"></property>
  91. <property name="maxIdle" value="30"></property>
  92. <property name="maxWait" value="500"></property>
  93. <property name="defaultAutoCommit" value="true"></property>
  94. </bean>
  95. <bean id="dataSource_10" class="org.apache.commons.dbcp.BasicDataSource">
  96. <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
  97. <property name="url" value="jdbc:mysql://localhost:3306/test10"></property>
  98. <property name="username" value="root"></property>
  99. <property name="password" value="root"></property>
  100. <property name="maxActive" value="100"></property>
  101. <property name="maxIdle" value="30"></property>
  102. <property name="maxWait" value="500"></property>
  103. <property name="defaultAutoCommit" value="true"></property>
  104. </bean>
  105. <bean id="dataSource_single" class="org.apache.commons.dbcp.BasicDataSource">
  106. <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
  107. <property name="url" value="jdbc:mysql://localhost:3306/test_single"></property>
  108. <property name="username" value="root"></property>
  109. <property name="password" value="root"></property>
  110. <property name="maxActive" value="100"></property>
  111. <property name="maxIdle" value="30"></property>
  112. <property name="maxWait" value="500"></property>
  113. <property name="defaultAutoCommit" value="true"></property>
  114. </bean>
  115. <bean id="dataSource" class="com.liuchaojun.DynamicDataSource">
  116. <property name="targetDataSources">
  117. <map>
  118. <entry key="test1" value-ref="dataSource_1"/>
  119. <entry key="test2" value-ref="dataSource_2"/>
  120. <entry key="test3" value-ref="dataSource_3"/>
  121. <entry key="test4" value-ref="dataSource_4"/>
  122. <entry key="test5" value-ref="dataSource_5"/>
  123. <entry key="test6" value-ref="dataSource_6"/>
  124. <entry key="test7" value-ref="dataSource_7"/>
  125. <entry key="test8" value-ref="dataSource_8"/>
  126. <entry key="test9" value-ref="dataSource_9"/>
  127. <entry key="test10" value-ref="dataSource_10"/>
  128. <entry key="test_single" value-ref="dataSource_single"/>
  129. </map>
  130. </property>
  131. </bean>
  132. <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  133. <property name="configLocation" value="classpath:cfg/mybatis.xml"></property>
  134. <property name="dataSource" ref="dataSource" />
  135. </bean>
  136. <bean id="iDemo" class="org.mybatis.spring.mapper.MapperFactoryBean">
  137. <property name="mapperInterface" value="com.liuchaojun.IDemo"></property>
  138. <property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
  139. </bean>
  140. <bean id="iDemoService" class="com.liuchaojun.DemoServiceImpl">
  141. <property name="idemo" ref="iDemo"></property>
  142. </bean>
  143. </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);


  1. <span style="color:#454545">
  2. </span>

專案原始碼資源下載地址:https://download.csdn.net/download/qq_27026603/10298566