Saat ini, sistem e-commerce skala besar sebagian besar menggunakan teknologi pemisahan baca dan tulis di tingkat database, yang merupakan basis data master dan beberapa database budak. Master Library bertanggung jawab atas pembaruan data dan permintaan data real-time, dan Perpustakaan Slave bertanggung jawab atas permintaan data non-real-time. Karena dalam aplikasi aktual, basis data membaca lebih banyak dan menulis lebih sedikit (frekuensi data membaca tinggi dan frekuensi memperbarui data relatif kecil), dan data membaca biasanya lebih lama dan menempati lebih banyak CPU di server database, yang mempengaruhi pengalaman pengguna. Pendekatan kami yang biasa adalah mengekstrak kueri dari perpustakaan utama, menggunakan beberapa perpustakaan budak, dan menggunakan penyeimbangan beban untuk mengurangi tekanan kueri dari setiap perpustakaan budak.
Tujuan menggunakan teknologi pemisahan baca dan tulis adalah untuk secara efektif mengurangi tekanan pada perpustakaan master, dan untuk mendistribusikan permintaan data kueri pengguna ke perpustakaan budak yang berbeda, sehingga memastikan kekokohan sistem. Mari kita lihat latar belakang menggunakan pemisahan baca-tulis.
Ketika bisnis situs web terus berkembang, data terus meningkat, dan lebih banyak pengguna, tekanan pada database menjadi lebih besar dan lebih besar. Metode tradisional, seperti: Database atau optimasi SQL pada dasarnya tidak dapat memenuhi persyaratan. Pada saat ini, strategi pemisahan membaca dan menulis dapat digunakan untuk mengubah status quo.
Khususnya dalam pengembangan, bagaimana cara dengan mudah mencapai pemisahan baca dan tulis? Ada dua metode yang umum digunakan:
1 Metode pertama adalah metode yang paling umum digunakan, yaitu untuk menentukan dua koneksi database, satu adalah MasterDataSource dan yang lainnya adalah SlavedataSource. Saat memperbarui data, kami membaca MasterDataSource, dan ketika menanyakan data, kami membaca SlaveDataSource. Metode ini sangat sederhana, jadi saya tidak akan membahas detailnya.
2 Metode kedua dari switching sumber data dinamis adalah untuk secara dinamis menenun sumber data ke dalam program saat program berjalan, sehingga dapat memilih untuk membaca perpustakaan master atau perpustakaan budak. Teknologi utama yang digunakan adalah: anotasi, pegas AOP, refleksi. Metode implementasi akan dijelaskan secara rinci di bawah ini.
Sebelum memperkenalkan metode implementasi, kami akan menyiapkan beberapa pengetahuan yang diperlukan, kelas abstractroutingDataSource musim semi
Kelas AbstractroutingDataSource telah ditambahkan setelah Musim Semi 2.0. Mari pertama -tama lihat definisi AbstractroutingDataSource:
Salinan kode adalah sebagai berikut:
Kelas Abstrak Publik AbstractroutingDataSource Memperluas AbstractDataSource mengimplementasikan initializingBean {}
AbstractroutingDataSource mewarisi AbstractDataSource, yang merupakan subclass dari DataSource. DataSource adalah antarmuka sumber data javax.sql, didefinisikan sebagai berikut:
DataSource Antarmuka Publik Memperluas CommondataSource, Wrapper { /** * <p> Berusaha untuk membuat koneksi dengan sumber data bahwa * ini <Code> Objek DataSource </code> mewakili. * * @Return koneksi ke sumber data * @Exception SQLEXCEPTION Jika kesalahan akses basis data terjadi */ koneksi getConnection () melempar sqlexception; /** * <p> Berusaha membuat koneksi dengan sumber data yang * ini <code> Objek DataSource </code> mewakili. * * nama pengguna @param Pengguna basis data di sisi siapa koneksi adalah * dibuat * @param kata sandi pengguna * @return koneksi ke sumber data * @exception sqlexception jika kesalahan akses basis data terjadi * @since 1.4 */ koneksi getConnection (string nama pengguna, string kata sandi) melempar sqlexception;} Antarmuka DataSource mendefinisikan dua metode, yang keduanya memperoleh koneksi basis data. Mari kita lihat bagaimana AbstractroutingDataSource mengimplementasikan antarmuka DataSource:
koneksi publik getConnection () melempar sqlexception {return detectInetargetDataSource (). getConnection (); } koneksi publik getConnection (string username, string password) melempar sqlexception {return detectInetargetDataSource (). getConnection (nama pengguna, kata sandi); } Jelas, itu untuk memanggil metode determinetargetDataSource () Anda sendiri untuk mendapatkan koneksi. Metode DetectInetGetDataSource didefinisikan sebagai berikut:
DataSource Detasource yang Dilindungi DeterminetGetDataSource () {assert.notnull (this.resolvedDataSources, "router DataSource tidak diinisialisasi"); Objek lookupkey = determinecurrentlookupkey (); DataSource DataSource = this.resolvedDataSources.get (lookUpkey); if (DataSource == null && (this.lenientfallback || lookupkey == null)) {DataSource = this.resolvedDefaultDataSource; } if (DataSource == null) {lempar baru ilegalstateException ("tidak dapat menentukan sumber data target untuk kunci pencarian [" + lookupkey + "]"); } return DataSource; }Yang paling kita pedulikan adalah dua kalimat berikut:
Objek lookupkey = deteceCurrentLookUpkey (); DataSource DataSource = this.resolvedDataSources.get (lookupkey);
Metode DeterminecurrentLookUpkey Mengembalikan LookUpkey, SecarvedDataSources Metode adalah untuk mendapatkan sumber data dari peta berdasarkan LookUpkey. ResolvedDataSources dan DefectedCurrentLookUpkey didefinisikan sebagai berikut:
peta pribadi <objek, DataSource> ResolvedDataSources; Abstrak Abstrak DeterminecurrentLookUpkey ()
Setelah melihat definisi di atas, apakah kita punya ide? ResolvedDataSources adalah jenis peta. Kita dapat menyimpan masterdataSource dan slavedataSource ke peta, sebagai berikut:
| kunci | nilai |
| menguasai | MasterDataSource |
| budak | SlaveDataSource |
Kami sedang menulis kelas dinamisdataSource yang mewarisi abstractroutingDataSource dan mengimplementasikan metode determinecurrentlookupkey (), yang mengembalikan kunci, master atau slave peta.
Oke, setelah banyak mengatakan, saya sedikit menjengkelkan. Mari kita lihat bagaimana mencapainya.
Teknologi yang ingin kami gunakan telah disebutkan di atas. Pertama -tama mari kita lihat definisi anotasi:
@Retention (retentionpolicy.runtime) @target (elementType.method) public @interface dataSource {string value ();} Kami juga perlu mengimplementasikan kelas abstrak musim semi abstractroutingDataSource, yaitu untuk mengimplementasikan metode determinecurrentlookupkey:
Public Class DynamicDataSource memperluas AbstractroutingDataSource {@Override Protected Object DetectionCurrentLookUpKey () {// TODO Metode yang dihasilkan secara otomatis Stub return return DynamicDataSourceHolder.getDataSouce (); }} kelas publik DynamicDataSourceHolder {public static final ThreadLocal <String> holder = new ThreadLocal <String> (); public static void putDataSource (nama string) {holder.set (name); } public static string getDataSouce () {return holder.get (); }} Dari definisi DynamicDataSource, ia mengembalikan nilai DynamicDataSourceHolder.getDataSouce (). Kita perlu memanggil metode DynamicDataSourceHolder.putDataSource () saat program berjalan dan menetapkan nilai. Berikut ini adalah bagian inti dari implementasi kami, yaitu bagian AOP. DataSourCeaspect didefinisikan sebagai berikut:
Public Class DataSourCeaspect {public void Sebelumnya (point goinpoint) {objek target = point.getTarget (); Metode String = point.getSignature (). GetName (); Kelas <?> [] Classz = target.getClass (). GetInterfaces (); Class <?> [] ParameterTypes = ((Methodyignature) point.getSignature ()) .getMethod (). GetParameterTypes (); coba {Method m = classz [0] .getMethod (metode, parameterTypes); if (m! = null && m.isAnnotationPresent (DataSource.class)) {DataSource data = m .getAnnotation (DataSource.class); DynamicDataSourceHolder.putDataSource (data.Value ()); System.out.println (data.Value ()); }} catch (Exception e) {// todo: menangani pengecualian}}}Untuk kenyamanan pengujian, saya mendefinisikan 2 basis data, perpustakaan master mock shop, pustaka tes mock slave, struktur toko dan tes tes adalah sama, tetapi data berbeda, dan konfigurasi basis data adalah sebagai berikut:
<bean id = "masterdataSource"> <name properti = "driverclassname" value = "com.mysql.jdbc.driver" /> <name properti = "url" value = "jdbc: mysql: //127.0.0.1: 3306 /shop" /<name mysql: //127.0.0.1: 3306 /shop " /<a name mysql: //127.0.0 value = "yangyanping0615"/> </ bean> <bean id = "slaveDataSource"> <name properti = "driverclassname" value = "com.mysql.jdbc.driver"/> <nama properti = "url" value = "jdbc: mysql: //127.127.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0. value = "root" /> <name properti = "kata sandi" value = "yangyanping0615" /> < /bean> <bean: bean id = "DataSource"> <name properti = "targetDataSources"> <peta key-type = "java.Lang.string"> <!-tulis-> <Mata key = "MASTER =" MASTER = "MASTER =" ""> <!-write-> <magery = "magering =" magering = "magering =" "" <" /<!-write-> <magery =" mager = "magering =" mager = ""> <!-write-> <ENTER KEY = "MURTER =" MASTER = "MASTER =" " key="slave" value-ref="slavedataSource"/> </map> </property> <property name="defaultTargetDataSource" ref="masterdataSource"/> </beans:bean> <bean id="transactionManager" > <property name="dataSource" ref="dataSource" /> </bean> <!-- Configure SqlSessionFactoryBean --> <bean id = "sqlSessionFactory"> <name properti = "DataSource" ref = "DataSource" /> <name properti = "configLocation" value = "classpath: config /mybatis-config.xml" /> < /bean>
Tambahkan konfigurasi AOP ke konfigurasi pegas
<!-- Configure database annotation aop --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> <beans:bean id="manyDataSourceAspect" /> <aop:config> <aop:aspect id="c" ref="manyDataSourceAspect"> <aop:pointcut id="tx" expression="execution(* com.air.shop.mapper.*.*(..)) "/> <aop: sebelum pointcut-ref =" tx "method =" sebelum "/> </aop: aspek> </aop: config> <!-Konfigurasikan anotasi database aop->
Berikut ini adalah definisi mybatis usermapper. Untuk kenyamanan pengujian, login membaca perpustakaan master dan daftar pengguna membaca perpustakaan budak:
antarmuka publik usermapper {@datasource ("master") public void add (pengguna pengguna); @Datasource ("Master") Pembaruan public void (pengguna pengguna); @Datasource ("Master") public void delete (int id); @DataSource ("Slave") Public User LoadById (int ID); @DataSource ("Master") User Public LoadByName (nama string); @DataSource ("Slave") Daftar Publik <User> Daftar ();}Oke, jalankan gerhana kami untuk melihat efeknya, masukkan admin nama pengguna dan masuk untuk melihat efeknya
Di atas adalah semua konten artikel ini. Saya berharap ini akan membantu untuk pembelajaran semua orang dan saya harap semua orang akan lebih mendukung wulin.com.