1. مقدمة
عند استخدام Java لتطوير برنامج تطبيق Enterprise ، غالبًا ما يتم استخدام Spring+MyBatis+MySQL لإنشاء إطار قاعدة بيانات. إذا كان حجم البيانات كبيرًا ، فإن مكتبة MySQL تخزن كفاءة الوصول إلى البيانات منخفضة للغاية ، وغالبًا ما تستخدم طريقة إدارة التخزين المسببة للتكاثر. تصف هذه المقالة كيفية إنشاء بنية وصول متعددة المسافات من خلال Spring+MyBatis واستخدام متعدد الخيوط لتحسين كفاءة الوصول إلى قاعدة البيانات.
تجدر الإشارة إلى أن هذه الطريقة مناسبة فقط للمواقف التي يتم فيها إصلاح عدد قواعد البيانات والأسماء ، وليس كبيرة بشكل خاص. استجابةً للموقف الذي لا يتم فيه إصلاح عدد قواعد البيانات ، سأكتب خطة معالجة أخرى لاحقًا.
2. الخطة العامة
3. إعداد بيئة التنمية
3.1 قم بتنزيل Spring ، MyBatis ، مكونات MySQL.
3.2 Eclipse: Java Development IDE. يتم تقديم حزم الجرة التالية:
هيكل الكود كما يلي:
4. بناء مجموعة قاعدة البيانات
قم بإنشاء 11 قاعدة بيانات في MySQL (Test1/2/3/4/5/6/7/8/9/10/11) لإنشاء جدول بسيط:
أدخل 50 مليون قطعة من البيانات في جدول TBL_DEMO في Test1 ، و 5 ملايين قطعة من البيانات في جدول TBL_DEMO في قواعد البيانات العشرة الأخرى (باستخدام وظائف).
أدخل 50 مليون قطعة من البيانات في جدول TBL_DEMO في Test1 ، و 5 ملايين قطعة من البيانات في جدول TBL_DEMO في قواعد البيانات العشرة الأخرى (باستخدام وظائف).
5. إنشاء واجهة تعيين قاعدة بيانات MyBatis
/** * واجهة رسم الخرائط MyBatis * * * Author Elon * version 1.0 ، 23 أكتوبر ، 2015 */واجهة عامة Idemo {public void insertDemo (Demodao Demo) ؛ القائمة العامة <integer> selectGroup () ؛}/** * * واجهة خدمة تعيين MyBatis * * Author Elon * version 1.0 ، 23 أكتوبر 2015 */الواجهة العامة Idemoservice {public void insertdemo (Demodao Demo) ؛ القائمة العامة <integer> SELECTGROUP () ؛}/** * * تنفيذ خدمة تعيين MyBatis * * Author ELON * VERVENT 1.0 ، 23 أكتوبر 2015 */فئة DemoServiceImpl العامة تنفذ Idemoservice {private Idemo Idea = null ؛ public void setIdemo (Idemo Idea) {this.idemo = Idea ؛ } Override public void insertDemo (Demodao Demo) {ideamo.insertDemo (Demo) ؛ } Override Public List <integer> selectGroup () {return Idea.SelectGroup () ؛ }}6. إنشاء إدارة هوية قاعدة البيانات ومصادر البيانات الديناميكية
/** * * احفظ معرف قاعدة البيانات. يتم تخزين كل مؤشر ترابط بواسطة كائن مستقل * * Author Elon * version 1.0 ، 23 أكتوبر 2015 */الفئة العامة dbindetifier {private static threadlocal <string> dbKey = new threadlocal <string> () ؛ public static void setDbKey (سلسلة dbkeypara النهائية) {dbkey.set (dbkeypara) ؛ } سلسلة ثابتة getDBKey () {return dbKey.get () ؛ }}/*** مصدر البيانات الديناميكي. يمكن توصيل قواعد البيانات المختلفة وفقًا لمؤشرات البيانات المختلفة * * Author Elon * Version 1.0 ، 23 أكتوبر 2015 */Class Public Class DynamicDataSource يمتد AbstRactRoutingDataSource {Override Public Object ConferIncurrentOkeupKey () {return dbindetifier.getdbkey () ؛ }}7. إنشاء كائن الوصول إلى قاعدة البيانات
/** * * كائن الوصول إلى قاعدة البيانات. تستخدم لإدراج البيانات. * * Author Elon * @Version 1.0 ، 23 أكتوبر 2015 */فئة عامة Demodao {private int a ؛ سلسلة خاصة ب ؛ Private Int C ؛ public int geta () {return a ؛ } public void seta (int a) {this.a = a ؛ } السلسلة العامة getB () {return b ؛ } public void setb (string b) {this.b = b ؛ } public int getc () {return c ؛ } public void setc (int c) {this.c = c ؛ }}/** * تعريف نتائج التعيين * * Author elon * version 1.0 ، 23 أكتوبر ، 2015 */طبقة عامة DemoreSult تسلسل {/** * التعليق لـ <code> SerialVersionuid </code> <br> * */private static static insialversionuid = -41300113879253148l ؛ مبلغ طويل خاص ؛ Public Long getSum () {return sum ؛ } public void setSum (sum long) {this.sum = sum ؛ } Override public string toString () {return string.valueof (sum) ؛ }}8. قم بإنشاء مهام الوصول إلى قاعدة البيانات
/*** تعريف مهمة الوصول إلى قاعدة البيانات. قم بتعبئة كل طلب إلى الوصول إلى قاعدة البيانات إلى كائن مهمة ، ووضعه في إدارة المهام ، ثم انتظر حتى يقوم تنفيذ المهمة بإكمال واسترداد نتيجة التنفيذ. * * Author Elon * @Varvent 1.0 ، 23 أكتوبر 2015 */Public Class DBTASK تنفذ Runnable {// عملية قاعدة البيانات ، المستخدمة لتحديد قاعدة البيانات التي تم الوصول إليها. تمشيا مع تعريف مصدر البيانات الديناميكي في ملف تكوين الربيع. سلسلة نهائية خاصة DBKEY ؛ // MyBatis Database Access Object Final Final Object DBAccessObject ؛ . // قم بتخزين قيمة الكائن النهائي الخاص المتغير المعلمات [] Paraarray ؛ . // نتيجة تشغيل قاعدة البيانات. تقوم عملية الاستعلام بإرجاع نتيجة الاستعلام ؛ إدراج وحذف وتعديل عمليات إرجاع فارغة. كائن خاص العمليات ؛ // معلومات الاستثناء التي ألقاها قاعدة بيانات التشغيل استثناء استثناء خاص ؛ // تحديد ما إذا كانت المهمة قد تم تنفيذها المنطقية الخاصة ؛ / *** مُنشئ* param dbkey معرف قاعدة البيانات* param dbaccessobject كائن الوصول إلى قاعدة البيانات* param methodname database method method* @param paraarray list*/ public dbtask (final string dbkey ، dbacky dbaccessobject ، methodname final ، paraarray) this.dbAccessObject = dBAccessObject ؛ this.methodname = methodName ؛ this.paraarray = paraarray ؛ الانتهاء = خطأ. استثناء = فارغ ؛ paraclassarray = فئة جديدة [paraarray.length] ؛ لـ (int index = 0 ؛ index <paraarray.length ؛ ++ index) {paraclassarray [index] = paraarray [index] .getClass () ؛ } operateresult = null ؛ } / *** وظيفة تنفيذ المهمة** / Override public void run () {try {dbindetifier.setdbkey (dbkey) ؛ طريقة طريقة = dbaccessObject.getClass (). getMethod (MethodName ، paraclassarray) ؛ // تقوم عملية الاستعلام بإرجاع نتيجة الاستعلام ؛ إدراج وحذف وتعديل عمليات إرجاع الفارغول = method.invoke (DBAccessObject ، paraarray) ؛ } catch (استثناء e) {استثناء = e ؛ E.PrintStackTrace () ؛ } الانتهاء = صحيح ؛ } /** * * إرجاع نتيجة العملية. عملية الاستعلام إرجاع نتائج الاستعلام ؛ أدخل وحذف وتعديل عمليات الإرجاع NULL * * RETURN نتيجة */ كائن عام getRetValue () {return OperateResult ؛ } / *** رمي عملية قاعدة البيانات استثناء** @استثناء RETURN* / استثناء عام getException () {return inspected ؛ } / **** إرجاع ما إذا كان قد تم تنفيذ المهمة** tag* / public boolean isFinish () {return finish ؛ }}9. إنشاء مدير مهمة قاعدة بيانات
/*** إدارة مهمة الوصول إلى قاعدة البيانات. ضع مهمة الوصول إلى قاعدة البيانات في مجموعة مؤشرات الترابط لتنفيذها. * * * Author Elon * @Version 1.0 ، 23 أكتوبر 2015 */الفئة العامة dbtaskmgr {private static class dbtaskmgrinstance {public static final dbtaskmgr مثيل = جديد dbtaskmgr () ؛ } مثيل dbtaskmgr ثابت عام () {return dbtaskmgrinstance.instance ؛ } تجمع خاص threadpoolexecutor ؛ public dbtaskmgr () {pool = new threadpoolexecutor (10 ، 50 ، 60 ، timeUnit.Seconds ، ArrayBlockingqueue <Runnable> (10000) ، ThreadPoolexecutor.CallerRunspolicy ()) ؛ } public void excute (task runnable) {pool.execute (task) ؛ }}10. إنشاء ملف تكوين MyBatis
10.1 mybatis.xml
<؟ Resource = "CFG/DEMOMAPPER.XML"/> </mappers> </ispication>
10.2 demomapper.xml
<؟ id = "insertDemo" parametertype = "com.elon.demodao"> insert في TBL_DEMO (a ، b ، c) القيم ( #{a} ، #{b} ، #{c}) ؛ </sert> <resultmap id = "demoreult" type = "com.elon.demoresult"> <id property = "sum" column = "sumcolum"/> </sultresuremap> <select id = "selectgroup" resultmap = "demoreul </select> </tegper>11. إنشاء ملف تكوين الربيع
11.1 Spring.xml
<؟ XSI: schemalocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <vatasource_1 "> value = "com.mysql.jdbc.driver"> </property> <property name = "url" value = "jdbc: mysql: //10.70.69.69: 3306/test1"> </property> <property name = "username" value = "user123" value = "100"> </swerperal> <property name = "maxidle" value = "30"> </property> <property name = "maxwait" value = "500"> </property> <property name = "defaultautocommit value = "com.mysql.jdbc.driver"> </property> <property name = "url" value = "jdbc: mysql: //10.70.69.69: 3306/test2"> </property> <property name = "username" value = "user123" value = "100"> </swerperal> <property name = "maxidle" value = "30"> </sprention> <property name = "maxwait" value = "500"> </property> <property name = "defaultautocommit value = "com.mysql.jdbc.driver"> </property> <property name = "url" value = "jdbc: mysql: //10.70.69.69: 3306/test3"> </property> <property name = "username" value = "user123" value = "100"> </swerperal> <property name = "maxidle" value = "30"> </sprement> <property name = "maxwait" value = "500"> </splyment> <property name = "defaultautocommit value = "com.mysql.jdbc.driver"> </property> <property name = "url" value = "jdbc: mysql: //10.70.69.69: 3306/test4"> </property> <property name = "username" value = "user123" value = "100"> </swerperal> <property name = "maxidle" value = "30"> </property> <property name = "maxwait" value = "500"> </sopperation> <property name = "defaultautocommit value = "com.mysql.jdbc.driver"> </property> <property name = "url" value = "jdbc: mysql: //10.70.69.69: 3306/test5"> </property> <property name = "username" value = "user123" value = "100"> </property> <property name = "maxidle" value = "30"> </property> <property name = "maxwait" value = "500"> </splyment> <property name = "defaultautocommit value = "com.mysql.jdbc.driver"> </property> <property name = "url" value = "jdbc: mysql: //10.70.69.69: 3306/test6"> </property> <property name = "username" value = "user123" value = "100"> </swerperal> <property name = "maxidle" value = "30"> </property> <property name = "maxwait" value = "500"> </spertor> <property name = "defaultautocommit value = "com.mysql.jdbc.driver"> </property> <property name = "url" value = "jdbc: mysql: //10.61.67.246: 3306/test7"> </propert name = "maxactive" value = "100"> </property> <property name = "maxidle" value = "30"> </property> <property name = "maxwait" value = "500"> </spleneration> <property name = "defaultoCommit" value = "true"> </propert value = "com.mysql.jdbc.driver"> </property> <property name = "url" value = "jdbc: mysql: //10.61.67.246: 3306/test8"> </propert name = "maxactive" value = "100"> </property> <property name = "maxidle" value = "30"> </property> <property name = "maxwait" value = "500"> </spleneration> <property name = "defaultoCommit value = "com.mysql.jdbc.driver"> </property> <property name = "url" value = "jdbc: mysql: //10.61.67.246: 3306/test9"> </propert name = "maxactive" value = "100"> </property> <property name = "maxidle" value = "30"> </property> <property name = "maxwait" value = "500"> </sprement> <property name = "defaultoCommit value = "com.mysql.jdbc.driver"> </property> <property name = "url" value = "jdbc: mysql: //10.61.67.246: 3306/test10"> </property> <property name = username "value = user123" name = "maxactive" value = "100"> </property> <property name = "maxidle" value = "30"> </property> <property name = "maxwait" value = "500"> </sprement> <property name = "defaultoCommit value = "com.mysql.jdbc.driver"> </property> <property name = "url" value = "jdbc: mysql: //10.61.67.246: 3306/test11"> </spertar name = "maxactive" value = "100"> </property> <property name = "maxidle" value = "30"> </property> <property name = "maxwait" value = "500" key = "test1" value-ref = "dataSource_1"/> <interpl exply = "test2" value-ref = "dataSource_2"/> <interply key = "test3" value-res = key = "test6" value-ref = "dataSource_6"/> <interpl exply = "test7" value-ref = "dataSource_7"/> <interply key = "test8" value-res = key = "test11" value-ref = "dataSource_11"/> </map> </property> </boun> <bean id = "sqlsessionfactory"> <property name = "configlocation" value = "classpath: cfg/mybatis.xml"> </propert name = "mapPerInterface" value = "com.elon.idemo"> </property> <property name = "sqlsessionfactory" ref = "sqlsessionfactory"> </property> </bean> <bean id = "idemoservice"> property name = "idemo" ref = "idemo"
12. رمز الاختبار
الفئة العامة testmain {/** * رمز الاختبار * * * param args */public static void main (string [] args) {suppressWarnings ("Resource") ApplicationContext context = new ClassPathmLapplicationContext ("cfg/spring.xml") ؛ idemoservice service1 = (idemoservice) context.getBean ("idemoservice") ؛ // إنشاء كائن المهمة dbtask task1 = new dbtask ("test1" ، service1 ، "selectGroup") ؛ dbtask task2 = new dbtask ("test2" ، service1 ، "selectGroup") ؛ dbtask task3 = new dbtask ("test3" ، service1 ، "selectGroup") ؛ dbtask task4 = new dbtask ("test4" ، service1 ، "selectGroup") ؛ dbtask task5 = new DBTASK ("test5" ، service1 ، "selectGroup") ؛ dbtask task6 = new dbtask ("test6" ، service1 ، "selectGroup") ؛ dbtask task7 = new dbtask ("test7" ، service1 ، "selectGroup") ؛ dbtask task8 = new dbtask ("test8" ، service1 ، "selectGroup") ؛ dbtask task9 = new dbtask ("test9" ، service1 ، "selectGroup") ؛ dbtask task10 = new dbtask ("test10" ، service1 ، "selectGroup") ؛ dbtask task11 = new dbtask ("test11" ، service1 ، "selectGroup") ؛ DEMODAO DEMO = جديد DEMODAO () ؛ Demo.seta (10000000) ؛ Demo.SetB ("12121212") ؛ Demo.Setc (100) ؛ dbtask taskInsert = new dbtask ("test2" ، service1 ، "insertdemo" ، demo) ؛ تنسيق SimplEdateFormat = جديد SimplEdateFormat ("Yyyy-MM-DD HH: MM: SS") ؛ System.out.println ("بدء إدراج بيانات:" + format.format (New Date ())) ؛ dbtaskmgr.instance (). excute (TaskInsert) ؛ بينما (صحيح) {if (! taskInsert.isfinish ()) {try {thread.sleep (1000) ؛ } catch (interruptedException e) {E.PrintStackTrace () ؛ }} آخر {break ؛ }} system.out.println ("insert data end:" + format.format (new date ())) ؛ System.out.println ("ابدأ في الاستعلام عن جدول البيانات 50 مليون:" + format.format (New Date ())) ؛ dbtaskmgr.instance (). excute (task1) ؛ بينما (صحيح) {if (! task1.isfinish ()) {try {thread.sleep (1000) ؛ } catch (interruptedException e) {E.PrintStackTrace () ؛ }} آخر {break ؛ }} system.out.println (task1.getRetValue ()) ؛ System.out.println ("Query 50 مليون بيانات جدول البيانات:" + format.format (New Date ())) ؛ قائمة <Dbtask> TaskList = New ArrayList <DBTASK> () ؛ TaskList.add (Task2) ؛ TaskList.add (Task3) ؛ TaskList.add (Task4) ؛ TaskList.add (Task5) ؛ TaskList.add (Task6) ؛ TaskList.add (Task7) ؛ TaskList.add (Task8) ؛ TaskList.add (Task9) ؛ TaskList.add (Task10) ؛ TaskList.add (Task11) ؛ system.out.println ("ابدأ الاستعلام 10 مليون جداول بيانات:" + format.format (date ())) ؛ لـ (dbtask Task: TaskList) {dbtaskmgr.instance (). Excute (Task) ؛ } بينما (صحيح) {int success = 0 ؛ لـ (dbtask Task: TaskList) {if (! task.isfinish ()) {try {thread.sleep (1000) ؛ } catch (interruptedException e) {E.PrintStackTrace () ؛ }} آخر {++ النجاح ؛ }} if (success == 10) {break ؛ }} لـ (dbtask Task: TaskList) {system.out.println (task.getRetValue ()) ؛؛ } system.out.println ("10 مليون بيانات استعلام جدول البيانات:" +format.format (date ())) ؛ }}13. نتائج الاختبار
يستغرق الأمر 45 عامًا للاستعلام مباشرة عن قاعدة بيانات من 50 مليون بيانات.
يتطلب الأمر 22s للاستعلام عن 10 قواعد بيانات مع 5 ملايين بيانات بطريقة متزامنة.
منذ وضع 10 قواعد بيانات على خادمين ، يحتوي خادم واحد على 5 قواعد بيانات. إذا تم نشر 10 بيانات على 10 خوادم بشكل منفصل ، فستكون الكفاءة أعلى.
لخص
ما سبق هو مقدمة المحرر إلى Spring+MyBatis+MySQL لإنشاء إطار وصول قاعدة بيانات موزع. آمل أن يكون ذلك مفيدًا للجميع. إذا كان لديك أي أسئلة ، فيرجى ترك رسالة لي وسوف يرد المحرر على الجميع في الوقت المناسب. شكرا جزيلا لدعمكم لموقع wulin.com!