1. Prefácio
A estratégia de separação de leitura e gravação dos bancos de dados em um ambiente distribuído é uma solução essencial para resolver o gargalo do desempenho de leitura e gravação do banco de dados, e também maximiza a velocidade e a concorrência dos dados de leitura (leitura) em aplicativos.
Ao separar o banco de dados Leia e gravar, primeiro precisamos configurar o mestre e o escravo do banco de dados. O mais simples é um mestre e um escravo (para grandes sistemas de sites, é claro, será muito complicado. Aqui apenas analisamos a situação mais simples). Através da configuração mestre-escravo, o banco de dados Master-Slave mantém os mesmos dados. Acessamos o escravo do banco de dados escravo ao executar operações de leitura e o Master Database Master ao executar operações de gravação. Isso reduzirá a pressão em um servidor.
Ao conduzir a análise de casos da separação de leitura e gravação. Primeiro, configure a replicação da escrava mestre do banco de dados e forneça uma explicação detalhada da instalação e configuração síncrona do banco de dados MySQL5.6 Master-Slave (Master/Slave)
Obviamente, é apenas uma maneira simples de ver como usar o código para obter a separação do banco de dados Read and Write, e não há necessidade de configurar o banco de dados Master e Slave. Requer apenas duas máquinas com o mesmo banco de dados instalado.
2. Duas maneiras de alcançar a separação de leitura e escrita
Especificamente no desenvolvimento, existem duas maneiras comuns de alcançar a separação de leitura e escrita:
1. O primeiro método é o método mais comumente usado, que é definir duas conexões de banco de dados, um é o MasterDataSource e o outro é escravo. Ao atualizar os dados, lemos o MasterDataSource e, ao consultar os dados, lemos o SlaveDatasource. Este método é muito simples, então não vou entrar em detalhes.
2. O segundo método de comutação dinâmica da fonte de dados é tecer dinamicamente a fonte de dados no programa quando o programa estiver em execução, de modo a optar por ler a biblioteca mestre ou a biblioteca de escravos. As principais tecnologias utilizadas são: anotação, Spring AOP, reflexão.
O método de implementação será descrito em detalhes abaixo.
3. AOP percebe o caso de separação de leitura e gravação do banco de dados de escravos mestre
1. Endereço do código do projeto
O endereço atual do projeto desta demonstração: demonstração
2. Estrutura do projeto
Na figura acima, além do código marcado, os outros são principalmente o código de configuração e o código comercial.
3. Análise específica
Este projeto é uma demonstração da estrutura do SSM, primavera, MVC de primavera e mybatis. Os arquivos de configuração específicos não são muito introduzidos.
(1) UserContoller simula dados de leitura e escrita
/*** Criado por Xuliugen em 2016/5/4. */@Controlador@requestmapp (value = "/user", produz = {"Application/json; charset = utf-8"}) classe pública userController {@inject private iUserService UserService; //http://localhost:8080/user/select.do @responsebody @requestMapping (value = "/select.do", método = requestmethod.get) public string () {user user = userService.selectUserbyid (123); return user.toString (); } //http://localhost:8080/user/add.do @ResponseBody @ReQuestMapping (value = "/add.do", método = requestmethod.get) public string add () {boolean iSok = ususerVice.adduser (novo usuário ("333" 444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444) retornar isok == true? "Shibai": "Chenggong"; }}Simule dados de leitura e escrita e ligue para IUSERSERVICE.
(2) Spring-db.xml Leia e gravação Configuração da fonte de dados
<? xml versão = "1.0" coding = "utf-8"?> <Beans xmlns = "http://www.springframework.org/schema/beans" xmlns: xsi = "http:/wwww.w3 xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd "> <bean id =" statfilter "LAZY =" True "> <nome da") value = "true"/> </i bean> <!-conexão com o banco de dados-> <bean id = "readDataSource" destruir-method = "fechar" init-method = "init" lazy-init = "true"> <nome da propriedade = "driver" nome "{" {}}/> <names) value = "root"/> <propriedade name = "senha" value = "$ {senha}"/> <!-omita algum conteúdo-> </bean> <bean id = "wridedataSource" destruir-method = "fechar" init-method = "init" lazy-init = ""> <nome da propriedade = "Driver "Mame") value = "$ {url}"/> <propriedade name = "userName" value = "root"/> <propriedade name = "senha" value = "$ {senha}"/> <!-omita alguns conteúdos-> </bean> <!-Configurar dinamicamente leia e gravação de dados-> <bean iD = "DataSource" key-type = "java.lang.string" value-type = "javax.sql.dataSource"> <!-write-> <entradas key = "write" value-ref = "wridedatasource"/> <!-read-> <key de entrada ". name = "DefaultTargetDataSource" ref = "writedataSource"/> <propriedade name = "Methodtype"> <map key-lype = "java.lang.string"> <!-read-> <! </map> </ousetwer> </shean> </ Beans>Na configuração acima, o ReadDataSource e o WritedATAsource são configurados, mas apenas o DatAsource é entregue ao SQLSessionFactoryBean para o gerenciamento e o uso de: com.xuliugen.Choososedb.demo.aspect.ChoosedAsource isso é usado para a seleção de dados de dados.
<Propriedade name = "Methodtype"> <map key-type = "java.lang.string"> <!-leia-> <Entry key = "read" value = ", obtenha, selecione, contagem, listar, consultar"/> <!-write-> <Entrada key = "Write", ", Adicionar, Criar, Atualizar, Delete, Remover,"/>
As palavras -chave de prefixo específicas do banco de dados estão configuradas. O código específico do CHOUSELATASOURCE é o seguinte:
(3) CHOASEDatasource
/*** Obtenha a fonte de dados, usada para alternar dinamicamente as fontes de dados*/classe pública CHOUSEDatasource estende abstractroutingDataSource {public static map <string, list <tring>> method_type_map = new hashmap <string, list <string> (); / *** Implemente o método abstrato na classe pai e obtenha o nome da fonte de dados* @return*/ Protected Object determineCurrentLookKey () {return dataSourceHandler.getDataSource (); } // Defina a fonte de dados correspondente ao nome do método prefixo public void setMethodType (map <string, string> map) {for (string key: map.keyset ()) {list <string> v = new ArrayList <string> (); String [] types = map.get (key) .split (","); para (tipo de string: tipos) {if (stringUtils.isnotblank (type)) {v.add (type); }} Method_type_map.put (chave, v); }}}(4) DataSourCeastep executa a interceptação da AOP para métodos específicos
/** * Switch Data Source (diferentes métodos chamam diferentes de fontes de dados) */@aspecto@componente@enabaspectJautoProxy (proxyTargetClass = true) public class DataSourCeaspect {protegido logger logger = loggerFactory.getLogger (this.getClass ()); @PointCut ("Execution (*com.xuliugen.choosedb.demo.mybatis.dao.*.*(..))") public void Aspeccement () {} / ***configure a classe () PRONTRE NOTIFICAÇÕES, Use o ponto de entrada registrado no método jung ()* / @Efore ("aspecto ()") Point.getTarget (). getClass (). getName (); String métod = Point.getSignature (). GetName (); Logger.info (className + "." + Método + "(" + StringUtils.Join (Point.getargs (), ",") + ")"); tente {for (string key: choosedataSource.method_type_map.keyset ()) {for (string type: ChoosedataSource.method_type_map.get (key)) {if (method.startswith (type)) {dataSourtDler.putDataSource (key); }}}} catch (Exceção e) {e.printStackTrace (); }}}(5) DataSourceHandler, a classe manipuladora da fonte de dados
pacote com.xuliugen.Choososedb.demo.aspect;/*** Classe de manipulador de dados*/public class DataSourceHandler {// Nome da fonte de dados Threadpool public static final ThreadLocal <string> holder = new Threadlocal <string> (); / *** Adicione as fontes de dados de leitura e gravação configuradas ao titular quando o projeto iniciar*/ public static void putDataSource (string dataSource) {holder.set (DataSource); } / *** Obtenha a sequência de origem de dados do holer* / public static string getDataSource () {return holder.get (); }} O código principal, como mencionado acima.
Código neste artigo: demonstração
O exposto acima é todo o conteúdo deste artigo. Espero que seja útil para o aprendizado de todos e espero que todos apoiem mais o wulin.com.