Heim  >  Artikel  >  15 echte Shopee-Server-Interviewfragen, können Sie sie alle richtig beantworten? (mit Analyse)

15 echte Shopee-Server-Interviewfragen, können Sie sie alle richtig beantworten? (mit Analyse)

青灯夜游
青灯夜游nach vorne
2022-02-21 11:40:264587Durchsuche

Lesen Sie vor dem Vorstellungsgespräch mehr über die Interviewmaterialien des Unternehmens, die für spätere Vorstellungsgespräche sehr hilfreich sein werden. Heute werde ich Ihnen 15 echte Shopee-Server-Interviewfragen mitteilen (mit Antwortanalyse). Ich hoffe, es kann Ihnen helfen.

1. Sortieren Sie die verknüpfte Liste

Wenn Sie den Kopfknoten der verknüpften Liste haben, sortieren Sie ihn bitte in aufsteigender Reihenfolge und geben Sie die sortierte verknüpfte Liste zurück.

15 echte Shopee-Server-Interviewfragen, können Sie sie alle richtig beantworten? (mit Analyse)

Beispiel 1:

输入:head = [4,2,1,3]
输出:[1,2,3,4]

15 echte Shopee-Server-Interviewfragen, können Sie sie alle richtig beantworten? (mit Analyse)

Beispiel 2:

输入:head = [-1,5,3,4,0]
输出:[-1,0,3,4,5]

Dieses Problem kann mit Doppelzeigern + Zusammenführungssortierungsalgorithmus gelöst werden. Die wichtigsten vier Schritte sind wie folgt: 1. Schnelle und langsame Zeigermethode, Durchlaufen Sie die verknüpfte Liste, um den mittleren Knoten zu finden

 2. Schneiden Sie die verknüpfte Liste am mittleren Knoten ab

3. Ordnen Sie die linken und rechten unterverknüpften Listen mithilfe der Zusammenführungssortierung an

 4. Führen Sie die unterverknüpften Listen zusammen

Der vollständige Code lautet wie folgt:

class Solution {
    public ListNode sortList(ListNode head) {
        //如果链表为空,或者只有一个节点,直接返回即可,不用排序
        if (head == null || head.next == null)
            return head;
        
        //快慢指针移动,以寻找到中间节点
        ListNode slow = head;
        ListNode fast = head;
        while(fast.next!=null && fast.next.next !=null){
          fast = fast.next.next;
          slow = slow.next;
        }
        //找到中间节点,slow节点的next指针,指向mid
        ListNode mid = slow.next;
        //切断链表
        slow.next = null;
        
        //排序左子链表
        ListNode left = sortList(head);
        //排序左子链表
        ListNode right = sortList(mid);
        
        //合并链表
        return merge(left,right);
    }
    
    public ListNode merge(ListNode left, ListNode right) {
       ListNode head = new ListNode(0);
       ListNode temp = head;
       while (left != null && right != null) {
           if (left.val <= right.val) {
                temp.next = left;
                left = left.next;
            } else {
                temp.next = right;
                right = right.next;
            }
            temp = temp.next;
        }
        if (left != null) {
            temp.next = left;
        } else if (right != null) {
            temp.next = right;
        }
        return head.next;
    }
}

2. Der Unterschied zwischen symmetrischen und asymmetrischen Verschlüsselungsalgorithmen

Erste Review-bezogene Konzepte:

    Klartext: bezieht sich auf Informationen/Daten, die nicht verschlüsselt wurden.
  • Chiffretext: Nachdem der Klartext durch den Verschlüsselungsalgorithmus verschlüsselt wurde, wird er zum Chiffretext, um die Datensicherheit zu gewährleisten.
  • Schlüssel: ist ein Parameter, der in den Algorithmus eingegeben wird, der Klartext in Chiffretext oder Chiffretext in Klartext umwandelt. Schlüssel werden in symmetrische Schlüssel und asymmetrische Schlüssel unterteilt.
  • Verschlüsselung: Der Prozess der Umwandlung von Klartext in Chiffretext.
  • Entschlüsselung: Der Prozess der Reduzierung von Chiffretext in Klartext.
  • Symmetrischer Verschlüsselungsalgorithmus: Ein Verschlüsselungsalgorithmus, der
den gleichen Schlüssel

für die Verschlüsselung und Entschlüsselung verwendet. Zu den gängigen symmetrischen Verschlüsselungsalgorithmen gehören AES, 3DES, DES, RC5, RC6 usw.

15 echte Shopee-Server-Interviewfragen, können Sie sie alle richtig beantworten? (mit Analyse)

Asymmetrischer Verschlüsselungsalgorithmus

: Der asymmetrische Verschlüsselungsalgorithmus erfordert zwei Schlüssel (öffentlicher Schlüssel und privater Schlüssel). Öffentliche Schlüssel und private Schlüssel existieren paarweise. Wenn der öffentliche Schlüssel zum Verschlüsseln von Daten verwendet wird, kann nur der entsprechende private Schlüssel diese entschlüsseln. Die wichtigsten asymmetrischen Verschlüsselungsalgorithmen sind: RSA, Elgamal, DSA, D-H, ECC.

15 echte Shopee-Server-Interviewfragen, können Sie sie alle richtig beantworten? (mit Analyse)

3. Wie TCP Zuverlässigkeit gewährleistet

    Zuallererst basiert die TCP-Verbindung auf einem Drei-Wege-Handshake, während die Trennung auf vier Wellen basiert. Sorgen Sie für eine zuverlässige Verbindung und Trennung.
  • Zweitens spiegelt sich die Zuverlässigkeit von TCP auch in seiner Zustandsbezogenheit wider; TCP zeichnet auf, welche Daten gesendet, welche Daten akzeptiert und welche nicht akzeptiert werden, und stellt sicher, dass die Datenpakete in der richtigen Reihenfolge ankommen, wodurch sichergestellt wird, dass die Datenübertragung erfolgt nicht schiefgehen.
  • Wieder einmal spiegelt sich die Zuverlässigkeit von TCP auch in seiner Steuerbarkeit wider. Es verfügt über Mechanismen wie Nachrichtenüberprüfung, ACK-Antwort, erneute Übertragung bei Zeitüberschreitung (Sender), erneute Übertragung von Daten außerhalb der Reihenfolge (Empfänger), Verwerfen doppelter Daten, Flusskontrolle (gleitendes Fenster) und Überlastungskontrolle. 4. Lassen Sie uns über die fünf E/A-Modelle sprechen Es hat blockiert und gewartet, bis die Kerneldaten bereit sind und vom Kernel in den Benutzerbereich kopiert wurden, bevor eine Erfolgsmeldung zurückgegeben wird. Dieser E/A-Vorgang wird als blockierende E/A bezeichnet.

