Konfigurieren und Verwenden von Apache Ignite als MyBatis Second Level Cache (L2-Cache)

    In diesem Artikel werde ich erläutern, wie Sie Apache Ignite als Cache der zweiten Ebene für MyBatis konfigurieren und den Cache-Eintrag in Apache Ignite anzeigen. Was ist Apache Ignite? Dies ist eine verteilte, leistungsstarke Plattform für In-Memory-Computing mit den Hauptmerkmalen:

    Bild



    • mit verteilter Speicherung von Objekten In-Memory Data Grid, Implementierung von JSR 107 (Jcache)
    • mit verteiltem Rechnen im RAM
    • mit verteilten Nachrichten und Ereignissen
    • mit einem In-Memory-Beschleuniger für Hadoop und Spark.

    Warum Apache Ignite? Wir haben lange Zeit EhCache und Oracle Coherence verwendet. Danach sind wir aufgrund der einfachen Bedienung auf HazelCast umgestiegen. In neueren Versionen reduzierte HazelCast die Leistung in der Open Source-Version, und wir waren auch daran interessiert, sie als eine einzige Plattform für Spark und Hadoop zu verwenden.

    Warum MyBatis? Die Wahl zwischen Hibernate und MyBatis ist wie die Wahl zwischen den Marken BMW und Mercedes. Die native SQL-Unterstützung und der Speicherort von SQL-Skripten an einem Ort (nicht über alle Quellcodes verteilt) sind für uns sehr wichtig, damit SQL-Abfragen bequem optimiert werden können.

    Недавно Apache Ignite анонсировал поддержку MyBatis в качестве 2-ого уровня кэша, и мы решили протестировать его функциональность и производительность. Любые операции с базами данными стоят дорого, поэтому одна из основных задач для увеличения производительности систем – уменьшить число обращений к БД: т.е. использовать кэш.
    Время отклика на запрос можно рассчитать по простой формуле:

    T = tacq + treq + texec + tres

    где:

    tacq – время приобретения соединения
    treq – время отправки запроса к БД
    texec – время выполнения запроса в БД
    tres- Zeit, um eine Antwort von der Datenbank zu erhalten


    Für eine gut optimierte Abfrage beträgt die minimale Antwortzeit 20 bis 150 ms.

    MyBatis Tech unterstützt standardmäßig 2 Cache-Ebenen:

    • Caching in lokaler Sitzung Lokaler Cache (standardmäßig aktiviert)
    • Cache der zweiten Ebene 2 nd Ebene


    Standardmäßig verwendet MyBatis nur Caching der ersten Ebene (L1-Cache), dh, in einer Sitzung zwischengespeicherte Objekte sind für eine andere Sitzung nicht verfügbar. Es kann jedoch auch die globale 2. Ebene verwendet werden: In ihr stehen zwischengespeicherte Objekte für alle Sitzungen zur Verfügung. Dies verbessert normalerweise die Leistung, da jede neue Sitzung Daten aus dem L2-Cache verwendet.

    Mybatis 2 nd Level - Cache speichert Daten oder Informationen über Objekte (Rechtsträger Daten) und besitzen das Objekt nicht in den Ruhezustand. Die Daten im Cache werden im Format 'Serialized' gespeichert - eine Hash-Tabelle, bei der der Schlüssel die Kennung der Entität ist und die Werte eine Liste von Parameterwerten sind.

    Im folgenden Beispiel sehen Sie den Cache der Einträge in apache ignite für den MyBatis 2nd Level Cache.



    Wo:

    Cache-Schlüssel:[idHash=1499858, hash=2019660929, checksum=800710994, count=6, multiplier=37,hashcode=2019660929, updateList=[com.blu.ignite.mapper.UserMapper.getUserObject, 0, 2147483647, SELECT * FROM all_objects t where t.OBJECT_TYPE='TABLE' and t.object_name=?, USERS, SqlSessionFactoryBean]]
    Werteklasse: java.util.ArrayList
    Cache-Wert:[UserObject [idHash=243119413, hash=1658511469, owner=C##DONOTDELETE, object_type=TABLE, object_id=94087, created=Mon Feb 15 13:59:41 MSK 2016, object_name=USERS]]


    In unserem Fall ist der Schlüssel eine SQL-Abfrage."SELECT * FROM all_objects t where t.OBJECT_TYPE='TABLE' and t.object_name=?"

    Als Beispiel habe ich die Systemtabelle 'all_objects' aus dem Oracle-DBMS und die folgenden Abfragen genommen:

    QUERY_1: SELECT * FROM all_objects t where t.OBJECT_TYPE='TABLE' and t.object_name='EMP';
    QUERY_2: SELECT * FROM all_objects t where t.OBJECT_TYPE='TABLE';
    QUERY_3: SELECT count(*) FROM all_objects;

    SandBox-Funktionen:
    Apache zünden Cluster
    2 virtuelle Maschinen (VM Ware)
    CPU: 2
    RAM : 4 GV
    Java HEAP : 2 GV
    Betriebssystem : Red Hat Santigo
    JVM : Oracle JVM 1.7_45
    Oracle 12c
    virtuelle Maschine (VM Ware)
    CPU : 4
    RAM : 8 GV
    Betriebssystem : Red Hat Santigo
    Eigenständige Java-App + SoapUI
    MacBook Pro
    CPU : 4
    RAM : 16 GV
    JVM : Oracle JVM 1.7_45

    Wenn Sie die obigen SQL-Abfragen (QUERY1-3) über SQL Developer ausführen, erhalten Sie die folgende Antwortzeit:
    Nr
    Name der Anfrage
    Reaktionszeit (mc)
    1
    QUERY_1: SELECT * FROM all_objects t where t.OBJECT_TYPE='TABLE' and t.object_name='EMP';
    ~ 660
    2
    QUERY_2: SELECT * FROM all_objects t where t.OBJECT_TYPE='TABLE';
    ~ 378
    3
    QUERY_3: SELECT count(*) FROM all_objects;
    ~ 700

    Fügen Sie nun Apache Ignite als Level 2-Cache hinzu und sehen Sie sich das Ergebnis an. Anweisungen zur Installation von Apache Ignite finden Sie in meinem Blog und alle Quellcodes auf Github .

    Fügen Sie im Maven-Projekt die mybatis-ignite-Bibliothek hinzu:

    org.mybatis.cachesmybatis-ignite1.0.0-beta1

    Fügen Sie MyBatis SQL Mapper hinzu

     
    

    Hier sind wir:
    • Geben Sie den Cache-Adapter im IgniteCacheAdapter an
    • Geben Sie für jede SQL-Abfrage useCache = "true" an, dh aktivieren Sie den Caching-Modus.

    Fügen Sie Zündfederkonfigurationen hinzu

    
            
                     
                          
                    
                          
                   
                   
                
            
        
        
            
                
                        
                            
                                IP_ADDRESS_IGNITE_NODE
                                IP_ADDRESS_IGNITE_NODE
                            
                        
                    
                
            
        

    Achten Sie besonders darauf, dass Sie "clientMode" auf "false" setzen. Es ermöglicht Ihnen, cacheMode = Partitioned zu verbinden, wobei wir den partitionierten Cache verwenden, um Daten zwischen Cache-Knoten auszutauschen. Eine weitere Option ist die Aktivierung des Replikationsmodus, mit dem Daten zwischen allen Caching-Knoten repliziert werden.

    statisticsEnabled = true, Ermöglicht das Abrufen von Statistiken zur Cachenutzung: Trefferanzahl usw.

    writeSynchronizationMode= FULL_SYNCErmöglicht das vollständige Synchronisieren zwischengespeicherter Daten mit Sicherungsknoten.

    Fügen Sie die entsprechende Java-Schnittstelle hinzu:

    public interface UserMapper {
           User getUser( String id);
    List getUniqueJob();
    UserObject getUserObject(String objectName);
    String allObjectCount();
    List getAllObjectsTypeByGroup();
    }

    Sowie ein einfacher Seifenservice

    @WebService(name = "IgniteTestServices",
            serviceName=" IgniteTestServices ",
            targetNamespace = "http://com.blu.rules/services")
    public class WebServices {
        private UserServices userServices;
        @WebMethod(operationName = "getUserName")
        public String getUserName(String userId){
            User user = userServices.getUser(userId);
            return user.getuName();
        }
        @WebMethod(operationName = "getUserObject")
        public UserObject getUserObject(String objectName){
            return userServices.getUserObject(objectName);
        }
        @WebMethod(operationName = "getUniqueJobs")
        public List getUniqueJobs(){
            return userServices.getUniqueJobs();
        }
        @WebMethod(exclude = true)
        public void setDao(UserServices userServices){
            this.userServices = userServices;
        }
        @WebMethod(operationName = "allObjectCount")
        public String allObjectCount(){
            return userServices.allObjectCount();
        }
        @WebMethod(operationName = "getAllObjectsTypeCntByGroup")
        public List getAllObjectsTypeCntByGroup(){
            return userServices.getAllObjectCntbyGroup();
        } 
    }
    

    Wenn wir nach erfolgreicher Kompilierung des Projekts die Webmethode 'getAllObjectsTypeCntByGroup' aufrufen, erhöht sich die Antwortzeit in meinem Fall über SoapUi auf ~ 1600 ms.



    Ab dem zweiten Mal sollte sich die Antwortzeit erheblich verkürzen, da das Ergebnis vom Apache Ignite-Cache zurückgegeben wird und die Datenbankanforderung nicht empfangen wird.



    Nach dem ersten Aufruf der Web-Methode beträgt die Antwortzeit nun 5-6 ms.

    In Apache Ignite sieht der Cache-Eintrag folgendermaßen aus:



    Cache-Schlüssel: [idHash=46158416, hash=1558187086, checksum=2921583030, count=5, multiplier=37, hashcode=1558187086, updateList=[com.blu.ignite.mapper.UserMapper.getAllObjectsTypeByGroup, 0, 2147483647, SELECT t.object_type, count(*) as cnt FROM all_objects t group by t.OBJECT_TYPE, SqlSessionFactoryBean]]
    Wertklasse: java.util.ArrayList
    Cache-Wert: [UobjectGroupBy [idHash=2103707742, hash=1378996400, cnt=1, object_type=EDITION], UobjectGroupBy [idHash=333378159, hash=872886462, cnt=444, object_type=INDEX PARTITION], UobjectGroupBy [idHash=756814918, hash=1462794064, cnt=32, object_type=TABLE SUBPARTITION], UobjectGroupBy [idHash=931078572, hash=953621437, cnt=2, object_type=CONSUMER GROUP], UobjectGroupBy [idHash=1778706917, hash=1681913927, cnt=256, object_type=SEQUENCE], UobjectGroupBy [idHash=246231872, hash=1764800190, cnt=519, object_type=TABLE PARTITION], UobjectGroupBy [idHash=1138665719, hash=1030673983, cnt=4, object_type=SCHEDULE], UobjectGroupBy [idHash=232948577, hash=1038362844, cnt=1, object_type=RULE], UobjectGroupBy [idHash=1080301817, hash=646054631, cnt=310, object_type=JAVA DATA], UobjectGroupBy [idHash=657724550, hash=1248576975, cnt=201, object_type=PROCEDURE], UobjectGroupBy [idHash=295410055, hash=33504659, cnt=54, object_type=OPERATOR], UobjectGroupBy [idHash=150727006, hash=499210168, cnt=2, object_type=DESTINATION], UobjectGroupBy [idHash=1865360077, hash=727903197, cnt=9, object_type=WINDOW], UobjectGroupBy [idHash=582342926, hash=1060308675, cnt=4, object_type=SCHEDULER GROUP], UobjectGroupBy [idHash=1968399647, hash=1205380883, cnt=1306, object_type=PACKAGE], UobjectGroupBy [idHash=1495061270, hash=1345537223, cnt=1245, object_type=PACKAGE BODY], UobjectGroupBy [idHash=1328790450, hash=1823695135, cnt=228, object_type=LIBRARY], UobjectGroupBy [idHash=1128429299, hash=1267824468, cnt=10, object_type=PROGRAM], UobjectGroupBy [idHash=760711193, hash=1240703242, cnt=17, object_type=RULE SET], UobjectGroupBy [idHash=317487814, hash=61657487, cnt=10, object_type=CONTEXT], UobjectGroupBy [idHash=1079028994, hash=1960895356, cnt=229, object_type=TYPE BODY], UobjectGroupBy [idHash=276147733, hash=873140579, cnt=44, object_type=XML SCHEMA], UobjectGroupBy [idHash=24378178, hash=1621363993, cnt=1014, object_type=JAVA RESOURCE], UobjectGroupBy [idHash=1891142624, hash=90282027, cnt=10, object_type=DIRECTORY], UobjectGroupBy [idHash=902107208, hash=1995006200, cnt=593, object_type=TRIGGER], UobjectGroupBy [idHash=142411235, hash=444983119, cnt=14, object_type=JOB CLASS], UobjectGroupBy [idHash=373966405, hash=1518992835, cnt=3494, object_type=INDEX], UobjectGroupBy [idHash=580466919, hash=1394644601, cnt=2422, object_type=TABLE], UobjectGroupBy [idHash=1061370796, hash=1861472837, cnt=37082, object_type=SYNONYM], UobjectGroupBy [idHash=1609659322, hash=1543110475, cnt=6487, object_type=VIEW], UobjectGroupBy [idHash=458063471, hash=1317758482, cnt=346, object_type=FUNCTION], UobjectGroupBy [idHash=1886921697, hash=424653540, cnt=7, object_type=INDEXTYPE], UobjectGroupBy [idHash=1455482905, hash=1776171634, cnt=30816, object_type=JAVA CLASS], UobjectGroupBy [idHash=49819096, hash=2110362533, cnt=2, object_type=JAVA SOURCE], UobjectGroupBy [idHash=1916179950, hash=1760023032, cnt=10, object_type=CLUSTER], UobjectGroupBy [idHash=1138808674, hash=215713426, cnt=2536, object_type=TYPE], UobjectGroupBy [idHash=305229607, hash=340664529, cnt=23, object_type=JOB], UobjectGroupBy [idHash=1365509716, hash=623631686, cnt=12, object_type=EVALUATION CONTEXT]]

    Leistungsbewertung:


    Obwohl unsere Tests kein Beispiel für eine korrekte Leistungsberechnung sind (wir haben weder den Verbindungspool verwendet noch die SQL-Abfragen optimiert), helfen sie dennoch bei der Berechnung des Leistungsgewinns mit der üblichen Formel:

    Leistungsgewinn = Reaktionszeit ohne Caching / Reaktionszeit mit Caching = 1589 / 6, die ungefähr 265-mal schneller ist oder Leistungsgewinn = ((Antwortzeit ohne Zwischenspeicherung - Antwortzeit mit Zwischenspeicherung) / Antwortzeit mit Zwischenspeicherung * 100) ist ungefähr 26.383% schneller.

    Somit können Sie mit dem Cache der 2. Ebene die Systemleistung im Vergleich zum Ansatz ohne Verwendung eines Caches um einhundert steigern.

    Jetzt auch beliebt: