1. Prefácio
Ao usar o Java para desenvolver o software de aplicativos corporativos, o Spring+Mybatis+MySQL é frequentemente usado para criar uma estrutura de banco de dados. Se o volume de dados for grande, uma eficiência de acesso à biblioteca do MySQL armazena muito baixa e geralmente usa o método de gerenciamento de armazenamento sub-repositório. Este artigo descreve como criar uma arquitetura de acesso de vários dados através da Spring+Mybatis e usar o multi-threading para melhorar a eficiência do acesso ao banco de dados.
Deve -se notar que esse método é adequado apenas para situações em que o número de bancos de dados e nomes é corrigido e não é particularmente grande. Em resposta à situação em que o número de bancos de dados não estiver corrigido, escreverei outro plano de processamento posteriormente.
2. Plano geral
3. Preparação do ambiente de desenvolvimento
3.1 Download Spring, Mybatis, MySQL Components.
3.2 Eclipse: Java Development IDE. Os seguintes pacotes JAR são introduzidos:
A estrutura do código é a seguinte:
4. Construa um cluster de banco de dados
Crie 11 bancos de dados em MySQL (TEST1/2/3/4/5/6/7/8/9/10/11) para criar uma tabela simples:
Insira 50 milhões de dados na tabela TBL_DEMO no TEST1 e 5 milhões de dados na tabela TBL_DEMO nos outros 10 bancos de dados (usando funções).
Insira 50 milhões de dados na tabela TBL_DEMO no TEST1 e 5 milhões de dados na tabela TBL_DEMO nos outros 10 bancos de dados (usando funções).
5. Crie interface de mapeamento de banco de dados Mybatis
/** * interface de mapeamento mybatis * * * @author elon * @version 1.0, 23 de outubro de 2015 */interface pública idemo {public void InsertDemo (Demodao Demo); Lista pública <Teger> selectGroup ();}/** * * Interface de serviço de mapeamento Mybatis * * @author elon * @version 1.0, 23 de outubro de 2015 */interface pública idemoservice {public void InsertDemo (demodao Demo); Lista pública <Teger> selectGroup ();}/** * * Mybatis Mapping Service Implementation * * @Author Elon * @Version 1.0, 23 de outubro de 2015 */classe pública DemoserviceImpl implementa idemoservice {private idemo Idea = null; public void Setidemo (Idemo Idea) {this.idemo = Idea; } @Override public void InsertDemo (Demodao Demo) {iDeaMo.insertDemo (Demo); } @Override Public List <Teger> selectGroup () {return Idea.SelectGroup (); }}6. Crie gerenciamento de identidade de banco de dados e fontes de dados dinâmicas
/** * * Salvar o ID do banco de dados. Cada encadeamento é armazenado por um objeto independente * * @author elon * @version 1.0, 23 de outubro de 2015 */public class dbindeTifier {private static threadlocal <string> dbKey = new Threadlocal <string> (); public static void setDbKey (string final dbkeypara) {dbkey.set (dbkeypara); } public static string getDbKey () {return dbkey.get (); }}/*** fonte de dados dinâmicos. Diferentes bancos de dados podem ser conectados de acordo com diferentes índices de dados * * @author elon * @version 1.0, 23 de outubro de 2015 */public class DynamicDataSource estende abstractroutingDataSource {@Override Public Object determineNeCurrentLookKey () {return dbIndetImier.getDBKEY (); }}7. Crie objeto de acesso ao banco de dados
/** * * Objeto de acesso ao banco de dados. Usado para inserir dados. * * @Author Elon * @Version 1.0, 23 de outubro de 2015 */classe pública Demodao {private Int A; String privada B; privado 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; }}/** * Definição do resultado do mapeamento * * @Author Elon * @Version 1.0, 23 de outubro de 2015 */classe pública Demoresult implementa seriizável {/** * Comentário para <code> serialversion soma longa privada; public Long getUm () {retornar soma; } public void setSum (soma longa) {this.sum = sum; } @Override public string tostring () {return string.valueof (soma); }}8. Crie tarefas de acesso ao banco de dados
/*** Definição da tarefa de acesso ao banco de dados. Empacote cada solicitação ao acesso ao banco de dados em um objeto de tarefas, coloque -o no gerenciamento de tarefas e aguarde a execução da tarefa para concluir e recuperar o resultado da execução. * * @Author Elon * @Version 1.0, 23 de outubro de 2015 */public class DBTask implementa Runnable {// Operação Identidade do banco de dados, usado para especificar o banco de dados acessado. Consistente com a definição de fonte dinâmica de dados de dados no arquivo de configuração da mola. String final privada DBKEY; // Objeto de acesso ao banco de dados mybatis DBACCESSOBJECT DBACCESSOBJECT; // Nome do método de acesso ao banco de dados do Mysbatis, usado para refletir o nome da string final de chamada privada MethodName; // armazenar o valor dos parâmetros variáveis Objeto final privado [] Paraarray; // Armazene o parâmetro variável Tipo @suppresswarnings ("RawTypes") Classe final privada [] paraclassarray; // Resultado da operação do banco de dados. A operação de consulta retorna o resultado da consulta; As operações de inserção, exclusão e modificação retornam NULL. Objetos privados operamult; // Informações de exceção lançadas pelo banco de dados de operação Exceção privada de exceção; // identifica se a tarefa foi executada em acabamento booleano privado; /** this.dbaccessObject = dbaccessObject; this.methodName = MethodName; this.paraarray = paraarray; acabamento = false; exceção = nulo; paraclassarray = nova classe [paraarray.length]; for (int index = 0; index <paraarray.length; ++ Índice) {paraclassarRray [index] = paraarray [index] .getClass (); } operateresult = null; } / *** Função de execução de tarefas** / @Override public void run () {try {dbindetifier.setDbKey (dbKey); Método Método = DbaccessObject.getClass (). GetMethod (MethodName, paraclassarRray); // a operação de consulta retorna o resultado da consulta; as operações de inserção, exclusão e modificação retornam NULL Operateresult = Method.inVoke (dbaccessObject, paraarray); } catch (Exceção e) {exceção = e; E.PrintStackTrace (); } acabamento = true; } /** * * Retorne o resultado da operação. Operação de consulta retorna resultados de consulta; Insira, exclua e modifique as operações retornar NULL * * @return Operação Resultado */ Public Object getRetValue () {return Operateresult; } / *** Exceção de operação do banco de dados*** @return Exception* / public Exception getException () {return Exception; } / **** Retorne se a tarefa foi executada** @return tag* / public boolean isfinish () {return fin fim; }}9. Crie um gerenciador de tarefas de banco de dados
/*** Gerenciamento de tarefas de acesso ao banco de dados. Coloque a tarefa de acesso ao banco de dados no pool de threads para executar. * * * @author elon * @version 1.0, 23 de outubro de 2015 */public class DBTaskmgr {classe estática privada dbTaskmgrInstance {public static final dbTaskmgr instância = new DBTaskMgr (); } public static dbTaskmgr instance () {return dbTaskMgrInstance.Instance; } pool de threadpoolExecutor privado; public dBTaskMgr () {Pool = new ThreadPoolExecutor (10, 50, 60, TimeUnit.Seconds, New ArrayBlockingQueue <uncrnable> (10000), new Threadpoolexecutor.callerRunSpolicy ()); } public void Excute (Runnable Task) {Pool.execute (Task); }}10. Crie arquivo de configuração Mybatis
10.1 mybatis.xml
<? xml versão = "1.0" coding = "utf-8"?> <! Doctype Configuration public "-// mybatis.org//dtd Config 3.0 // en" "http://mybatis.org/dtd/mybatis-3-config. magro"> Resource = "CFG/Demomapper.xml"/> </mappers> </figuration>
10.2 Demomapper.xml
<? xml versão = "1.0" coding = "utf-8"?> <! id = "insertDemo" parameterType = "com.elon.demodao"> inserir em tbl_demo (a, b, c) valores ( #{a}, #{b}, #{c}); </insert> <resultMap id = "Demoresult" type = "com.elon.demoresult"> <iD Property = "Sum" Column = "SumColum"/> </ResultMap> <SELECT ID = "SelectGroup" ResultMap = "Demoresult"> Selecione Sum (a) como sumcolum do grupo TBL_DEMO por C; </leclect> </pappper>11. Crie arquivo de configuração de mola
11.1 Spring.xml
<? xml versão = "1.0" coding = "utf-8"?> <Beans xmlns = "http://www.springframework.org/schema/beans" xmlns: xsi = "http:/wwww.w3 xsi: schemalocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-bans-3.0.xsd"> <bean id = "dataSource_1" value = "com.mysql.jdbc.driver"> </property> <propriedade name = "url" value = "jdbc: mysql: //10.70.69.69: 3306/test1"> </propriedade> <names name = "username" = "user123"> </</imobiliário> </propriedades> <nome da propriedade = "username" = "user123"> </</</propriedade> </propriedade> <nome da propriedade = "username" ") name = "maxactive" value = "100"> </propriedade> <propriedade name = "maxidle" value = "30"> </propriedade> <propriedade name = "maxwait" value = "500"> </propriedade> <nome da propriedade = "defaultAutocommit" value = ""> </propriedades> </bEan> <Bean id = "" value = "com.mysql.jdbc.driver"> </property> <propriedade name = "url" value = "jdbc: mysql: //10.70.69.69: 3306/test2"> </propriedade> <names name = "username" = "user123"> </</propriedade> </propriedade> <nome da propriedade = "username" = "user123"> </</</propriedade> </propriedades> name = "maxactive" value = "100"> </propriedade> <propriedade name = "maxidle" value = "30"> </propriedade> <propriedade name = "maxwait" value = "500"> </property> <nome do nome = "defaultAutocommit" value = ""> </propriedades> </bEan> <Bean id = "" value = "com.mysql.jdbc.driver"> </property> <propriedade name = "url" value = "jdbc: mysql: //10.70.69.69: 3306/test3"> </propriedade> <names name = "username"/"user123"> </</propriedade> <nome da propriedade = "username" ") name = "maxactive" value = "100"> </propriedade> <propriedade name = "maxidle" value = "30"> </propriedade> <propriedade name = "maxwait" value = "500"> </propriedade> <names name = "defaultAutocommit" value = ""> </propriedades> </bEan> <bean id = "" value = "com.mysql.jdbc.driver"> </property> <propriedade name = "url" value = "jdbc: mysql: //10.70.69.69: 3306/test4"> </propriedade> <names name = "username" = "user123"> </</imobiliário> <weead> <nome da propriedade = "username" = "user123"> </</</propriedades> name = "maxactive" value = "100"> </propriedade> <propriedade name = "maxidle" value = "30"> </propriedade> <propriedade name = "maxwait" value = "500"> </propriedade> <nome da propriedade = "defaultAutocommit" value = ""> </propriedades> </bEan> <Bean id = "" value = "com.mysql.jdbc.driver"> </property> <propriedade name = "url" value = "jdbc: mysql: //10.70.69.69: 3306/test5"> </propriedade> <names name = "username" = "user123"> </</propriedade> </propriedades> name = "maxactive" value = "100"> </propriedade> <propriedade name = "maxidle" value = "30"> </propriedade> <propriedade name = "maxwait" value = "500"> </propriedade> <names name = "defaultAutocommit" value = ""> </propriedades> </bEan> <Bean id = "" value = "com.mysql.jdbc.driver"> </property> <propriedade name = "url" value = "jdbc: mysql: //10.70.69.69: 3306/test6"> </propriedade> <names name = "username" = "user123"> </</propriedade> <nome da propriedade = "Nome =" Username "=" User123 "> </</</propriedades> name = "maxactive" value = "100"> </propriedade> <propriedade name = "maxidle" value = "30"> </propriedade> <propriedade name = "maxwait" value = "500"> </propriedade> <nome da propriedade = "defaultAutocommit" value = ""> </propriedades> </bEan> <Bean id = " value = "com.mysql.jdbc.driver"> </propriedade> <propriedade name = "url" value = "jdbc: mysql: //10.61.67.246: 3306/test7"> </propriedade> <nome da propriedade = "username" "user123"> <//<//"> </propriedade> <nome da propriedade =" username "=" user123 "> </<//<//"> </propriedade> name = "maxactive" value = "100"> </propriedade> <propriedade name = "maxidle" value = "30"> </propriedade> <propriedade name = "maxwait" value = "500"> </propriedade> <names name = "defaultAutocommit" value = ""> </propriedades> </bEan> <Bean id = "" value = "com.mysql.jdbc.driver"> </propriedade> <propriedade name = "url" value = "jdbc: mysql: //10.61.67.246: 3306/test8"> </propriedade> <nome da propriedade = "username" "user123"> <//</</ name = "maxactive" value = "100"> </propriedade> <propriedade name = "maxidle" value = "30"> </propriedade> <propriedade name = "maxwait" value = "500"> </propriedade> <names name = "defaultAutocommit" value = ""> </propriedades> </bEan> <Bean id = "" value = "com.mysql.jdbc.driver"> </property> <propriedade name = "url" value = "jdbc: mysql: //10.61.67.246: 3306/test9"> </propriedade> <nome da propriedade = "username" "user123"> <//<//"> </propriedade> <nome da propriedade =" username "" user123 "> <//</<//"> </propriedade> name = "maxactive" value = "100"> </propriedade> <propriedade name = "maxidle" value = "30"> </propriedade> <propriedade name = "maxwait" value = "500"> </property> <nome do nome = "defaultAutocommit" value = ""> </propriedades> </bEan> <Bean id = "" value = "com.mysql.jdbc.driver"> </property> <propriedade name = "url" value = "jdbc: mysql: //10.61.67.246: 3306/test10"> </propriedade> <nome da propriedade = "username" "user123"> <//<//</propriedades> name = "maxactive" value = "100"> </propriedade> <propriedade name = "maxidle" value = "30"> </propriedade> <propriedade name = "maxwait" value = "500"> </propriedade> <names name = "defaultAutocommit" value = ""> </propriedades> </bEan> <Bean id = " value = "com.mysql.jdbc.driver"> </property> <propriedade name = "url" value = "jdbc: mysql: //10.61.67.246: 3306/test11"> </propriedade> <nome da propriedade = "username" "user123"> <//<//"> </propriedade> <nome da propriedade =" username "=" user123 "> <//<//</ name = "maxactive" value = "100"> </propriedade> <propriedade name = "maxidle" value = "30"> </propriedade> <propriedade name = "maxwait" value = "500"> </propriedade> <names name = "defaultAutocommit" value = "true"> </propriedade> </bEan> <Bean id "" key = "test1" value-ref = "DataSource_1"/> <entradas key = "test2" value-ref = "dataSource_2"/> <Entry key = "test3" value-ref = "DataSource_3"/> <Entry Key = "Test4" value = "DataSource_4"/> <tha "/" key = "test6" value-ref = "DataSource_6"/> <entradas key = "test7" value-ref = "datasource_7"/> <Entrada key = "test8" value-ref = "DataSource_8"/> <Entrada key = "Test9" value = "DataSource_9"/> <> <key = "TEST10) key = "Test11" value-ref = "DataSource_11"/> </map> </property> </bean> <bean id = "sqlsessionFactory"> <names name = "configLocation" value = "classpath: cfg/mybatis.xml"> </"> <wean Name =" DataSource " id="iDemo"> <property name="mapperInterface" value="com.elon.IDemo"></property> <property name="sqlSessionFactory" ref="sqlSessionFactory"></property> </bean> <bean id="iDemoService"> <property name="idemo" ref="iDemo"></property> </bean></beans>
12. Código de teste
public class TestMain {/** * Código de teste * * @param args */public static void main (string [] args) {@suppresswarnings ("Resource") ApplicationContext Context = new ClassPathXMLApplicationContext ("cfg/spring.xml"); Idemoservice Service1 = (idemoservice) context.getBean ("idemoservice"); // Crie objeto de tarefa 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 taskInssert = new dbTask ("test2", serviço1, "insertDemo", demonstração); SimpledateFormat formato = new SimpleDateFormat ("AAAA-MM-DD HH: MM: SS"); System.out.println ("Iniciar os dados da inserção:" + format.format (new Date ())); DbTaskmgr.instance (). Excute (TaskInssert); while (true) {if (! taskInsert.isfinish ()) {try {thread.sleep (1000); } catch (interruptedException e) {e.printStackTrace (); }} else {break; }} System.out.println ("Insira os dados finais:" + format.format (new Date ())); System.out.println ("Inicie a consulta da tabela de 50 milhões de dados:" + 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 ("Consulta 50 milhões de dados Tabela final:" + format.format (new Date ())); List <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 ("Iniciar a consulta 10 5 milhões de tabelas de dados:" + format.format (new Date ())); para (tarefa dBTask: listada de tarefas) {dbTaskmgr.instance (). Excute (tarefa); } while (true) {int sucem = 0; para (tarefa dbTask: lists de tarefas) {if (! task.isfinish ()) {try {thread.sleep (1000); } catch (interruptedException e) {e.printStackTrace (); }} else {++ success; }} if (sucesso == 10) {break; }} para (tarefa dbTask: taskList) {System.out.println (task.getRetValue ()) ;; } System.out.println ("10 5 milhões de dados da tabela de dados termina:" +format.format (new Date ())); }}13. Resultados dos testes
É preciso 45s para consultar diretamente um banco de dados de 50 milhões de dados.
São necessários 22s para consultar 10 bancos de dados com 5 milhões de dados de maneira síncrona.
Como 10 bancos de dados são colocados em dois servidores, um servidor possui 5 bancos de dados. Se 10 dados forem implantados em 10 servidores separadamente, a eficiência será ainda maior.
Resumir
O exposto acima é a introdução do editor ao Spring+Mybatis+MySQL para criar uma estrutura de acesso ao banco de dados distribuída. Espero que seja útil para todos. Se você tiver alguma dúvida, deixe -me uma mensagem e o editor responderá a todos a tempo. Muito obrigado pelo seu apoio ao site wulin.com!