في الوقت الحاضر ، تستخدم أنظمة التجارة الإلكترونية على نطاق واسع في الغالب تقنية القراءة والكتابة على مستوى قاعدة البيانات ، وهي قاعدة بيانات رئيسية وقواعد بيانات عبودية متعددة. المكتبة الرئيسية هي المسؤولة عن تحديثات البيانات والاستعلام عن البيانات في الوقت الفعلي ، ومكتبة الرقيق مسؤولة عن استعلام البيانات غير الواقعية. لأنه في التطبيقات الفعلية ، تقرأ قواعد البيانات أكثر وتكتب أقل (تواتر بيانات القراءة مرتفع وتكرار تحديث البيانات صغير نسبيًا) ، وعادة ما تكون بيانات القراءة أطول وتحتل مزيد من وحدات المعالجة المركزية على خادم قاعدة البيانات ، مما يؤثر على تجربة المستخدم. تتمثل نهجنا المعتاد في استخراج الاستعلام من المكتبة الرئيسية ، واستخدام مكتبات العبيد المتعددة ، واستخدام موازنة التحميل لتقليل ضغط الاستعلام لكل مكتبة عبيد.
الهدف من استخدام تقنية الفصل القراءة والكتابة هو تقليل الضغط على المكتبة الرئيسية بفعالية ، وتوزيع طلبات بيانات استعلام المستخدم على مكتبات العبيد المختلفة ، وبالتالي ضمان متانة النظام. دعونا نلقي نظرة على خلفية استخدام فصل القراءة والكتابة.
مع استمرار التوسع في أعمال موقع الويب ، تستمر البيانات في الزيادة ، ويصبح المزيد من المستخدمين ، يصبح الضغط على قاعدة البيانات أكبر وأكبر. الأساليب التقليدية ، مثل: قاعدة البيانات أو تحسين SQL لا يمكن أن تلبي المتطلبات بشكل أساسي. في هذا الوقت ، يمكن استخدام استراتيجية فصل القراءة والكتابة لتغيير الوضع الراهن.
على وجه التحديد في التطوير ، كيفية تحقيق فصل القراءة والكتابة بسهولة؟ هناك طريقتان شائعتين:
1 الطريقة الأولى هي الطريقة الأكثر استخدامًا ، والتي تتمثل في تحديد اتصالات قاعدة البيانات ، أحدهما هو MasterDataSource والآخر هو slavedataSource. عند تحديث البيانات ، نقرأ MasterDataSource ، وعند الاستعلام عن البيانات ، نقرأ slavedataSource. هذه الطريقة بسيطة للغاية ، لذلك لن أخوض في التفاصيل.
2 الطريقة الثانية لتبديل مصدر البيانات الديناميكي هي نسج مصدر البيانات ديناميكيًا في البرنامج عند تشغيل البرنامج ، وذلك لاختيار قراءة المكتبة الرئيسية أو مكتبة الرقيق. التقنيات الرئيسية المستخدمة هي: التعليق التوضيحي ، الربيع AOP ، الانعكاس. سيتم وصف طريقة التنفيذ بالتفصيل أدناه.
قبل تقديم طريقة التنفيذ ، سنقوم بإعداد بعض المعرفة اللازمة ، فئة الربيع المزعجة
تمت إضافة فئة AbstRactRoutingDataSource بعد Spring 2.0. دعونا أولاً نلقي نظرة على تعريف AbstRactRoutingDataSource:
نسخة الكود كما يلي:
الطبقة التجريدية العامة AbstRactRoutingDataSource تمتد AbstractDataSource الأدوات التهيئة {}
AbstractroutingDataSource يرث AbstractDataSource ، وهو فئة فرعية من مصدر البيانات. DataSource هي واجهة مصدر البيانات لـ javax.sql ، التي يتم تعريفها على النحو التالي:
يمتد DataSource الواجهة العامة CommonDataSource ، Wrapper { /** * <p> يحاول إنشاء اتصال مع مصدر البيانات الذي يمثله كائن DataSource </code> هذا. * * RETURN اتصال إلى مصدر البيانات * exception sqlexception في حالة حدوث خطأ في الوصول إلى قاعدة البيانات */ connection getConnection () يلقي sqlexception ؛ /** * <p> يحاول إنشاء اتصال بمصدر البيانات الذي يمثله هذا الكائن * <code> dataSource </code>. *. تحدد واجهة مصدر البيانات طريقتين ، وكلاهما يحصل على اتصالات قاعدة البيانات. دعونا نلقي نظرة على كيفية تنفيذ AbstRactRactroutingDataSource واجهة مصدر البيانات:
الاتصال العام getConnection () يلقي sqlexception {return deturnetArgetDataSource (). getConnection () ؛ } الاتصال العام getConnection (اسم مستخدم السلسلة ، كلمة مرور السلسلة) يلقي sqlexception {return decondInetArgetDataSource (). getConnection (اسم المستخدم ، كلمة المرور) ؛ } من الواضح ، هو استدعاء طريقة denterInetArgetDataSource () للحصول على الاتصال. يتم تعريف طريقة densionArgetDataSource على النحو التالي:
DataSource DETERNETARGETDATASOURCE () {Assert.notnull (this.resolvedDataSources ، "DataSource Router غير تهيئة") ؛ Object lookupkey = decondInecurrentLookupKey () ؛ datasource dataSource = this.resolvedDatasources.get (lookupkey) ؛ if (datasource == null && (this.lenientfallback || lookupkey == null)) {datasource = this.resolvedDefaultDataSource ؛ } if (dataSource == null) {رمي جديد alficalstateException ("لا يمكن تحديد مصدر البيانات المستهدف لمفتاح البحث [" + lookupkey + "]") ؛ } إرجاع مصدر البيانات ؛ }أكثر ما نهتم به هو الجملتين التاليتين:
Object lookupkey = decondInecurrentLookePkey () ؛ dataSource dataSource = this.resolvedDataSources.get (lookupkey) ؛
طريقة DETINCURRENTOLKEPKEY إرجاع LookupKey ، طريقة ResolvedDataSources هي الحصول على مصدر البيانات من الخريطة استنادًا إلى LookupKey. يتم تعريف ResolvedDataSources و CriteCurrentLookepkey على النحو التالي:
خريطة خاصة <object ، dataSource> resolvedDataSources ؛ كائن تجريدي محمي محدد ursurrentookupkey ()
بعد رؤية التعريف أعلاه ، هل لدينا بعض الأفكار؟ ResolvedDataSources هو نوع الخريطة. يمكننا حفظ MasterDataSource و slavedataSource على الخريطة ، على النحو التالي:
| مفتاح | قيمة |
| يتقن | MasterDataSource |
| عبد | slavedataSource |
نحن نكتب DynamicDataSource الطبقة التي ترث AbstractractRoutingDataSource وتنفذ طريقة تحديدها urnecurrentlookupkey () ، والتي تُرجع المفتاح أو سيد أو عبد الخريطة.
حسنًا ، بعد أن أقول الكثير ، أنا مزعج بعض الشيء. دعونا نرى كيفية تحقيق ذلك.
تم ذكر التكنولوجيا التي نريد استخدامها أعلاه. دعونا أولاً نلقي نظرة على تعريف التعليق التوضيحي:
@repinent (attreentionpolicy.runtime) target (elementType.method) public interface dataSource {string value () ؛} نحتاج أيضًا إلى تنفيذ فئة Spring AbstractractRoutingDataSource ، والتي تتمثل في تنفيذ طريقة denterInecurrentLookupKey:
يمتد DynamicDataSource من الطبقة العامة abstractractroutingdataSource {Override كائن محمي DETERNECURRENTLOCKUPKEY () {// todo method method method clud dynamicdatasourceholder.getdatasouce () ؛ }} الفئة العامة DynamicDataSourceHolder {public static Final Threadlocal <string> حامل = new threadlocal <string> () ؛ putDataSource putDataSource (اسم السلسلة) {holder.set (name) ؛ } سلسلة ثابتة عامة getDatasouce () {return Holder.get () ؛ }} من تعريف DynamicDataSource ، فإنه يعيد قيمة DynamicDataSourceHolder.getDatasouce (). نحتاج إلى استدعاء طريقة DynamicDataSourceHolder.putDataSource () عند تشغيل البرنامج وتعيينه. فيما يلي الجزء الأساسي من تنفيذنا ، أي الجزء AOP. يتم تعريف DataSourCeaspress على النحو التالي:
الفئة العامة dataSourCeaspect {public void قبل (نقطة JoinPoint) {Object target = point.getTarget () ؛ طريقة السلسلة = point.getSignature (). getName () ؛ الفئة <؟> [] classz = target.getClass (). getInterFaces () ؛ class <؟> [] parametertypes = ((MaysIngureature) point.getSignature ()) .getMethod (). getParameterTypes () ؛ حاول {method m = classz [0] .getMethod (method ، parametertypes) ؛ if (m! = null && m.iSannotationPresent (dataSource.Class)) {dataSource data = m .getAnnotation (datasource.class) ؛ DynamicDataSourceHolder.putDataSource (data.value ()) ؛ system.out.println (data.value ()) ؛ }} catch (استثناء e) {// todo: مقبض الاستثناء}}}}من أجل راحة الاختبار ، قمت بتعريف قواعد البيانات 2 ، مكتبة Mock Master Shop ، واختبار مكتبة الرقيق ، وهياكل المتجر وجدول الاختبار هي نفسها ، لكن البيانات مختلفة ، وتكوين قاعدة البيانات كما يلي:
<bean id = "masterDataSource"> <property name = "driverClassName" value = "com.mysql.jdbc.driver" /> <property name = "url" value = "jdbc: mysql: //127.0.0.1: 3306 /shop" /> <property name = username value = "yangyanping0615"/> </bean> <bean id = "slavedatasource"> <property name = "driverClassName" value = "com.mysql.jdbc.driver"/> <property name = "url" value = "jdbc: mysql: //127.0.1: 3306/test" /> <property name = "password" value = "yangyanping0615" /> </bean> <beans: bean id = "datasource"> <property name = "targetdatasources"> <map key-type = "java.lang.string"> <! value-ref = "slavedataSource"/> </map> </property> <property name = "defaultTargetDataSource" ref = "masterdatasource"/> </beans: bean> <bean id = "transactionManager"> <property name = "datasource ref =" datasource "/>- id = "sqlsessionfactory"> <property name = "dataSource" ref = "datasource" /> <property name = "configlocation" value = "classpath: config /mybatis-config.xml" /> </bean>
إضافة تكوين AOP إلى تكوين الربيع
<!-تكوين شرح قاعدة البيانات AOP-> <aOP: SideJ-Autoproxy> < /aop: sidej-autoproxy> <beans: bean id = "manyDataSourCeaspect" /> <aop: config> <aop: side id = "c com.air.shop.mapper.*.*(..)) "/> <aop: قبل pointcut-ref =" tx "method =" before "/> </aop: side> </aop: config> <!-تكوين تعليقات قاعدة البيانات aop->
ما يلي هو تعريف mybatis usermapper. لراحة الاختبار ، يقرأ تسجيل الدخول المكتبة الرئيسية وقائمة المستخدم تقرأ مكتبة الرقيق:
الواجهة العامة usermapper {dataSource ("master") public void add (مستخدم المستخدم) ؛ dataSource ("Master") تحديث الفراغ العام (مستخدم المستخدم) ؛ datasource ("Master") حذف الفراغ العام (int id) ؛ dataSource ("Slave") المستخدم العام loadbyid (int id) ؛ dataSource ("Master") المستخدم العام loadbyname (اسم السلسلة) ؛ dataSource ("Slave") قائمة عامة <Sether> list () ؛}حسنًا ، قم بتشغيل Eclipse لمعرفة التأثير ، وأدخل اسم المستخدم وتسجيل الدخول لمعرفة التأثير
ما سبق هو كل محتوى هذه المقالة. آمل أن يكون ذلك مفيدًا لتعلم الجميع وآمل أن يدعم الجميع wulin.com أكثر.