De nos jours, les systèmes de commerce électronique à grande échelle utilisent principalement une technologie de séparation de lecture et d'écriture au niveau de la base de données, qui est une base de données maître et plusieurs bases de données d'esclaves. La bibliothèque Master est responsable des mises à jour des données et de la requête de données en temps réel, et la bibliothèque des esclaves est responsable de la requête de données non réel. Parce que dans les applications réelles, la base de données lit plus et écrit moins (la fréquence des données de lecture est élevée et la fréquence de mise à jour des données est relativement faible), et que les données de lecture sont généralement plus longues et occupe plus de CPU sur le serveur de base de données, ce qui affecte l'expérience utilisateur. Notre approche habituelle consiste à extraire la requête de la bibliothèque principale, à utiliser plusieurs bibliothèques d'esclaves et à utiliser l'équilibrage de charge pour réduire la pression de requête de chaque bibliothèque d'esclaves.
L'objectif d'utiliser la technologie de séparation de lecture et d'écriture est de réduire efficacement la pression sur la bibliothèque maître et de distribuer des demandes de données de requête utilisateur aux différentes bibliothèques d'esclaves, garantissant ainsi la robustesse du système. Jetons un coup d'œil à l'arrière-plan de l'utilisation de la séparation en lecture-écriture.
Alors que les activités du site Web continuent de se développer, les données continuent d'augmenter et plus les utilisateurs, la pression sur la base de données devient de plus en plus grande.
Spécifiquement dans le développement, comment réaliser facilement la séparation de lecture et d'écriture?
1 La première méthode est la méthode la plus couramment utilisée, qui consiste à définir deux connexions de base de données, l'une est MasterDataSource et l'autre est esclavédataSource. Lors de la mise à jour des données, nous lisons le MasterDataSource et lors de l'interrogation des données, nous lisons le SlavedataSource. Cette méthode est très simple, donc je n'entrerai pas dans les détails.
2 La deuxième méthode de commutation de source de données dynamique consiste à tisser dynamiquement la source de données dans le programme lorsque le programme est en cours d'exécution, afin de choisir de lire la bibliothèque maître ou la bibliothèque des esclaves. Les principales technologies utilisées sont: Annotation, printemps AOP, réflexion. La méthode de mise en œuvre sera décrite en détail ci-dessous.
Avant d'introduire la méthode de mise en œuvre, nous préparerons certaines connaissances nécessaires, la classe AbstractroutingDatasource du printemps
La classe AbstractroutingDataSource a été ajoutée après Spring 2.0.
La copie de code est la suivante:
Classe abstraite du public AbstractroutingDataSource étend AbstractDataSource implémente InitializingBean {}
AbstractroutingDataSource hérite AbstractDatasource, qui est une sous-classe de DataSource. DataSource est l'interface de source de données de javax.sql, définie comme suit:
L'interface publique DataSource étend CommondataSource, Wrapper {/ ** * <p> tente d'établir une connexion avec la source de données que * cet <code> objet DataSource </code> représente. que * cet objet <code> DataSource </code> représente. L'interface DataSource définit deux méthodes, qui obtiennent toutes deux des connexions de base de données. Jetons un coup d'œil à la façon dont AbstractroutingDataSource implémente l'interface DataSource:
Connexion publique getConnection () lève SQELPECTING {return DeterminetargetDataSource (). GetConnection ();} Connexion publique GetConnection (String Username, String Motway) lève SQELLECTOW De toute évidence, il s'agit d'appeler votre propre méthode de déterminetargetDataSource () pour obtenir la connexion. La méthode de détermination detargetDataSource est définie comme suit:
DataSource protégée de détermination = null)) {dataSource = this.resolveddefaultDataSource; if (dataSource == null) {lancez un nouveau IllégalStateException ("Impossible de déterminer la clé de données cible pour la clé de recherche [" + LookupKey + "]");Ce dont nous nous soucions le plus, ce sont les deux phrases suivantes:
Object LookupKey = déterminatCurrentlookupkey (); dataSource dataSource = this.resolveddatasources.get (lookupkey);
La méthode de détermination de la fourniture de Lookupkey renvoie LookupKey, la méthode ResolvedDataSources consiste à obtenir la source de données à partir de la carte basée sur LookupKey. ResolvedDatasources et déterminé deBurrentlookupkey sont définis comme suit:
Carte privée <Objet, DataSource> ResolvedDataSources;
Après avoir vu la définition ci-dessus, avons-nous quelques idées?
| clé | valeur |
| maître | Masterdatasource |
| esclave | Esclavédatasource |
Nous écrivons une classe DynamicDataSource qui hérite d'abstractroutingDataSource et implémente sa méthode déterminantecurrentLookupkey (), qui renvoie la clé, le maître ou l'esclave de la carte.
D'accord, après avoir dit beaucoup, je suis un peu ennuyeux.
La technologie que nous voulons utiliser a été mentionnée ci-dessus.
@Retention (RetentionPolicy.Runtime) @target (elementType.Method) public @Interface DataSource {String Value ();} Nous devons également implémenter la classe abstraite de Spring AbstractroutingDataSource, qui est de mettre en œuvre la méthode déterminante de la fourniture de détermination:
classe publique DynamicDataSource étend AbstractroutingDataSource {@Override Protected Object DetermentCurrentLookUpkey () {// TODO Method Auto-Generated Stub Return DynamicDataSource.GetDatasouce (); atasource (chaîne Nom) {Holder.set (Name);} String statique public getDataSouce () {return holder.get (); D'après la définition de DynamicDataSource, il renvoie la valeur dynamicdatasource.getDataSouce (). Ce qui suit est la partie principale de notre implémentation, c'est-à-dire la partie AOP.
Classe publique DataSourceSpect {public void avant (point de jointure) {objet Target = Point.getTarget (); String Method = Point.getSignature (). GetName (); {Méthode m = classz [0] .getMethod (méthode, paramètre); Exception e) {// TODO: gère l'exception}}}Pour la commodité des tests, j'ai défini 2 bases de données, Mock Mock Master Library, Testing Mock Slave Library, Shop and Test Table Table Structures sont les mêmes, mais les données sont différentes, et la configuration de la base de données est la suivante:
<bean id = "MasterDataSource"> <propriété name = "driverclassname" value = "com.mysql.jdbc.driver" /> <propriété name = "url" value = "jdbc: mysql: //127.0.0.1: 3306 / shop" /> <propriété name = "usernpre / bean> <bean id = "SlaveDataSource"> <propriété name = "driverclassname" value = "com.mysql.jdbc.driver" /> <propriété name = "url" value = "jdbc: mysql: //127.0.0.1: 3306 / test" /> <propriété name = "username" value = "root" /> <propriété name = "mot de passe" .lang.string "> <! - écriture -> <entrée key =" maître "value-ref =" MasterDataSource "/> <! - Read -> <entrée key = "esclave" value-ref = "slavedatasource" /> </ map> </ propriété> <propriété name = "defaultTargetDataSource" ref = "MasterDataSource" /> </ beans: bean> <bean id = "TransactionManager"> <propriété Name = "DataSource" Ref = "DataSource" /> </EAND> <! - Sessionfactory "> <propriété name =" dataSource "ref =" dataSource "/> <propriété name =" configLocation " value = "classpath: config / mybatis-config.xml" /> </any>
Ajouter la configuration AOP à la configuration de ressort
<! - Configurer l'annotation de la base de données AOP -> <aop: AspectJ-Autoproxy> </aop: AspectJ-Autoproxy> <Beans: Bean Id = "ManyDatasourCeaspect" /> <aop: Config> <aop: Aspect Id = "C" Ref = "Expression" * (..)) "/> <aop: avant Pointcut-ref =" tx "méthode =" avant "/> </aop: aspect> </ aop: config> <! - Configurer l'annotation de la base de données AOP ->
Ce qui suit est la définition de MyBatis UserMapper.
Interface publique UserMapper {@DataSource ("Master") Public Void Add (utilisateur utilisateur); "esclave") public list <serv> list ();}Ok, exécutez notre éclipse pour voir l'effet, entrez l'administrateur du nom d'utilisateur et connectez-vous pour voir l'effet
Ce qui précède est tout le contenu de cet article.