Atualmente, os sistemas de comércio eletrônico em larga escala usam principalmente a tecnologia de separação de leitura e gravação no nível do banco de dados, que é um banco de dados mestre e vários bancos de dados de escravos. A Biblioteca Master é responsável por atualizações de dados e consulta de dados em tempo real, e a Biblioteca de Escravos é responsável pela consulta de dados que não está em tempo real. Porque nos aplicativos reais, o banco de dados lê mais e grava menos (a frequência dos dados de leitura é alta e a frequência de atualização de dados é relativamente pequena), e os dados de leitura geralmente são mais longos e ocupa mais CPUs no servidor de banco de dados, o que afeta a experiência do usuário. Nossa abordagem usual é extrair a consulta da biblioteca principal, usar várias bibliotecas de escravos e usar o balanceamento de carga para reduzir a pressão de consulta de cada biblioteca de escravos.
O objetivo de usar a tecnologia de leitura e gravação de separação é reduzir efetivamente a pressão na biblioteca mestre e distribuir solicitações de dados de consultas do usuário para diferentes bibliotecas de escravos, garantindo assim a robustez do sistema. Vamos dar uma olhada no pano de fundo do uso da separação de leitura-gravação.
À medida que os negócios do site continuam a se expandir, os dados continuam a aumentar e mais usuários, a pressão no banco de dados se torna cada vez maior.
Especificamente no desenvolvimento, como alcançar facilmente a separação de leitura e gravação?
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, para 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.
Antes de introduzir o método de implementação, prepararemos algum conhecimento necessário, a classe de primavera da Spring
AbstractRoutingDataSource Classe foi adicionada após a primavera 2.0.
A cópia do código é a seguinte:
Classe abstrata pública abstractroutingDataSource estende o abstratoDataSource implementos InicializandoBean {}
AbstractroutingDataSource herda o abstrataDataSource, que é uma subclasse do DataSource. DataSource é a interface da fonte de dados do javax.sql, definida da seguinte forma:
interface pública DataSource estende comando o wrapper { /** ** * que * esse objeto <Code> DataSource </code> representa. A interface DataSource define dois métodos, os quais estão obtendo conexões de banco de dados. Vamos dar uma olhada em como o abstractroutingDataSource implementa a interface do DataSource:
Public Connection getConnection () lança SQLEXCIONE {Retorno DecongretargetDataSource (). GetConnection (); Obviamente, é para chamar seu próprio método determinanteTargetDataSource () para obter a conexão. O método DetermineTargetDataSource é definido da seguinte forma:
DataSource protegido DetermineTargetDataSource () {Assert.NotNull (this.ResolvedDataSources, "DataSource Router não inicializado"); Key == null)) {DataSource = this.ResolvedDefaultDataSource; if (DataSource == NULL) {LONGE NOVA ILAGEMENTE ("Não é possível determinar o DataSource de destino para a chave de pesquisa [" + LookUpKey + "]");O que mais nos importamos são as duas frases a seguir:
Objeto LookUpKey = DetermineCurrentLookupKey (); DataSource DataSource = this.ResolvedDataSources.get (LookUpKey);
O método DetermineCurrentLookupKey retorna o método LookUpKey, ResolvedDataSources é obter a fonte de dados do mapa com base no LookUpKey. ResolvedDataSources e determinadoCurrentLookupKey são definidos da seguinte forma:
mapa privado <Objeto, DataSource> ResolvedDataSources;
Depois de ver a definição acima, temos algumas idéias?
| chave | valor |
| mestre | MasterDataSource |
| escravo | SlavedataSource |
Estamos escrevendo uma classe DynamicDataSource que herda o abstractroutingDataSource e implementa seu método DetermineCurrentLookupKey (), que retorna a chave, mestre ou escravo do mapa.
Ok, depois de dizer tanto, sou um pouco irritante.
A tecnologia que queremos usar foi mencionada acima.
@Retention (retentionpolicy.runtime) @target (elementType.method) public @Interface DataSource {String value ();} Também precisamos implementar a classe abstrata abstrata de Spring, abstractroutingDataSource, que é implementar o método DetermineCurrentLookupKey:
classe pública DynamicDataSource estende abstractroutingDataSource {@Override Protected Object DetermineCurrentLeovepy () {// TODO Método Auto-Generado DataSource (string nome) {holder.set (nome); A partir da definição de DynamicDataSource, ele retorna o DynamicDataSourceholder.getDatasouce () Valor. A seguir, a parte principal de nossa implementação, ou seja, a parte da AOP.
classe pública DataSourCeastecy {public void antes (ponto de junta) {Object Target = Point.getTarget (); tente {método m = Classz [0] .getMethod (Método, ParameterTypes); {// TODO: lidar com exceção}}}Para a conveniência dos testes, defini 2 bancos de dados, a biblioteca -mestre simulada, a biblioteca de escravos de teste, as estruturas de compra e mesa de teste são as mesmas, mas os dados são diferentes, e a configuração do banco de dados é a seguinte:
<bean id = "masterDataSource"> <propriedade name = "driverclassName" value = "com.mysql.jdbc.driver" /> <nome da propriedade = "url" value = "jdbc: mysql: //127.0.0.1: 3306 /shop" /> <propriedades = "username" " </bean> <bean id = "SlaveDataSource"> <propriedade name = "driverclassName" value = "com.mysql.jdbc.driver" /> <Propriedade name = "url" value = "jdbc: mysql: //127.0.0.1: 3306/teste"/> <nome da propriedade = "nome de usuário" Value = "root"/> (nomes de senha ") ava.lang.string "> <!-write-> <entradas key =" mestre "value-ref =" masterDataSource "/> <!-leia-> <entrada key = "escravo" value-ref = "escravos dotas"/> </map> </property> <propriedades name = "defaultTargetDataSource" ref = "masterDataSource"/> </beans: bean> <bean id = " = "SQLSessionFactory"> <Propriedade name = "DataSource" Ref = "DataSource" /> <Nome da propriedade = "ConfigLocation" Value = "ClassPath: config/mybatis-config.xml"/> </ Bean>
Adicionar configuração AOP à configuração da mola
<!-Configure anotação do banco de dados AOP-> <AOP: AspectJ-AutoProxy> < /aOP: AspectJ-Autoproxy> <Beans: Bean id = "ManyDataSourCeaspect" /> <AOP: config> <Aop: ASPECT ID = C "Ref =" ManyDataSourCeas "> *.*(..)) "/> <AOP: Antes de Pointcut-ref =" TX "Method =" Antes "/> </AOP: ASPECT> </AOP: config> <!-Configurar anotação do banco de dados AOP->
A seguir, a definição de Mybatis UserMapper.
interface pública UsermApper {@DataSource ("Master") publicou (Usuário); Lista pública "Slave") <suser> ();}Ok, execute nosso eclipse para ver o efeito, insira o nome de usuário e faça login para ver o efeito
O acima é todo o conteúdo deste artigo.