[Lösung zur Schnittstellenoptimierung]

Vorwort

	在工作中大家会遇到接口响应慢的问题,导致线上用户在等待,现在总结出了18中接口方案的优化,供大家参考,如果有遗漏请大家也留言补充。

1. Batch-Einfügung oder Datenbankabfrage

Mit zunehmender Datenmenge steigt auch die Leistung von Datenbankabfragen. Daher müssen wir jede Abfrage oder die Anzahl der Einfügungen in die Datenbank optimieren, um Daten sicherzustellen.
Gegenbeispiel:

//直接遍历插入,数据量大,耗时
for(User user :list){
    
    
	insert(user);
}

Positives Beispiel

batchInsert(list);//批量插入,每次按照一定的数量进行插入

2. Asynchrones Denken ist ein zeitaufwändiger Vorgang. Erwägen Sie, es in asynchrones Denken umzuwandeln

Erwägen Sie bei zeitaufwändigen Vorgängen die Verwendung einer asynchronen Verarbeitung, die den Zeitverbrauch der Schnittstelle reduzieren kann.
Gegenbeispiel
Fügen Sie hier eine Bildbeschreibung ein

Positives Beispiel
Fügen Sie hier eine Bildbeschreibung ein
Für die asynchrone Implementierung können Sie einen Thread-Pool oder eine Nachrichtenwarteschlange verwenden.

3. Die Idee, Raum gegen Zeit zu tauschen: Cache angemessen nutzen.

In geeigneten Geschäftsszenarien kann die ordnungsgemäße Verwendung des Caches die Schnittstellenleistung erheblich verbessern. Beim Caching handelt es sich eigentlich um den Austausch von Raum gegen Zeit. Das heißt, Sie legen die Daten, die Sie überprüfen möchten, vorab im Cache ab und überprüfen den Cache bei Bedarf direkt, ohne die Datenbank oder die Berechnung überprüfen zu müssen Verfahren.
Der Cache umfasst hier: Redis-Cache, lokalen JVM-Cache, Memcached oder Map usw. ICH

4. Prefetching-Idee: Initialisieren Sie den Cache im Voraus

Die Idee des Vorabrufs ist leicht zu verstehen. Dabei werden die zu berechnenden und im Cache abzufragenden Daten im Voraus initialisiert. Wenn Sie zu einem späteren Zeitpunkt bestimmte Daten verwenden müssen, die komplexen Berechnungen unterzogen wurden, kann die Berechnung in Echtzeit viel Zeit in Anspruch nehmen. Zu diesem Zeitpunkt können wir die Idee des Vorabrufs übernehmen, die in Zukunft möglicherweise benötigten Daten im Voraus berechnen, in den Cache legen und sie dann bei Bedarf aus dem Cache abrufen. Dadurch wird die Schnittstellenleistung erheblich verbessert

5. Leihen Sie den Thread-Pool aus

Der Thread-Pool kann uns dabei helfen, Threads zu verwalten und einen erhöhten Ressourcenverbrauch beim Erstellen und Zerstören von Threads zu vermeiden.
Wenn Sie jedes Mal einen Thread erstellen, wenn Sie ihn verwenden müssen, dauert dies eine gewisse Zeit. Der Thread-Pool kann Threads wiederverwenden, um unnötigen Zeitaufwand zu vermeiden. Die Pooling-Technologie bezieht sich nicht nur auf Thread-Pools, sondern spiegelt in vielen Szenarien auch die Idee des Poolings wider. Ihr Kern besteht in der Vorzuweisung und dem Recycling.

6. Idee für einen Event-Callback: Weigern Sie sich, das Warten zu blockieren.

Wenn Sie eine Schnittstelle von System B aufrufen, diese jedoch Geschäftslogik verarbeitet, dauert dies 10 Sekunden oder länger. Blockieren Sie dann und warten Sie, bis die Downstream-Schnittstelle von System B zurückkehrt, bevor Sie mit Ihrem nächsten Vorgang fortfahren? Das ist offensichtlich unvernünftig.
Wir beziehen uns auf das IO-Multiplexing-Modell. Das heißt, wir müssen nicht blockieren und auf die Schnittstelle von System B warten, sondern müssen zuerst andere Vorgänge ausführen. Nachdem die Schnittstelle von System B verarbeitet wurde, wird die Ereignisrückrufbenachrichtigung verwendet. Unsere Schnittstelle kann die Benachrichtigung empfangen und dann den entsprechenden Geschäftsvorgang ausführen.

7. Vermeiden Sie eine zu grobe Sperrkörnigkeit

Bei hoher Parallelität ist eine Sperre erforderlich, um die Richtigkeit der Daten sicherzustellen.
Da die Effizienz des Sperrens definitiv geringer wird, ist der Umfang der Sperre sehr wichtig. Daher müssen wir sorgfältiger sperren, anstatt den gesamten Codeblock zu sperren.
Gegenbeispiel