4.2 Nicht blockierendes IO-Modell

Wenn die Kerneldaten noch nicht bereit sind, können Sie zunächst eine Fehlermeldung an den Benutzerprozess zurücksenden, sodass dieser nicht warten muss, sondern erneut anfordert durch Umfragen. Dies ist ein nicht blockierendes IO. Das Flussdiagramm sieht wie folgt aus:

4.3 IO-Multiplexing-Modell15 echte Shopee-Server-Interviewfragen, können Sie sie alle richtig beantworten? (mit Analyse)

Auswahl des IO-Multiplexings

Der Anwendungsprozess kann mehrere Geräte gleichzeitig durch Aufrufen überwachen Die Auswahlfunktion fd, in der von der Auswahlfunktion überwachten FD, solange ein Datenstatus bereit ist, kehrt die Auswahlfunktion in den lesbaren Status zurück, und dann initiiert der Anwendungsprozess eine Recvfrom-Anforderung zum Lesen der Daten.

15 echte Shopee-Server-Interviewfragen, können Sie sie alle richtig beantworten? (mit Analyse)

select hat mehrere Nachteile:

Die maximale Anzahl von Verbindungen ist begrenzt, im Allgemeinen 1024 auf Linux-Systemen.

Nachdem die Auswahlfunktion zurückgekehrt ist, durchläuft sie den fdset, um den fertigen Deskriptor fd zu finden.

IO-Multiplexing-Epoll15 echte Shopee-Server-Interviewfragen, können Sie sie alle richtig beantworten? (mit Analyse)

Um die Probleme von Select zu lösen, wurde das Multiplexing-Modell Epoll geboren. Es wird wie folgt implementiert:

  • epoll registriert zunächst einen fd (Dateideskriptor) über epoll_ctl(). Sobald ein bestimmter fd bereit ist, aktiviert der Kernel den fd schnell, wenn er epoll_wait() aufruft. Der knifflige Vorgang des Durchlaufens von Dateideskriptoren wird hier entfernt und ein Mechanismus zum Abhören von Ereignisrückrufen wird verwendet. Dies ist das Highlight von Epoll.

    4.4 Signalgesteuertes Modell des IO-Modells

    Signalgesteuertes IO verwendet keine aktive Abfrage mehr, um zu bestätigen, ob die Daten bereit sind, sondern sendet ein Signal an den Kernel (erstellt beim Aufruf von Sigaction ein SIGIO-Signal). Der Anwendungsbenutzerprozess kann dann andere Dinge tun, ohne ihn zu blockieren. Wenn die Kerneldaten bereit sind, wird der Anwendungsprozess über das SIGIO-Signal benachrichtigt, dass die Daten zur Lesbarkeit bereit sind. Nachdem der Anwendungsbenutzerprozess das Signal empfängt, ruft er sofort recvfrom auf, um die Daten zu lesen. 4.5 IO-Modell asynchrones IO (AIO) „Sofort“ ist nicht das Verarbeitungsergebnis, sondern bedeutet, dass die Übermittlung erfolgreich war. Wenn die Kerneldaten bereit sind, kopieren Sie die Daten in den Benutzerprozesspuffer und senden Sie ein Signal, um den Benutzerprozess darüber zu informieren, dass der E/A-Vorgang abgeschlossen ist.

    Der Prozess ist wie folgt:15 echte Shopee-Server-Interviewfragen, können Sie sie alle richtig beantworten? (mit Analyse)

    5. Hystrix-Arbeitsprinzip:

    1. Build-Befehl

    Hystrix stellt zwei Befehlsobjekte bereit: HystrixCommand und HystrixObserv fähiger Befehl , wird es im Namen einer Ihrer Abhängigkeitsanforderungsaufgaben die zum Anfordern von Abhängigkeiten erforderlichen Parameter an den Konstruktor übergeben.

    15 echte Shopee-Server-Interviewfragen, können Sie sie alle richtig beantworten? (mit Analyse)2. Befehle ausführen

    Es gibt vier Möglichkeiten, Hystrix-Befehle auszuführen. Dies sind:

    Rexecute(): synchrone Blockierungsausführung, Empfang einer einzelnen Antwort von der abhängigen Anforderung.

    115 echte Shopee-Server-Interviewfragen, können Sie sie alle richtig beantworten? (mit Analyse)

    Future queue(): Asynchrone Ausführung, gibt ein Future-Objekt zurück, das eine einzelne Antwort enthält.

    Observable observable(): Nach dem Erstellen eines Observables abonniert es das Observable und gibt das Observable-Objekt zurück, das die Antwort der abhängigen Anfrage darstellt.

    Observable toObservable(): Observable kalt stellen, ein Observable zurückgeben und Der Hystrix-Befehl wird nur beim Abonnieren ausgeführt. Es können mehrere Ergebnisse zurückgegeben werden bevor die Aufgabe ausgeführt wird. Wenn dies der Fall ist, wird das Observable, das die zwischengespeicherte Antwort enthält, direkt zurückgegeben. Wenn kein zwischengespeichertes Ergebnis vorhanden ist, die Zwischenspeicherung jedoch aktiviert ist, wird das Ausführungsergebnis für die spätere Verwendung zwischengespeichert.
    • 4. Überprüfen Sie, ob der Leistungsschalter (Leistungsschalter) geöffnet ist. Eine Sicherung brennt aus, um den Stromkreis zu schützen, wenn eine Gefahr auftritt, während ein Leistungsschalter einen Kurzschluss auslösen kann Es erreicht den von uns festgelegten Schwellenwert (z. B. Die Anforderungsfehlerrate erreicht 50 %) und weigert sich, eine Anforderung auszuführen.

      Wenn der Looper geöffnet ist, führt Hystrix den Befehl nicht aus und wechselt direkt in die Fallback-Verarbeitungslogik.
    • 5. Überprüfen Sie den Thread-Pool-/Semaphor-/Warteschlangenstatus. Zu den Hystrix-Isolationsmethoden gehören die Thread-Pool-Isolation und die Semaphor-Isolation. Bei Verwendung des Hystrix-Thread-Pools weist Hystrix standardmäßig jedem abhängigen Dienst 10 Threads zu. Wenn alle 10 Threads ausgelastet sind, wird die Ausführung des Befehls abgelehnt und stattdessen sofort zur Ausführung der Fallback-Logik übergegangen.

      6. Verwenden Sie HystrixObservableCommand.construct() oder HystrixCommand.run(), um die eigentlichen Aufgaben des Benutzers auszuführen.
    • 7. Berechnen Sie den Zustand der Schleife. Jedes Mal, wenn die Ausführung eines Befehls beginnt oder eine Ausnahme auftritt, wird der Ausführungsstatus aufgezeichnet, z. B.: Erfolg, Fehler, Ablehnung, Zeitüberschreitung und andere Indikatoren Die Daten werden regelmäßig verarbeitet und dann basierend auf den festgelegten Bedingungen bestimmt, ob der Looper geöffnet werden soll.

      8. Führen Sie die Fallback-Logik aus, wenn der Befehl fehlschlägt. In der obigen Abbildung werden Schaltkreisunterbrechung, Thread-Pool-Ablehnung, Semaphor-Ablehnung, Ausführungsausführung und Ausführungszeitüberschreitung alle in die Fallback-Verarbeitung einbezogen.
    • 9. Das ursprüngliche Objektergebnis wird in Form von Observable zurückgegeben. Bevor es an den Benutzer zurückgegeben wird, erfolgt je nach aufrufender Methode eine gewisse Verarbeitung.

    • 6. Verzögerungsszenarioverarbeitung

    In der täglichen Entwicklung stoßen wir häufig auf diese Art von Geschäftsszenario, wie zum Beispiel: Wenn eine Bestellung zum Mitnehmen länger als 30 Minuten nicht bezahlt wird, wird die Bestellung 15 Minuten später automatisch storniert Wenn sich der Benutzer erfolgreich registriert, wird eine Textnachricht gesendet. Benutzer benachrichtigen und mehr. Dies ist das Szenario mit verzögerter Aufgabenverarbeitung. Wir haben hauptsächlich die folgenden Lösungen für solche Szenarien:

    JDKs DelayQueue-Verzögerungswarteschlange

    Zeitradalgorithmus

    Datenbank-geplante Aufgaben (z. B. Quartz)

    Redis ZSet-Implementierung

    MQ-Verzögerung Warteschlangenimplementierung

