1. 서문
Java를 사용하여 Enterprise Application 소프트웨어를 개발할 때 Spring+MyBatis+MySQL은 종종 데이터베이스 프레임 워크를 구축하는 데 사용됩니다. 데이터 볼륨이 크면 MySQL 라이브러리는 데이터 액세스 효율을 매우 낮게 저장하고 종종 하위 고정 스토리지 관리 방법을 사용합니다. 이 기사에서는 Spring+Mybatis를 통해 멀티-다타베이스 액세스 아키텍처를 구축하고 멀티 스레딩을 사용하여 데이터베이스 액세스 효율을 향상시키는 방법에 대해 설명합니다.
이 방법은 데이터베이스와 이름의 수가 고정되어 있고 특히 크지 않은 상황에만 적합하다는 점에 유의해야합니다. 데이터베이스 수가 고정되지 않은 상황에 따라 나중에 다른 처리 계획을 작성하겠습니다.
2. 전체 계획
3. 개발 환경 준비
3.1 다운로드 Spring, Mybatis, MySQL 구성 요소.
3.2 Eclipse : Java Development IDE. 다음과 같은 항아리 패키지가 소개됩니다.
코드 구조는 다음과 같습니다.
4. 데이터베이스 클러스터를 구축하십시오
간단한 테이블을 만들려면 MySQL에서 11 개의 데이터베이스를 작성하십시오 (Test1/2/3/4/5/5/5/5/5/5/5/7/8/9/10/11) : 간단한 테이블을 만듭니다.
Test1의 TBL_DEMO 테이블에 5 천만 개의 데이터를 삽입하고 다른 10 개의 데이터베이스 (기능 사용)의 TBL_DEMO 테이블에 5 백만 조각의 데이터를 삽입하십시오.
Test1의 TBL_DEMO 테이블에 5 천만 개의 데이터를 삽입하고 다른 10 개의 데이터베이스 (기능 사용)의 TBL_DEMO 테이블에 5 백만 조각의 데이터를 삽입하십시오.
5. MyBatis 데이터베이스 매핑 인터페이스를 만듭니다
/** * MyBatis 매핑 인터페이스 * * * @Author Elon * @version 1.0, 2015 년 10 월 23 일 */public void insertdemo (demodao demo); 공개 목록 <integer> selectGroup ();}/** * * MyBatis 매핑 서비스 인터페이스 * * @Author Elon * @version 1.0, 2015 년 10 월 23 일 */public void InsertDemo (demodao demo); 공개 목록 <integer> selectGroup ();}/** * * MyBatis 매핑 서비스 구현 * * @Author Elon * @version 1.0, 2015 년 10 월 23 일 */public class demoserviceimpl implements idemoservice {private idemo ide = null; public void setidemo (idemo idea) {this.idemo = Idea; } @override public void insertdemo (demodao demo) {ideamo.insertdemo (demo); } @override public list <integer> selectgroup () {return idea.selectgroup (); }}6. 데이터베이스 아이덴티티 관리 및 동적 데이터 소스를 만듭니다
/** * * 데이터베이스 ID를 저장합니다. 각 스레드는 독립 객체 * * @author elon * @version 1.0, 2015 년 10 월 23 일 */public class dbindetifier {private static stroodlocal <string> dbkey = new ThreadLocal <string> (); 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는 AbsTractroutingDatasource {@override public object dectionEcurrentLookupkey () {return dbindeifier.getDbkey (); }}7. 데이터베이스 액세스 개체를 만듭니다
/** * * 데이터베이스 액세스 개체. 데이터를 삽입하는 데 사용됩니다. * * @Author Elon * @version 1.0, 2015 년 10 월 23 일 */공개 클래스 Demodao {private int a; 개인 문자열 B; 개인 INT C; public int geta () {return a; } public void seta (int a) {this.a = a; } public String getb () {return b; } public void setb (문자열 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 일 */공개 클래스 DeMoresult는 <code> serialversionUid </code>/private static final long serialversionuid = -413001138792531448L에 대한 serializable {/** * 주석을 구현합니다. 개인 장거리; public long getsum () {return sum; } public void setsum (long sum) {this.sum = sum; } @override public String toString () {return string.valueof (sum); }}8. 데이터베이스 액세스 작업을 만듭니다
/*** 데이터베이스 액세스 작업 정의. 각 요청을 데이터베이스 액세스에 작업 객체에 넣고 작업 관리에 넣은 다음 작업 실행이 완료되고 실행 결과를 검색 할 때까지 기다립니다. * * @author Elon * @version 1.0, 2015 년 10 월 23 일 */public class dbtask emplements runnable {// 액세스 된 데이터베이스를 지정하는 데 사용되는 운영 데이터베이스 ID. 스프링 구성 파일의 데이터 동적 데이터 소스 정의와 일치합니다. 개인 최종 문자열 dbkey; // myBatis 데이터베이스 액세스 객체 개인 최종 객체 dbaccessObject; // mysbatis 데이터베이스 액세스 방법 이름, 호출 개인 최종 문자열 메소드 이름을 반영하는 데 사용됩니다. // 변수 매개 변수의 값을 저장 개인 최종 개체 [] paraArray; // 변수 매개 변수 유형 @SuppressWarnings ( "rawTypes") 개인 최종 클래스 [] paraclassArray; // 데이터베이스 작동 결과. 쿼리 작업은 쿼리 결과를 반환합니다. 삽입, 삭제 및 수정 작업은 NULL을 반환합니다. 개인 물체 Operateresult; // 작업 데이터베이스에서 발생하는 예외 정보 개인 예외 예외; // 작업이 개인 부울 마감으로 실행되었는지 여부를 식별합니다. / *** 생성자* @param dbkey 데이터베이스 ID* @param dbaccessObject 데이터베이스 액세스 객체* @param 메소드 이름 데이터베이스 액세스 메소드 이름* @param paraarrray 매개 변수 목록*/ public dbtask (최종 문자열 dbkey, 최종 객체 dbaccessObject, 최종 문자열 메소드 이름, 최종 객체 ... paraarray) {dbkey = dbkey; this.dbaccessObject = dbaccessObject; this.methodName = MethodName; this.paraarray = paraarray; 마무리 = 거짓; 예외 = null; paraclassarray = 새로운 클래스 [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); 메소드 메소드 = dbaccessObject.getClass (). getMethod (MethodName, paraclassArray); // 쿼리 작업은 쿼리 결과를 반환합니다. 삽입, 삭제 및 수정 작업 리턴 NULL OPERATERESULT = METHOD.INVOKE (DBACCESSOBJECT, PARAARRAY); } catch (예외 e) {예외 = e; e.printstacktrace (); } finish = true; } /** * * 작업 결과를 반환합니다. 쿼리 작동은 쿼리 결과를 반환합니다. 작업을 삽입, 삭제 및 수정하면 return null * * @return 작동 결과 */ public object getRetvalue () {return operateresult; } / *** 던지기 데이터베이스 작동 예외** @return Exception* / public Exception getException () {return Exception; } / **** 작업이 실행되었는지 여부** @return tag* / public boolean isfinish () {return finish; }}9. 데이터베이스 작업 관리자를 만듭니다
/*** 데이터베이스 액세스 작업 관리. 데이터베이스 액세스 작업을 스레드 풀에 넣어 실행하십시오. * * * @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; } 개인 ThreadPooleExecutor 풀; public dbtaskmgr () {pool = new ThreadPoolexecutor (10, 50, 60, TimeUnit.seconds, New ArrayBlockingqueue <Runnable> (10000), New ThreadPooleExecutor.callerRunspolicy ()); } public void excute (runnable task) {pool.execute (task); }}10. myBatis 구성 파일을 만듭니다
10.1 mybatis.xml
<? xml version = "1.0"encoding = "utf-8"?> <! doctype configuration public "-// mybatis.org//dtd config 3.0 // en" "http://mybatis.org/dtd/mybatis-3-config.dtd "> <mapper> Resource = "CFG/Demomapper.xml"/> </mappers> </configuration>
10.2 demomapper.xml
<? xml version = "1.0"encoding = "utf-8"?> <! doctype mapper public "-// mybatis.org//dtd mapper 3.0 // en" "http://mybatis.org/dtd/mybatis-3-mapper.dtd "> <mapper namper faces ="com.ideNto "" ". parametertype = "com.elon.demodao"> tbl_demo (a, b, c) 값 ( #{a}, #{b}, #{c})에 삽입; </insert> <resultmap id = "demoresult"type = "com.elon.demoresult"> <id property = "sum"column = "sumcolum"/> </resultmap> <select id = "selectgroup"resultmap = "demoresult"> seal sum (a) cy tbl_demo 그룹 c; </선택> </맵퍼>11. 스프링 구성 파일을 만듭니다
11.1 Spring.xml
<? xml 버전 = "1.0"alcoding = "utf-8"?> <beans xmlns = "http://www.springframework.org/schema/beans"xmlns : xsi = "http://ww.w.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"> <특성 이름 = "DriverClassSname" value = "com.mysql.jdbc.driver"> </property> <속성 이름 = "url"value = "jdbc : mysql : //10.70.69.69 : 3306/test1"> </property> <속성 이름 = "username"value = "user123"> </property> <property> <valess = "user123"> ">"> 이름 = "maxActive"value = "100"> </propert> <속성 이름 = "maxIdle"value = "30"> </property> <속성 이름 = "maxWait"value = "500"> </property> <property name = "defaultAutoCommit"value = "true"> </property> </bean> <bean id = "dataSource_2"> <속성 이름 " value = "com.mysql.jdbc.driver"> </property> <속성 이름 = "url"value = "jdbc : mysql : //10.70.69.69 : 3306/test2"> </property> <속성 이름 = "username"value = "user123"> 이름 = "maxActive"value = "100"> </propert> <속성 이름 = "maxIdle"value = "30"> </property> <속성 이름 = "maxWait"value = "500"> </property> <property name = "defaultAutoCommit"value = "true"> </property> </bean> <bean id = "dataSource_3"> <속성 이름 " value = "com.mysql.jdbc.driver"> </property> <속성 이름 = "url"value = "jdbc : mysql : //10.70.69.69 : 3306/test3"> </property> <속성 이름 = "username"value = "user123"> 이름 = "maxactive"value = "100"> </propert> <속성 이름 = "maxidle"value = "30"> </property> <속성 이름 = "maxwait"value = "500"> </property> <property name = "defaultautocommit"value = "true"> </property> </bean> <bean id = "dataSource_4"> <속성 이름 = "DriverClassName value = "com.mysql.jdbc.driver"> </property> <속성 이름 = "url"value = "jdbc : mysql : //10.70.69.69 : 3306/test4"> </property> <속성 이름 = "username"value = "user123"> 이름 = "maxactive"value = "100"> </propert> <속성 이름 = "maxidle"value = "30"> </property> <속성 이름 = "maxwait"value = "500"> </property> <property name = "defaultautocommit"value = "true"> </property> </bean> <bean id = "dataSource_5"> <속성 이름 = "DriverClassName value = "com.mysql.jdbc.driver"> </property> <속성 이름 = "url"value = "jdbc : mysql : //10.70.69.69 : 3306/test5"> </property> <속성 이름 = "username"value = "user123"> 이름 = "maxactive"value = "100"> </propert> <속성 이름 = "maxidle"value = "30"> </property> <속성 이름 = "maxwait"value = "500"> </property> <property name = "defaultautocommit"value = "true"> </property> </bean> <bean id = "dataSource_6"> <속성 이름 = "DriverClassName value = "com.mysql.jdbc.driver"> </property> <속성 이름 = "url"value = "jdbc : mysql : //10.70.69.69 : 3306/test6"> </property> <속성 이름 = "username"value = "user123"> 이름 = "maxactive"value = "100"> </propert> <속성 이름 = "maxidle"value = "30"> </property> <속성 이름 = "maxwait"value = "500"> </property> <property am name = "defaultautocommit"value = "true"> </property> </bean> <bean id = "dataSource_7"> <속성 이름 = "DriverClassname value = "com.mysql.jdbc.driver"> </property> <property name = "url"value = "jdbc : mysql : //10.61.67.246 : 3306/test7"> </property> <속성 이름 = "username"value = "user123"> 이름 = "maxActive"value = "100"> </propert> <속성 이름 = "maxIdle"value = "30"> </property> <속성 이름 = "maxWait"value = "500"> </property> <property name = "defaultAutoCommit"value = "true"> </property> </bean> <bean id = "dataSource_8"> <속성 이름 " value = "com.mysql.jdbc.driver"> </property> <속성 이름 = "url"value = "jdbc : //10.61.67.246 : 3306/test8"> </property> <속성 이름 = "username"value = "user123"> 이름 = "maxactive"value = "100"> </propert> <속성 이름 = "maxidle"value = "30"> </property> <속성 이름 = "maxwait"value = "500"> </property> <property name = "defaultautocommit"value = "true"> </property> </bean> <bean id = "dataSource_9"> <속성 이름 " value = "com.mysql.jdbc.driver"> </property> <속성 이름 = "url"value = "jdbc : mysql : //10.61.67.246 : 3306/test9"> </property> <속성 이름 = "username"value = "user123"> 이름 = "maxactive"value = "100"> </propert> <속성 이름 = "maxIdle"value = "30"> </property> <속성 이름 = "maxWait"value = "500"> </property> <property am name = "defaultAutoCommit"value = "true"> </property> </bean> <bean id = "dataSource_10"> <속성 이름 "" value = "com.mysql.jdbc.driver"> </property> <속성 이름 = "url"value = "jdbc : //10.61.67.246 : 3306/test10"> </property> <속성 이름 = "username"value = "user123"> 이름 = "maxactive"value = "100"> </propert> <속성 이름 = "maxidle"value = "30"> </property> <속성 이름 = "maxwait"value = "500"> </property> <속성 이름 = "defaultAutocommit"value = "true"> </property> </bean> <bean id = "dataSource_11"> <속성 이름 " value = "com.mysql.jdbc.driver"> </property> <속성 이름 = "url"value = "jdbc : mysql : //10.61.67.246 : 3306/test11"> </property> <속성 이름 = "username"value = "user123"> 이름 = "maxactive"value = "100"> </propert> <속성 이름 = "maxidle"value = "30"> </property> <속성 이름 = "maxwait"value = "500"> </property> <property name = "defaultautocommit"value = "true"> </property> </bean> <bean id = "dataSource"> target datousources ""dataources " 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"/> <enlick key = "test9"value-ref = "dataSource_9"/> <enly key = "value-ref ="test11 " value-Ref = "DataSource_11"/> </map> </property> </bean> <bean id = "sqlsessionFactory"> <속성 이름 = "configlocation"value = "classPath : cfg/mybatis.xml"> </property> <속성 이름 = "dataSource"ref = "dataSource"/> </bean> 이름 = "mapperinterface"value = "com.elon.idemo"> </property> <속성 이름 = "sqlsessionFactory"ref = "sqlsessionFactory"> </property> </bean> <bean id = "idemoservice"> <property name = "idemo"ref = "idemo"> </bean> </beans>
12. 테스트 코드
공개 클래스 테스트 메인 {/** * 테스트 코드 * * * @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 = 새로운 demodao (); Demo.Seta (100000000); demo.setb ( "12121212"); demo.setc (100); dbtask taskinsert = new dbtask ( "test2", service1, "insertdemo", 데모); simpledateformat 형식 = 새로운 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 ()); 목록 <dbtask> tasklist = new arraylist <dbtask> (); 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 {++ 성공; }} if (success == 10) {break; }} for (dbtask task : tasklist) {system.out.println (task.getretvalue ()) ;; } system.out.println ( "10 5 백만 데이터 테이블 쿼리 끝 :" +format.format (new date ()); }}13. 테스트 결과
5 천만 데이터의 데이터베이스를 직접 쿼리하는 데 45 대가 필요합니다.
5 백만 데이터의 데이터베이스를 동기식으로 쿼리하는 데 22 초가 걸립니다.
10 개의 데이터베이스가 두 개의 서버에 배치되므로 1 개의 서버에는 5 개의 데이터베이스가 있습니다. 10 개의 데이터가 10 개의 서버에 별도로 배포되면 효율이 훨씬 높아집니다.
요약
위는 분산 데이터베이스 액세스 프레임 워크를 구축하기 위해 Spring+Mybatis+MySQL에 대한 편집기의 소개입니다. 모든 사람에게 도움이되기를 바랍니다. 궁금한 점이 있으면 메시지를 남겨 주시면 편집자가 제 시간에 모든 사람에게 답장을 드리겠습니다. Wulin.com 웹 사이트를 지원해 주셔서 대단히 감사합니다!