Lock lock=new ReentrantLock();
lock.lock
//这里不管有没有数据安全问题都进行加锁
lock.unlock();

Gegenbeispiel

Lock lock=new ReentrantLock();
lock.lock
//只锁可能出现数据安全的地方
//这里如果是写出现的数据问题,就加写锁,如果为读出现的问题,就加读锁。
lock.unlock();

8. Speichermethode wechseln: Dateiübertragung und temporäre Datenspeicherung

Wenn die Datenmenge zu groß ist, ist die Ausführung der Datenbank extrem langsam. Zu diesem Zeitpunkt sollten Sie erwägen, sie zuerst lokal zu speichern und sie dann asynchron in die Datenbank zu schreiben.

9. Index

Wenn es um die Indexoptimierung geht, gehen wir im Allgemeinen von folgenden Aspekten aus:
Ist Ihr SQL indiziert?
Funktioniert Ihr Index wirklich?
Ist Ihre Indizierung ordnungsgemäß durchgeführt? (Hauptsächlich basierend auf der Größe der Daten, ob die aktuell indizierten Spalten häufig aktualisiert werden und ob zu viele aktuelle Indizes vorhanden sind)

10. SQL optimieren

1. Wählen Sie bestimmte Felder anstelle von „select *“ aus.
2. Verwenden Sie „Limit“ häufiger.
3. Versuchen Sie, „Union All“ anstelle von „Union“ zu verwenden. 4.
Optimieren Sie die Gruppe um
5. Optimieren Sie die Reihenfolge um
6. Kleine Tabellen führen zu großen Tabellen
. 7. Ist die Verwendung von Feldfeld Typen sinnvoll?
8. Optimieren Sie das Limit-Paging.
9. Sinnvolle Verwendung von exist&in.
10. Es sollten nicht zu viele Tabellen mit dem Join verknüpft sein. 11.
Die Unterabfrage delete+in verwendet nicht den Index.
12. Es sollten nicht zu viele Elemente in in vorhanden sein

11. Vermeiden Sie große Geschäftsprobleme

Um die Konsistenz der Datenbankdaten sicherzustellen, müssen wir häufig Transaktionen verwenden, wenn mehrere Datenbankänderungsvorgänge beteiligt sind.
Die Verwendung deklarativer Spring-Transaktionen ist sehr einfach. Sie müssen lediglich eine Annotation @Transactional als positives Beispiel verwenden

@Transactional
public int createUser(User user){
    
    
    //保存用户信息
    userDao.save(user);
    passCertDao.updateFlag(user.getPassId());
    return user.getUserId();
}

Gegenbeispiel

@Transactional
public int createUser(User user){
    
    
    //保存用户信息
    userDao.save(user);
    passCertDao.updateFlag(user.getPassId());
    sendEmailRpc(user.getEmail());
    return user.getUserId();
}

Diese Implementierung kann Fallstricke aufweisen. RPC-Remoteaufrufe sind in der Transaktion verschachtelt, dh einige Nicht-DB-Vorgänge sind in der Transaktion verschachtelt. Wenn diese Nicht-DB-Vorgänge lange dauern, können große Transaktionsprobleme auftreten.

Das sogenannte große Transaktionsproblem ist eine Transaktion, deren Ausführung lange dauert. Da Transaktionen nicht konsistent übermittelt werden, ist die Datenbankverbindung belegt. Das heißt, in einem gleichzeitigen Szenario ist der Datenbankverbindungspool voll, was sich auf andere Anforderungen zum Zugriff auf die Datenbank und auf die Leistung anderer Schnittstellen auswirkt.

Zu den Hauptproblemen, die durch große Transaktionen verursacht werden, gehören: Schnittstellen-Timeout, Deadlock, Master-Slave-Verzögerung usw. Um die Schnittstelle zu optimieren, müssen wir daher große Transaktionsprobleme vermeiden. Mit diesen Lösungen können wir große Transaktionen vermeiden:
Platzieren Sie keine RPC-Remote-Aufrufe innerhalb von Transaktionen
. Versuchen Sie, einige abfragebezogene Vorgänge außerhalb von Transaktionen zu platzieren.
Vermeiden Sie die Verarbeitung zu vieler Daten in Transaktionen.

12. Deep-Paging-Problem