7.https-Anfrageprozess

  • HTTPS = HTTP + SSL/TLS, d. h. SSL/TLS zum Verschlüsseln und Entschlüsseln der Daten und HTTP für die Übertragung verwenden.

  • SSL oder Secure Sockets Layer ist ein Sicherheitsprotokoll, das Sicherheit und Datenintegrität für die Netzwerkkommunikation bietet.

  • TLS, Transport Layer Security (Secure Transport Layer Protocol), ist die Nachfolgeversion von SSL 3.0.

115 echte Shopee-Server-Interviewfragen, können Sie sie alle richtig beantworten? (mit Analyse)
http-Anfrageprozess

1 Der Benutzer gibt eine https-URL in den Browser ein und stellt dann eine Verbindung zum 443-Port des Servers her.

2. Der Server muss über einen Satz digitaler Zertifikate verfügen. Sie können diese selbst erstellen oder bei der Organisation beantragen. Der Unterschied besteht darin, dass das von Ihnen ausgestellte Zertifikat vom Kunden überprüft werden muss. Bei diesem Zertifikatssatz handelt es sich eigentlich um ein Paar öffentlicher und privater Schlüssel.

3. Der Server sendet sein eigenes digitales Zertifikat (mit öffentlichem Schlüssel) an den Client.

4. Nachdem der Client das digitale Zertifikat vom Server erhalten hat, wird es überprüft. Wenn dies fehlschlägt, wird ein Warnfeld angezeigt. Wenn das Zertifikat in Ordnung ist, wird ein Schlüssel generiert (symmetrische Verschlüsselung) und mit dem öffentlichen Schlüssel des Zertifikats verschlüsselt.

5. Der Client initiiert die zweite HTTP-Anfrage in HTTPS und sendet den verschlüsselten Client-Schlüssel an den Server.

6. Nachdem der Server den Chiffretext vom Client erhalten hat, verwendet er seinen eigenen privaten Schlüssel, um ihn asymmetrisch zu entschlüsseln, und verwendet dann den Client-Schlüssel, um die zurückgegebenen Daten symmetrisch zu verschlüsseln Auf diese Weise werden die Daten zu Chiffretext.

7. Der Server gibt den verschlüsselten Chiffretext an den Client zurück.

8. Der Client empfängt den vom Server zurückgegebenen Chiffretext, verwendet seinen eigenen Schlüssel (Client-Schlüssel), um ihn symmetrisch zu entschlüsseln, und erhält die vom Server zurückgegebenen Daten.

8. Lassen Sie uns über die Transaktionsisolationsstufe und das Implementierungsprinzip des wiederholbaren Lesens sprechen. 8.1 Die vier Isolationsstufen der Datenbank Lesen, Phantomlesen usw., die in gleichzeitigen Transaktionen vorhanden sind. Frage: Der Datenbankonkel hat vier Isolationsstufen entworfen. Sie sind „nicht festgeschrieben lesen“, „festgeschrieben lesen“, „wiederholbar lesen“ und „serialisierbar“.

