ทุกวันนี้ระบบอีคอมเมิร์ซขนาดใหญ่ส่วนใหญ่ใช้เทคโนโลยีการอ่านและเขียนที่ระดับฐานข้อมูลซึ่งเป็นฐานข้อมูลหลักและฐานข้อมูลทาสหลายแห่ง ไลบรารีหลักมีหน้าที่รับผิดชอบในการอัปเดตข้อมูลและแบบสอบถามข้อมูลเรียลไทม์และไลบรารีทาสมีหน้าที่รับผิดชอบในการสืบค้นข้อมูลที่ไม่ใช่เรียลไทม์ เนื่องจากในแอปพลิเคชันจริงฐานข้อมูลอ่านมากขึ้นและเขียนน้อยลง (ความถี่ของการอ่านข้อมูลสูงและความถี่ของการอัปเดตข้อมูลค่อนข้างเล็ก) และการอ่านข้อมูลมักจะยาวขึ้นและใช้ซีพียูมากขึ้นบนเซิร์ฟเวอร์ฐานข้อมูลซึ่งส่งผลกระทบต่อประสบการณ์ผู้ใช้ วิธีการตามปกติของเราคือการแยกคิวรีจากห้องสมุดหลักใช้ไลบรารีทาสหลายแห่งและใช้การปรับสมดุลโหลดเพื่อลดแรงดันคิวรีของแต่ละไลบรารีทาส
เป้าหมายของการใช้เทคโนโลยีการอ่านและการเขียนคือการลดแรงกดดันต่อไลบรารีหลักอย่างมีประสิทธิภาพและเพื่อแจกจ่ายคำขอข้อมูลการสืบค้นผู้ใช้ไปยังไลบรารีทาสที่แตกต่างกันเพื่อให้มั่นใจถึงความทนทานของระบบ ลองมาดูพื้นหลังของการใช้การแยกอ่าน-เขียน
ในขณะที่ธุรกิจของเว็บไซต์ยังคงขยายตัวข้อมูลยังคงเพิ่มขึ้นและผู้ใช้มากขึ้นความกดดันในฐานข้อมูลจะมากขึ้นเรื่อย ๆ
โดยเฉพาะในการพัฒนาวิธีการแยกการอ่านและการเขียนได้อย่างง่ายดายมีสองวิธีที่ใช้กันทั่วไป:
1 วิธีแรกเป็นวิธีที่ใช้กันมากที่สุดซึ่งคือการกำหนดการเชื่อมต่อฐานข้อมูลสองการเชื่อมต่อหนึ่งคือ MasterDataSource และอื่น ๆ คือ SlavedataSource เมื่ออัปเดตข้อมูลเราจะอ่าน MasterDataSource และเมื่อสอบถามข้อมูลเราจะอ่าน SlavedataSource วิธีนี้ง่ายมากดังนั้นฉันจะไม่เข้าไปดูรายละเอียด
2 วิธีที่สองของการสลับแหล่งข้อมูลแบบไดนามิกคือการสานแหล่งข้อมูลลงในโปรแกรมเมื่อโปรแกรมทำงานเพื่อเลือกที่จะอ่านไลบรารีหลักหรือไลบรารีทาส เทคโนโลยีหลักที่ใช้คือ: คำอธิบายประกอบ, สปริง AOP, การสะท้อน วิธีการใช้งานจะอธิบายในรายละเอียดด้านล่าง
ก่อนที่จะแนะนำวิธีการใช้
AbstractroutingDataSource คลาสได้รับการเพิ่มหลังจากฤดูใบไม้ผลิ 2.0
การคัดลอกรหัสมีดังนี้:
บทคัดย่อระดับสาธารณะ AbstractroutingDataSource ขยาย AbstractDataSource ใช้การเริ่มต้นเบียน {}
AbstractroutingDataSource สืบทอด AbstractDataSource ซึ่งเป็นคลาสย่อยของแหล่งข้อมูล DataSource เป็นอินเทอร์เฟซแหล่งข้อมูลของ javax.sql ซึ่งกำหนดดังนี้:
DataSource ส่วนต่อประสานสาธารณะขยายตัว, commondataSource, wrapper { /** * <p> พยายามสร้างการเชื่อมต่อกับแหล่งข้อมูลที่ * dataSource < /code> วัตถุนี้แสดงให้เห็น นั่นคือ <code> dataSource </code> วัตถุแทน อินเทอร์เฟซ DataSource กำหนดสองวิธีซึ่งทั้งสองอย่างนี้ได้รับการเชื่อมต่อฐานข้อมูล ลองมาดูกันว่า AbstractroutingDataSource ใช้อินเทอร์เฟซ DataSource อย่างไร:
การเชื่อมต่อสาธารณะ getConnection () พ่น SQLException {return dectargetDataSource (). getConnection (); เห็นได้ชัดว่ามันคือการเรียกเมธอด dectargetDataSource () ของคุณเองเพื่อรับการเชื่อมต่อ เมธอด decinetArgetDataSource ถูกกำหนดดังนี้:
DataSource DeCinetArgetDataSource () {assert.notnull (this.resolveddataSources, "เราเตอร์ DataSource ไม่ได้เริ่มต้น"); key == null)) {dataSource = this.resolveddefaultDataSource; if (dataSource == null) {โยน unglemalstateException ใหม่ ("ไม่สามารถกำหนด dataSource เป้าหมายสำหรับคีย์การค้นหา [" + lookupkey + "]");สิ่งที่เราสนใจมากที่สุดคือสองประโยคต่อไปนี้:
Object Lookupkey = DeCinecurrentLookUpkey (); DataSource DataSource = this.resolvedDataSources.get (lookupkey);
วิธีการกำหนดค่าใช้จ่ายในการค้นหาวิธีการค้นหาวิธีการแก้ไขปัญหาการใช้ข้อมูลคือการรับแหล่งข้อมูลจากแผนที่ตามการค้นหา ResolvedDataSources และ enedcurrentlookupkey ถูกกำหนดดังนี้:
แผนที่ส่วนตัว <วัตถุ, DataSource> ResolvedDataSources;
หลังจากเห็นคำจำกัดความข้างต้นเรามีความคิดบางอย่างหรือไม่?
| สำคัญ | ค่า |
| ผู้เชี่ยวชาญ | MasterDataSource |
| ทาส | Slavedatasource |
เรากำลังเขียนคลาส DynamicDataSource ที่สืบทอด AbstractroutingDataSource และใช้วิธีการกำหนดค่าของ Lookupkey () ซึ่งส่งคืนคีย์หลักหรือทาสของแผนที่
โอเคหลังจากพูดมากฉันน่ารำคาญนิดหน่อยมาดูกันว่าจะทำอย่างไร
เทคโนโลยีที่เราต้องการใช้นั้นได้รับการกล่าวถึงข้างต้น
@Retention (RetentionPolicy.Runtime) @Target (ElementType.Method) DataSource สาธารณะ @Interface {ค่าสตริง ();} นอกจากนี้เรายังจำเป็นต้องใช้ AbstractroutingDataSource ระดับนามธรรมของฤดูใบไม้ผลิซึ่งคือการใช้วิธีการกำหนดค่า
ระดับสาธารณะ DynamicDataSource ขยาย AbstractroutingDataSource {@Override วัตถุที่ได้รับการป้องกันการกำหนดค่าใช้จ่าย () {// toDo วิธีการที่สร้างขึ้นโดยอัตโนมัติ Putdatasource (สตริง ชื่อ) {Holder.set (ชื่อ); จากคำจำกัดความของ DynamicDataSource จะส่งคืนค่า DynamicDataSourceHolder.getDatasouce () ต่อไปนี้เป็นส่วนสำคัญของการใช้งานของเรานั่นคือส่วน AOP
DataSourceSpect สาธารณะ {โมฆะสาธารณะก่อน (จุดเข้าร่วม) {วัตถุเป้าหมาย = point.getTarget (); ลอง {วิธี m = classz [0] .getMethod (วิธีการ, พารามิเตอร์); ข้อยกเว้น e) {// todo: จัดการข้อยกเว้น}}}เพื่อความสะดวกในการทดสอบฉันได้กำหนดฐานข้อมูล 2 ฐานข้อมูลร้านค้า Mock Mock Master Library, Test Mock Slave Library, ร้านค้าและโครงสร้างตารางทดสอบเหมือนกัน แต่ข้อมูลแตกต่างกันและการกำหนดค่าฐานข้อมูลมีดังนี้:
<bean id = "MasterDataSource"> <property name = "driverclassname" value = "com.mysql.jdbc.driver" /> <property name = "url" value = "jdbc: mysql: //127.0.0.1: 3306 /bean> <bean id = "slavedataSource"> <property name = "driverclassname" value = "com.mysql.jdbc.driver" /> <property name = "url" value = "jdbc: mysql: //127.0.0.1: 3306/test"/> <property name = "ชื่อผู้ใช้" value = "root"/> <property name = "รหัสผ่าน" ava.lang.string "> <!-เขียน-> <entry key =" master "value-ref =" MasterDataSource "/> <!-อ่าน-> <รายการ key = "slave" value-ref = "slavedataSource"/> </map> </property> <property name = "defaultTargetDataSource" ref = "MasterDataSource"/> </epo SQLSessionFactory "> <property name =" dataSource "ref =" dataSource " /> <property name =" configLocation " value = "classpath: config/mybatis-config.xml"/> </ebean>
เพิ่มการกำหนดค่า AOP ในการกำหนดค่าสปริง
<!-กำหนดค่าคำอธิบายประกอบฐานข้อมูล AOP-> <AOP: ASPAINTJ-AUTOPROXY> < /AOP: ASPECTJ-AUTOPROXY> <Bean: Bean ID = "ManyDataSourceAspect" /> <aop: config> *.*(.. )) "/> <aop: ก่อน pointcut-ref =" tx "method =" ก่อน "/> </aop: แง่มุม> </aop: config> <!-กำหนดค่าคำอธิบายประกอบฐานข้อมูล AOP->
ต่อไปนี้เป็นคำจำกัดความของ mybatis usermapper
อินเทอร์เฟซสาธารณะ usermapper {@datasource ("master") โมฆะสาธารณะเพิ่ม (ผู้ใช้ผู้ใช้); ("slave") รายการสาธารณะ <user> list ();}ตกลงเรียกใช้ eclipse ของเราเพื่อดูเอฟเฟกต์ป้อนผู้ใช้ชื่อผู้ใช้และเข้าสู่ระบบเพื่อดูเอฟเฟกต์
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้