Deep-Paging-Problem, warum ist es langsam? Werfen wir einen Blick auf diese SQL-
Anweisung „select id,name,balance from account where create_time> ‚2020-09-19‘ limit 100000,10;
limit 100000,10 bedeutet, dass 100010 Zeilen gescannt werden, die ersten 100000 Zeilen werden verworfen, und es werden 10 Zeilen zurückgegeben. Selbst wenn create_time verwendet wird, wird die Tabelle viele Male zurückgegeben.
Wir können Deep-Paging-Probleme durch Tag-Aufzeichnung und verzögerte Zuordnung optimieren.
Die Etikettenaufzeichnungsmethode
besteht darin, zu markieren, welches Element zuletzt abgefragt wurde. Wenn Sie das nächste Mal erneut nachsehen, beginnen Sie mit dem Scannen ab diesem Element. Es ist, als würde man ein Buch lesen. Man faltet es einfach zusammen oder setzt ein Lesezeichen an die Stelle, an der man es zuletzt gesehen hat. Wenn man es das nächste Mal liest, kann man es einfach wieder aufschlagen.
Unter der Annahme, dass der letzte Datensatz 100.000 erreicht hat, kann die SQL wie folgt geändert werden:
Wählen Sie ID, Name, Kontostand aus dem Konto aus, wobei die ID > 100.000 auf 10 begrenzt ist.
In diesem Fall ist die Leistung unabhängig davon, wie viele Seiten später umgeblättert werden, gut, weil Der ID-Primärschlüsselindex wird getroffen. Diese Methode weist jedoch Einschränkungen auf: Sie erfordert ein Feld, das der kontinuierlichen automatischen Inkrementierung ähnelt.

Die verzögerte Assoziationsmethode besteht darin, die Bedingungen an den Primärschlüssel-Indexbaum zu übertragen und dann die Anzahl zurück in die Tabelle zu reduzieren. Das optimierte SQL lautet wie folgt:
select acct1.id,acct1.name,acct1.balance FROM account acct1 INNER JOIN (SELECT a.id FROM account a WHERE a.create_time > '2020-09-19' limit 100000, 10) AS acct2 auf acct1.id = acct2.id;
Die Optimierungsidee besteht darin, zuerst die Primärschlüssel-ID, die die Bedingungen erfüllt, über den sekundären Indexbaum idx_create_time abzufragen und sie dann über die Primärschlüssel-ID mit der Originaltabelle zu verbinden, sodass die primäre Der Schlüsselindex wird später direkt verwendet und auch reduziert. An die Tabelle zurückgegeben.

13. Optimieren Sie die Programmstruktur

Vermeiden Sie die Erstellung unnötiger Objekte, vermeiden Sie unnötige Daten aus Datenbankabfragen usw.

14. Übertragungsinhalt komprimieren

Durch die Komprimierung des Übertragungsinhalts werden die Übertragungsnachrichten kleiner, sodass die Übertragung schneller erfolgt. Bei einer Bandbreite von 10 MB ist die Übertragung von 10.000 Nachrichten im Allgemeinen schneller als die Übertragung von 1 Million Nachrichten.

15. Das Thread-Pool-Design muss angemessen sein

Wir verwenden Thread-Pools, um Aufgaben parallel zu verarbeiten und Aufgaben effizienter abzuschließen. Aber manchmal, wenn das Thread-Pool-Design nicht sinnvoll ist, ist die Effizienz der Schnittstellenausführung nicht ideal.
Im Allgemeinen müssen wir auf diese Parameter des Thread-Pools achten: Kern-Threads, maximale Anzahl von Threads und Blockierungswarteschlange.
Bei einem zu kleinen Kerngewinde wird keine gute Parallelität erreicht.
Wenn die Blockierungswarteschlange unangemessen ist, stellt dies nicht nur ein Blockierungsproblem dar, sondern kann sogar OOM verursachen.
Wenn der Thread-Pool nicht zwischen Geschäftsisolation unterscheidet, kann das Kerngeschäft durch das Edge-Geschäft beeinträchtigt werden.

16. Maschinenprobleme (fullGC, Threads sind voll, zu viele E/A-Ressourcen sind nicht geschlossen usw.)

Manchmal ist unsere Schnittstelle aufgrund von maschinellen Verarbeitungsproblemen langsam. Dazu gehören hauptsächlich FullGC, Threads sind voll, zu viele E/A-Ressourcen sind nicht geschlossen usw.
Wir haben zuvor ein FullGC-Problem untersucht: Als die Operationsdame mehr als 600.000 Excel exportierte, sagte sie, es stecke fest, und dann erhielten wir einen Überwachungsalarm. Eine spätere Untersuchung ergab, dass unser alter Code von Apache POI in Excel generiert wurde. Beim Exportieren einer großen Menge an Excel-Daten war der JVM-Speicher zu diesem Zeitpunkt knapp und führte direkt zu Full GC.
Wenn die Threads voll sind, wartet auch die Schnittstelle. Also. Wenn es sich um ein Szenario mit hoher Parallelität handelt, müssen wir auf die aktuelle Begrenzung zugreifen und redundante Anforderungen ablehnen.
Wenn die E/A-Ressourcen nicht geschlossen sind, erhöht sich auch der Zeitverbrauch. Sie können einen Blick darauf werfen. Wenn auf Ihrem Computer ständig viele Dateien geöffnet sind, haben Sie dann normalerweise das Gefühl, festzustecken?
Artikelreferenz GZH: Der Junge beim Schneckensammeln

おすすめ

転載: blog.csdn.net/weixin_47068446/article/details/132461145