Nicht festgeschriebene Isolationsstufe lesen: Es ist nur eingeschränkt, dass zwei Daten nicht gleichzeitig geändert werden können. Wenn die Transaktion jedoch nicht übermittelt wird, können sie von anderen Transaktionen gelesen werden Transaktionsisolation ist schmutzig. Probleme beim Lesen, beim wiederholten Lesen und beim Phantomlesen Es gibt immer noch Probleme mit wiederholtem Lesen und Phantomlesen.

Wiederholbares Lesen: Es schränkt die Änderung beim Lesen von Daten ein, sodass das Problem des wiederholten Lesens gelöst wird. Beim Lesen von Bereichsdaten können jedoch Daten eingefügt werden Es wird auch Phantomlesen geben Probleme;

Serialisierung: die höchste Isolationsstufe für Transaktionen. Auf dieser Stufe werden alle Transaktionen seriell und sequentiell ausgeführt. Es kann alle Parallelitätsprobleme von Dirty Reads, nicht wiederholbaren Lesevorgängen und Phantom Reads vermeiden. Unter dieser Transaktionsisolationsstufe ist die Transaktionsausführung jedoch sehr leistungsintensiv.

  • Was sind die Parallelitätsprobleme zwischen den vier Isolationsstufen?
    Isolationsstufe Dirty Read Non-repeatable Read Phantom Read
    Read Uncommitted
    lesen Senden ×
    Wiederholbares Lesen × ×
    Serialisierung × × ×
    8.2 Sichtbarkeitsregeln für Leseansichten eine Liste.

    max_limit_id

    gibt den ID-Wert an, der der nächsten Transaktion im System zugewiesen werden soll, wenn eine Leseansicht generiert wird. creator_trx_id

    Die Sichtbarkeitsregeln der Leseansicht lauten wie folgt:

    • Wenn die Datentransaktions-ID trx_id ist, bedeutet dies, dass die Transaktion, die diese Version generiert hat, vor der Generierung von <code>Read übermittelt wurde Ansicht (Da die Transaktions-ID inkrementiert wird), kann die aktuelle Transaktion auf diese Version zugreifen. trx_id ,表明生成该版本的事务在生成<code>Read View前,已经提交(因为事务ID是递增的),所以该版本可以被当前事务访问。

    • 如果trx_id>= max_limit_id,表明生成该版本的事务在生成Read View后才生成,所以该版本不可以被当前事务访问。

    • 如果 min_limit_id =<trx_id max_limit_id>,需要分3种情况讨论</trx_id>

    1)如果m_ids包含trx_id,则代表Read View生成时刻,这个事务还未提交,但是如果数据的trx_id等于creator_trx_id的话,表明数据是自己生成的,因此是可见的。

    2)如果m_ids包含trx_id,并且trx_id不等于creator_trx_id,则Read View生成时,事务未提交,并且不是自己生产的,所以当前事务也是看不见的;

    3)如果m_ids不包含trx_id,则说明你这个事务在Read View生成之前就已经提交了,修改的结果,当前事务是能看见的。

    8.3 可重复读实现原理

    数据库是通过加锁实现隔离级别的,比如,你想一个人静静,不被别人打扰,你可以把自己关在房子,并在房门上加上一把锁!串行化隔离级别就是加锁实现的。但是如果频繁加锁,性能会下降。因此设计数据库的大叔想到了MVCC

    可重复读的实现原理就是MVCC多版本并发控制。在一个事务范围内,两个相同的查询,读取同一条记录,却返回了不同的数据,这就是不可重复读。可重复读隔离级别,就是为了解决不可重复读问题。

    查询一条记录,基于MVCC,是怎样的流程呢?

    • 获取事务自己的版本号,即事务ID

    • 获取Read View

    • 查询得到的数据,然后Read View中的事务版本号进行比较。

    • 如果不符合Read View的可见性规则, 即就需要Undo log中历史快照;

    • 最后返回符合规则的数据

    InnoDB 实现MVCC,是通过Read View+ Undo Log实现的,Undo Log保存了历史快照,Read View可见性规则帮助判断当前版本的数据是否可见。

    可重复读(RR)隔离级别,是如何解决不可重复读问题的?

    假设存在事务A和B,SQL执行流程如下

    115 echte Shopee-Server-Interviewfragen, können Sie sie alle richtig beantworten? (mit Analyse)

    在可重复读(RR)隔离级别下,一个事务里只会获取一次read view

    Wenn trx_id>= max_limit_id, bedeutet dies, dass die Transaktion, die diese Version generiert hat, nach der Generierung von Read View generiert wurde, sodass auf diese Version nicht zugegriffen werden kann die aktuelle Transaktion.

    115 echte Shopee-Server-Interviewfragen, können Sie sie alle richtig beantworten? (mit Analyse)Wenn min_limit_id =<trx_id max_limit_id>, muss es in drei Situationen besprochen werden</trx_id>

    1) Wenn m_idsenthält <code>trx_id, der den Zeitpunkt darstellt, zu dem Read View generiert wird. Diese Transaktion wurde noch nicht übermittelt, aber wenn der trx_id der Daten ist gleich creator_trx_id gibt an, dass die Daten von sich selbst generiert werden und daher sichtbar sind.

    2) Wenn m_ids trx_id enthält und trx_id nicht gleich creator_trx_id ist, dann Read Ansicht generiert wird, wird die Transaktion nicht übermittelt und nicht von selbst erstellt, daher ist die aktuelle Transaktion unsichtbar

    3) Wenn m_ids nicht trx_id enthält; code>, dann bedeutet dies, dass Ihre Transaktion übermittelt wurde, bevor <code>Read View generiert wurde, und das Ergebnis der Änderung in der aktuellen Transaktion sichtbar ist.

    8.3 Prinzip der wiederholbaren Leseimplementierung

    🎜Die Datenbank erreicht Isolationsstufen durch Sperren, zum Beispiel wenn Sie Wenn Sie allein sein und nicht von anderen gestört werden möchten, können Sie sich im Haus einschließen und ein Schloss an der Tür anbringen! Die Serialisierungsisolationsstufe wird durch Sperren implementiert. Wenn Sie jedoch häufig sperren, nimmt die Leistung ab. Also dachte der Onkel, der die Datenbank entworfen hat, an MVCC. 🎜🎜Das Implementierungsprinzip des wiederholbaren Lesens ist MVCC-Parallelitätskontrolle für mehrere Versionen. Im Rahmen einer Transaktion lesen zwei identische Abfragen denselben Datensatz, geben jedoch unterschiedliche Daten zurück. Dies ist ein nicht wiederholbarer Lesevorgang. Die Isolationsstufe für wiederholbare Lesevorgänge soll das Problem des nicht wiederholbaren Lesevorgangs lösen. 🎜🎜Wie erfolgt die Abfrage eines Datensatzes basierend auf MVCC? 🎜🎜🎜🎜Rufen Sie die Versionsnummer der Transaktion ab, also die Transaktions-ID🎜🎜🎜Rufen Sie die aus der Leseansicht🎜🎜🎜-Abfrage erhaltenen Daten ab und vergleichen Sie dann die Transaktionsversionsnummern die Leseansicht. 🎜🎜🎜Wenn die Sichtbarkeitsregeln der Leseansicht nicht erfüllt sind, ist der historische Schnappschuss im Rückgängig-Protokoll erforderlich;🎜🎜🎜Endlich die Daten zurückgeben, die den Regeln entsprechen🎜🎜InnoDB MVCC wird durch Read View+ Undo Log implementiert, speichert historische Snapshots und ist für Read Viewsichtbar > Sexuelle Regeln helfen dabei, festzustellen, ob die aktuelle Version der Daten sichtbar ist. 🎜🎜Wie löst die Isolationsstufe „Repeatable Read“ (RR) das Problem des nicht wiederholbaren Lesens? 🎜🎜Angenommen, es gibt Transaktionen A und B, der SQL-Ausführungsprozess ist wie folgt🎜🎜115 echte Shopee-Server-Interviewfragen, können Sie sie alle richtig beantworten? (mit Analyse)🎜🎜Unter der Isolationsstufe „Repeatable Read“ (RR) wird eine Leseansicht nur einmal in einer Transaktion abgerufen, die von geteilt wird Replikate, wodurch sichergestellt wird, dass alle abgefragten Daten gleich sind. 🎜🎜Angenommen, es gibt derzeit eine core_user-Tabelle und fügen Sie Initialisierungsdaten wie folgt ein: 🎜🎜🎜🎜🎜Basierend auf MVCC werfen wir einen Blick auf den Ausführungsprozess 🎜🎜1 A startet eine Transaktion und erhält zunächst eine Transaktions-ID von 100 🎜🎜2. B Öffnen Sie die Transaktion und erhalten Sie die Transaktions-ID als 101🎜🎜3. Der entsprechende Wert der Leseansicht lautet wie folgt:
    min_limit_id stellt die kleinste Transaktions-ID unter den aktiven Lese- und Schreibtransaktionen im aktuellen System beim Generieren der Leseansicht dar, also den kleinsten Wert in m_ids.
    Erstellen Sie die Transaktions-ID der aktuellen Leseansicht
    m_idsmax_limit_idmin _limit_id creator_trx_id

    然后回到版本链:开始从版本链中挑选可见的记录:

    115 echte Shopee-Server-Interviewfragen, können Sie sie alle richtig beantworten? (mit Analyse)

    由图可以看出,最新版本的列name的内容是孙权,该版本的trx_id值为100。开始执行read view可见性规则校验:

    min_limit_id(100)=<trx_id(100)<102;
    creator_trx_id = trx_id =100;

    由此可得,trx_id=100的这个记录,当前事务是可见的。所以查到是name为孙权的记录。

    4、事务B进行修改操作,把名字改为曹操。把原数据拷贝到undo log,然后对数据进行修改,标记事务ID和上一个数据版本在undo log的地址。

    115 echte Shopee-Server-Interviewfragen, können Sie sie alle richtig beantworten? (mit Analyse)

    5、事务B提交事务

    6、事务A再次执行查询操作,因为是RR(可重复读)隔离级别,因此会复用老的Read View副本,Read View对应的值如下

    Variabler Wert
    100, 101
    102
    100
    100
    m_idsmax_limit_idmin _limit_id creator_trx_id

    然后再次回到版本链:从版本链中挑选可见的记录:

    115 echte Shopee-Server-Interviewfragen, können Sie sie alle richtig beantworten? (mit Analyse)

    从图可得,最新版本的列name的内容是曹操,该版本的trx_id值为101。开始执行read view可见性规则校验:

    min_limit_id(100)=<trx_id(101)<max_limit_id(102);
    
    因为m_ids{100,101}包含trx_id(101),
    并且creator_trx_id (100) 不等于trx_id(101)

    所以,trx_id=101这个记录,对于当前事务是不可见的。这时候呢,版本链roll_pointer跳到下一个版本,trx_id=100这个记录,再次校验是否可见:

    min_limit_id(100)=<trx_id(100)< max_limit_id(102);
    
    因为m_ids{100,101}包含trx_id(100),
    并且creator_trx_id (100) 等于trx_id(100)

    所以,trx_id=100这个记录,对于当前事务是可见的,所以两次查询结果,都是name=孙权的那个记录。即在可重复读(RR)隔离级别下,复用老的Read View副本,解决了不可重复读的问题。

    9. 聊聊索引在哪些场景下会失效?

    1. 查询条件包含or,可能导致索引失效

    2. 如何字段类型是字符串,where时一定用引号括起来,否则索引失效

    3. like通配符可能导致索引失效。

    4. 联合索引,查询时的条件列不是联合索引中的第一个列,索引失效。

    5. 在索引列上使用mysql的内置函数,索引失效。

    6. 对索引列运算(如,+、-、*、/),索引失效。

    7. 索引字段上使用(!= 或者 ,not in)时,可能会导致索引失效。

    8. 索引字段上使用is null, is not null,可能导致索引失效。

    9. 左连接查询或者右连接查询查询关联的字段编码格式不一样,可能导致索引失效。

    10. mysql估计使用全表扫描要比使用索引快,则不使用索引。

    10. 什么是虚拟内存

    虚拟内存,是虚拟出来的内存,它的核心思想就是确保每个程序拥有自己的地址空间,地址空间被分成多个块,每一块都有连续的地址空间。同时物理空间也分成多个块,块大小和虚拟地址空间的块大小一致,操作系统会自动将虚拟地址空间映射到物理地址空间,程序只需关注虚拟内存,请求的也是虚拟内存,真正使用却是物理内存。

    现代操作系统使用虚拟内存,即虚拟地址取代物理地址,使用虚拟内存可以有2个好处:

    • 虚拟内存空间可以远远大于物理内存空间

    • 多个虚拟内存可以指向同一个物理地址

    零拷贝实现思想,就利用了虚拟内存这个点:多个虚拟内存可以指向同一个物理地址,可以把内核空间和用户空间的虚拟地址映射到同一个物理地址,这样的话,就可以减少IO的数据拷贝次数啦,示意图如下:

    15 echte Shopee-Server-Interviewfragen, können Sie sie alle richtig beantworten? (mit Analyse)

    11. 排行榜的实现,比如高考成绩排序

    排行版的实现,一般使用redis的zset数据类型。

    使用格式如下:

    zadd key score member [score member ...],zrank key member
    • 层内部编码:ziplist(压缩列表)、skiplist(跳跃表)

    • 使用场景如排行榜,社交需求(如用户点赞)

    实现demo如下:

    115 echte Shopee-Server-Interviewfragen, können Sie sie alle richtig beantworten? (mit Analyse)

    12.分布式锁实现

    分布式锁,是控制分布式系统不同进程共同访问共享资源的一种锁的实现。秒杀下单、抢红包等等业务场景,都需要用到分布式锁,我们项目中经常使用Redis作为分布式锁。

    选了Redis分布式锁的几种实现方法,大家来讨论下,看有没有啥问题哈。

    • 命令setnx + expire分开写

    • setnx + value值是过期时间

    • set的扩展命令(set ex px nx)

    • set ex px nx + 校验唯一随机值,再删除

    • Redisson

    12.1 命令setnx + expire分开写

    if(jedis.setnx(key,lock_value) == 1){ //加锁
        expire(key,100); //设置过期时间
        try {
            do something  //业务请求
        }catch(){
      }
      finally {
           jedis.del(key); //释放锁
        }
    }

    如果执行完setnx加锁,正要执行expire设置过期时间时,进程crash掉或者要重启维护了,那这个锁就“长生不老”了,别的线程永远获取不到锁啦,所以分布式锁不能这么实现。

    12.2 setnx + value值是过期时间

    long expires = System.currentTimeMillis() + expireTime; //系统时间+设置的过期时间
    String expiresStr = String.valueOf(expires);
    
    // 如果当前锁不存在,返回加锁成功
    if (jedis.setnx(key, expiresStr) == 1) {
            return true;
    } 
    // 如果锁已经存在,获取锁的过期时间
    String currentValueStr = jedis.get(key);
    
    // 如果获取到的过期时间,小于系统当前时间,表示已经过期
    if (currentValueStr != null && Long.parseLong(currentValueStr) < System.currentTimeMillis()) {
    
         // 锁已过期,获取上一个锁的过期时间,并设置现在锁的过期时间(不了解redis的getSet命令的小伙伴,可以去官网看下哈)
        String oldValueStr = jedis.getSet(key_resource_id, expiresStr);
        
        if (oldValueStr != null && oldValueStr.equals(currentValueStr)) {
             // 考虑多线程并发的情况,只有一个线程的设置值和当前值相同,它才可以加锁
             return true;
        }
    }
            
    //其他情况,均返回加锁失败
    return false;
    }

    笔者看过有开发小伙伴就是这么实现分布式锁的,但是这种方案也有这些缺点:

    • 过期时间是客户端自己生成的,分布式环境下,每个客户端的时间必须同步。

    • 没有保存持有者的唯一标识,可能被别的客户端释放/解锁。

    • 锁过期的时候,并发多个客户端同时请求过来,都执行了jedis.getSet(),最终只能有一个客户端加锁成功,但是该客户端锁的过期时间,可能被别的客户端覆盖。

    12.3 set的扩展命令(set ex px nx)(注意可能存在的问题)

    if(jedis.set(key, lock_value, "NX", "EX", 100s) == 1){ //加锁
        try {
            do something  //业务处理
        }catch(){
      }
      finally {
           jedis.del(key); //释放锁
        }
    }

    这个方案可能存在这样的问题:

    • 锁过期释放了,业务还没执行完。

    • 锁被别的线程误删。

    12.4 set ex px nx + 校验唯一随机值,再删除

    if(jedis.set(key, uni_request_id, "NX", "EX", 100s) == 1){ //加锁
        try {
            do something  //业务处理
        }catch(){
      }
      finally {
           //判断是不是当前线程加的锁,是才释放
           if (uni_request_id.equals(jedis.get(key))) {
            jedis.del(key); //释放锁
            }
        }
    }

    在这里,判断当前线程加的锁和释放锁是不是一个原子操作。如果调用jedis.del()释放锁的时候,可能这把锁已经不属于当前客户端,会解除他人加的锁。

    一般也是用lua脚本代替。lua脚本如下:

    if redis.call(&#39;get&#39;,KEYS[1]) == ARGV[1] then 
       return redis.call(&#39;del&#39;,KEYS[1]) 
    else
       return 0
    end;

    这种方式比较不错了,一般情况下,已经可以使用这种实现方式。但是存在锁过期释放了,业务还没执行完的问题(实际上,估算个业务处理的时间,一般没啥问题了)。

    12.5 Redisson

    分布式锁可能存在锁过期释放,业务没执行完的问题。有些小伙伴认为,稍微把锁过期时间设置长一些就可以啦。其实我们设想一下,是否可以给获得锁的线程,开启一个定时守护线程,每隔一段时间检查锁是否还存在,存在则对锁的过期时间延长,防止锁过期提前释放。

    当前开源框架Redisson就解决了这个分布式锁问题。我们一起来看下Redisson底层原理是怎样的吧:

    15 echte Shopee-Server-Interviewfragen, können Sie sie alle richtig beantworten? (mit Analyse)

    只要线程一加锁成功,就会启动一个watch dog看门狗,它是一个后台线程,会每隔10秒检查一下,如果线程1还持有锁,那么就会不断的延长锁key的生存时间。因此,Redisson就是使用Redisson解决了锁过期释放,业务没执行完问题。

    13. 零拷贝

    零拷贝就是不需要将数据从一个存储区域复制到另一个存储区域。它是指在传统IO模型中,指CPU拷贝的次数为0。它是IO的优化方案

    传统IO流程

    • 零拷贝实现之mmap+write

    • 零拷贝实现之sendfile

    • 零拷贝实现之带有DMA收集拷贝功能的sendfile

    13.1 传统IO流程

    流程图如下:

    215 echte Shopee-Server-Interviewfragen, können Sie sie alle richtig beantworten? (mit Analyse)

    • 用户应用进程调用read函数,向操作系统发起IO调用,上下文从用户态转为内核态(切换1)

    • DMA控制器把数据从磁盘中,读取到内核缓冲区。

    • CPU把内核缓冲区数据,拷贝到用户应用缓冲区,上下文从内核态转为用户态(切换2),read函数返回

    • 用户应用进程通过write函数,发起IO调用,上下文从用户态转为内核态(切换3)

    • CPU将应用缓冲区中的数据,拷贝到socket缓冲区

    • DMA控制器把数据从socket缓冲区,拷贝到网卡设备,上下文从内核态切换回用户态(切换4),write函数返回

    从流程图可以看出,传统IO的读写流程,包括了4次上下文切换(4次用户态和内核态的切换),4次数据拷贝(两次CPU拷贝以及两次的DMA拷贝)。

    13.2 mmap+write实现的零拷贝

    mmap 的函数原型如下:

    void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
    • addr:指定映射的虚拟内存地址

    • length:映射的长度

    • prot:映射内存的保护模式

    • flags:指定映射的类型

    • fd:进行映射的文件句柄

    • offset:文件偏移量

    • mmap使用了虚拟内存,可以把内核空间和用户空间的虚拟地址映射到同一个物理地址,从而减少数据拷贝次数!

    mmap+write实现的零拷贝流程如下:

    215 echte Shopee-Server-Interviewfragen, können Sie sie alle richtig beantworten? (mit Analyse)

    • 用户进程通过mmap方法向操作系统内核发起IO调用,上下文从用户态切换为内核态。

    • CPU利用DMA控制器,把数据从硬盘中拷贝到内核缓冲区。

    • 上下文从内核态切换回用户态,mmap方法返回。

    • 用户进程通过write方法向操作系统内核发起IO调用,上下文从用户态切换为内核态。

    • CPU将内核缓冲区的数据拷贝到的socket缓冲区。

    • CPU利用DMA控制器,把数据从socket缓冲区拷贝到网卡,上下文从内核态切换回用户态,write调用返回。

    可以发现,mmap+write实现的零拷贝,I/O发生了4次用户空间与内核空间的上下文切换,以及3次数据拷贝。其中3次数据拷贝中,包括了2次DMA拷贝和1次CPU拷贝。

    mmap是将读缓冲区的地址和用户缓冲区的地址进行映射,内核缓冲区和应用缓冲区共享,所以节省了一次CPU拷贝‘’并且用户进程内存是虚拟的,只是映射到内核的读缓冲区,可以节省一半的内存空间。

    sendfile实现的零拷贝

    sendfile是Linux2.1内核版本后引入的一个系统调用函数,API如下:

    ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
    • out_fd:为待写入内容的文件描述符,一个socket描述符。,

    • in_fd:为待读出内容的文件描述符,必须是真实的文件,不能是socket和管道。

    • offset:指定从读入文件的哪个位置开始读,如果为NULL,表示文件的默认起始位置。

    • count:指定在fdout和fdin之间传输的字节数。

    • sendfile表示在两个文件描述符之间传输数据,它是在操作系统内核中操作的,避免了数据从内核缓冲区和用户缓冲区之间的拷贝操作,因此可以使用它来实现零拷贝。

    sendfile实现的零拷贝流程如下:

    215 echte Shopee-Server-Interviewfragen, können Sie sie alle richtig beantworten? (mit Analyse)
    sendfile实现的零拷贝

    • 用户进程发起sendfile系统调用,上下文(切换1)从用户态转向内核态

    • DMA控制器,把数据从硬盘中拷贝到内核缓冲区。

    • CPU将读缓冲区中数据拷贝到socket缓冲区

    • DMA控制器,异步把数据从socket缓冲区拷贝到网卡,

    • 上下文(切换2)从内核态切换回用户态,sendfile调用返回。

    可以发现,sendfile实现的零拷贝,I/O发生了2次用户空间与内核空间的上下文切换,以及3次数据拷贝。其中3次数据拷贝中,包括了2次DMA拷贝和1次CPU拷贝。那能不能把CPU拷贝的次数减少到0次呢?有的,即带有DMA收集拷贝功能的sendfile

    sendfile+DMA scatter/gather实现的零拷贝

    linux 2.4版本之后,对sendfile做了优化升级,引入SG-DMA技术,其实就是对DMA拷贝加入了scatter/gather操作,它可以直接从内核空间缓冲区中将数据读取到网卡。使用这个特点搞零拷贝,即还可以多省去一次CPU拷贝。

    sendfile+DMA scatter/gather实现的零拷贝流程如下:

    215 echte Shopee-Server-Interviewfragen, können Sie sie alle richtig beantworten? (mit Analyse)

    • 用户进程发起sendfile系统调用,上下文(切换1)从用户态转向内核态

    • DMA控制器,把数据从硬盘中拷贝到内核缓冲区。

    • CPU把内核缓冲区中的文件描述符信息(包括内核缓冲区的内存地址和偏移量)发送到socket缓冲区

    • DMA控制器根据文件描述符信息,直接把数据从内核缓冲区拷贝到网卡

    • 上下文(切换2)从内核态切换回用户态,sendfile调用返回。

    可以发现,sendfile+DMA scatter/gather实现的零拷贝,I/O发生了2次用户空间与内核空间的上下文切换,以及2次数据拷贝。其中2次数据拷贝都是包DMA拷贝。这就是真正的 零拷贝(Zero-copy) 技术,全程都没有通过CPU来搬运数据,所有的数据都是通过DMA来进行传输的。

    14. synchronized

    synchronized是Java中的关键字,是一种同步锁。synchronized关键字可以作用于方法或者代码块。

    一般面试时。可以这么回答:

    • 反编译后,monitorenter、monitorexit、ACC_SYNCHRONIZED

    • monitor监视器

    • Java Monitor 的工作机理

    • 对象与monitor关联

    14.1 monitorenter、monitorexit、ACC_SYNCHRONIZED

    如果synchronized作用于代码块,反编译可以看到两个指令:monitorenter、monitorexit,JVM使用monitorenter和monitorexit两个指令实现同步;如果作用synchronized作用于方法,反编译可以看到ACCSYNCHRONIZED标记,JVM通过在方法访问标识符(flags)中加入ACCSYNCHRONIZED来实现同步功能。

    • 同步代码块是通过monitorenter和monitorexit来实现,当线程执行到monitorenter的时候要先获得monitor锁,才能执行后面的方法。当线程执行到monitorexit的时候则要释放锁。

    • 同步方法是通过中设置ACCSYNCHRONIZED标志来实现,当线程执行有ACCSYNCHRONIZED标志的方法,需要获得monitor锁。每个对象都与一个monitor相关联,线程可以占有或者释放monitor。

    14.2 monitor监视器

    monitor是什么呢?操作系统的管程(monitors)是概念原理,ObjectMonitor是它的原理实现。

    215 echte Shopee-Server-Interviewfragen, können Sie sie alle richtig beantworten? (mit Analyse)

    在Java虚拟机(HotSpot)中,Monitor(管程)是由ObjectMonitor实现的,其主要数据结构如下:

     ObjectMonitor() {
        _header       = NULL;
        _count        = 0; // 记录个数
        _waiters      = 0,
        _recursions   = 0;
        _object       = NULL;
        _owner        = NULL;
        _WaitSet      = NULL;  // 处于wait状态的线程,会被加入到_WaitSet
        _WaitSetLock  = 0 ;
        _Responsible  = NULL ;
        _succ         = NULL ;
        _cxq          = NULL ;
        FreeNext      = NULL ;
        _EntryList    = NULL ;  // 处于等待锁block状态的线程,会被加入到该列表
        _SpinFreq     = 0 ;
        _SpinClock    = 0 ;
        OwnerIsThread = 0 ;
      }

    ObjectMonitor中几个关键字段的含义如图所示:

    215 echte Shopee-Server-Interviewfragen, können Sie sie alle richtig beantworten? (mit Analyse)

    14.3 Java Monitor 的工作机理

    215 echte Shopee-Server-Interviewfragen, können Sie sie alle richtig beantworten? (mit Analyse)

    • 想要获取monitor的线程,首先会进入_EntryList队列。

    • 当某个线程获取到对象的monitor后,进入Owner区域,设置为当前线程,同时计数器count加1。

    • 如果线程调用了wait()方法,则会进入WaitSet队列。它会释放monitor锁,即将owner赋值为null,count自减1,进入WaitSet队列阻塞等待。

    • 如果其他线程调用 notify() / notifyAll() ,会唤醒WaitSet中的某个线程,该线程再次尝试获取monitor锁,成功即进入Owner区域。

    • 同步方法执行完毕了,线程退出临界区,会将monitor的owner设为null,并释放监视锁。

    14.4 对象与monitor关联

    15 echte Shopee-Server-Interviewfragen, können Sie sie alle richtig beantworten? (mit Analyse)

    • 在HotSpot虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头(Header),实例数据(Instance Data)和对象填充(Padding)。

    • 对象头主要包括两部分数据:Mark Word(标记字段)、Class Pointer(类型指针)。

    Mark Word 是用于存储对象自身的运行时数据,如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程 ID、偏向时间戳等。

    215 echte Shopee-Server-Interviewfragen, können Sie sie alle richtig beantworten? (mit Analyse)

    重量级锁,指向互斥量的指针。其实synchronized是重量级锁,也就是说Synchronized的对象锁,Mark Word锁标识位为10,其中指针指向的是Monitor对象的起始地址。

    15. 分布式id生成方案有哪些?什么是雪花算法?

    分布式id生成方案主要有:

    • UUID

    • 数据库自增ID

    • 基于雪花算法(Snowflake)实现

    • 百度 (Uidgenerator)

    • 美团(Leaf)

    什么是雪花算法?

    雪花算法是一种生成分布式全局唯一ID的算法,生成的ID称为Snowflake IDs。这种算法由Twitter创建,并用于推文的ID。

    一个Snowflake ID有64位。

    • 第1位:Java中long的最高位是符号位代表正负,正数是0,负数是1,一般生成ID都为正数,所以默认为0。

    • 接下来前41位是时间戳,表示了自选定的时期以来的毫秒数。

    • 接下来的10位代表计算机ID,防止冲突。

    • 其余12位代表每台机器上生成ID的序列号,这允许在同一毫秒内创建多个Snowflake ID。

    15 echte Shopee-Server-Interviewfragen, können Sie sie alle richtig beantworten? (mit Analyse)
    雪花算法

    最后PHP中文网祝大家找到一份满意的工作!!!

    【面试题专题】

    Front-End: [Front-End-Interviewfragen][JS-Interviewfragen][ Vue-Interviewfragen][Ajax-Interviewfragen][React-Interviewfragen]

    Datenbank: [MySQL-Interview Fragen][ Redis-Interviewfragen][Oracle-Interviewfragen]

    Backend: [PHP-Interviewfragen][Thinkphp-Interviewfragen][Python-Interviewfragen][Java-Interviewfragen][ Frage zum Android-Interview

    Variabler Wert
    100, 101
    102
    100
    100
Stellungnahme:
Dieser Artikel ist reproduziert unter:微信公众号. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen