2017-05-16 3 views
0

Ich machte einen Parser basierend auf Jsoup. Dieser Parser behandelt eine Seite mit Paginierung. Diese Seite enthält beispielsweise 100 zu analysierende Links. Ich habe eine Hauptschleife erstellt, die die Seitennummerierung umgeht. Und ich muss asynchrone Tasks ausführen, um jedes der 100 Elemente auf jeder Seite zu analysieren. Wie ich es verstehe, unterstützt Jsoup keine Async-Anfragen. Nachdem ich jedes Element bearbeitet habe, muss ich es in der DB speichern. Ich möchte Fehler beim Einfügen in DB-Tabelle vermeiden (wenn Threads die gleiche ID für verschiedene Elemente zur gleichen Zeit verwenden, wenn es möglich ist). Was können Sie vorschlagen? kann ich einfach Thread-Instanz jedes Element zu analysieren:Gleichzeitige Einfügen in DB

public class ItemParser extends Thread { 
    private String url; 
    private MySpringDataJpaRepository repo; 

    public ItemParser(String url, MySpringDataJpaRepository repoReference) { 
     this.url = url; 
     this.repo = repoReference; 
    } 

    @Override 
    public void run() { 
     final MyItem item = jsoupParseItem(); 
     repo.save(item); 
    } 
} 

Und wie laufen:

public class Parser { 

    @Autowired 
    private MySpringDataJpaRepository repoReference; // <-- SINGLETON 

    public static void main(String[] args) { 
     int pages = 10000; 
     for (int i = 0; i < pages; i++) { 
      Document currentPage = Jsoup.parse(); 
      List<String> links = currentPage.extractLinks(); // contains 100 links to be parsed on each for-loop iteration 
      links.forEach(link -> new ItemParser(link, repoReference).start()); 
     } 
    } 
} 

Ich weiß, dass dieser Code nicht übersetzbar ist, ich möchte nur meine Idee zeigen.

Oder vielleicht ist es besser Spring Batch zu benutzen? Was ist die beste Vorgehensweise, um dies zu lösen? Was denkst du?

+0

Sie können Transaktion verwenden, um Fehler beim Einfügen und Einfügen zu vermeiden, wird wirklich schnell, wenn Sie Transaktion verwenden. –

+0

@utsavanand und welche Art von Isolationsstufe sollte ich verwenden? –

Antwort

2

Wenn Sie Zeilensperre verwenden, sollte in Ordnung sein. Es kann zu Problemen führen, wenn jede Einfügung eine Transaktion ist, aber dies hat Auswirkungen auf den gesamten Begriff einer Transaktion als eine Arbeitseinheit (d. H., Wenn eine einzelne Einfügung fehlschlägt, soll die gesamte Ausführung fehlschlagen und zurückgesetzt werden?).

Auch wenn Sie UUIDs oder db-generierte IDs verwenden, haben Sie keine Kollisionsprobleme.

Um den Code zu strukturieren, würde ich Runnables für jede Aufgabe und einen Thread-Pool-Executor verwenden. Zu viele Threads und das System verliert an Effizienz, wenn versucht wird, alle zu verwalten. Ich merke, dass Sie Feder verwenden, also sehen Sie sich https://docs.spring.io/spring/docs/current/spring-framework-reference/html/scheduling.html

+0

Also, es ist möglich, Daten-JPA-Repository zu verwenden, um DB zu speichern (aber bevor ich diesen Repo einrichten sollte, um Sperren auf Zeilenebene zu verwenden)? –

+0

Um klar zu sein, ist das Sperren auf Zeilenebene ein SQL-DB-Konzept. Es gibt Analoga in anderen Speichertechnologien, aber für sql dbs ist es etwas, das Sie in der Datenbank konfigurieren. ZB mysql: https://dev.mysql.com/doc/refman/5.7/en/internal-locking.html – Taylor