Heim  >  Artikel  >  Datenbank  >  Lassen Sie uns über das Prinzip verteilter Sperren sprechen und wie Redis verteilte Sperren implementiert

Lassen Sie uns über das Prinzip verteilter Sperren sprechen und wie Redis verteilte Sperren implementiert

藏色散人
藏色散人nach vorne
2023-01-27 07:30:011140Durchsuche

Dieser Artikel vermittelt Ihnen relevantes Wissen über Redis und stellt hauptsächlich vor, was verteilte Sperren sind. Wie implementiert Redis verteilte Sperren? Welche Voraussetzungen müssen erfüllt sein? Werfen wir einen Blick nach unten. Ich hoffe, dass es Freunden in Not hilfreich sein wird.

1. Grundprinzipien verteilter Sperren

Verteilte Sperren: Sperren, die für mehrere Prozesse in einem verteilten System oder Clustermodus sichtbar sind und sich gegenseitig ausschließen.

Bedingungen, die verteilte Sperren erfüllen sollten:

  • Sichtbarkeit: Mehrere Threads können das gleiche Ergebnis sehen. Hinweis: Die hier erwähnte Sichtbarkeit bezieht sich nicht auf die Speichersichtbarkeit bei gleichzeitiger Programmierung. Sie bedeutet lediglich, dass mehrere Prozesse Änderungen wahrnehmen können. Gegenseitiger Ausschluss: Gegenseitiger Ausschluss ist die grundlegendste Bedingung für verteilte Sperren, sodass das Programm seriell ausgeführt werden kann
  • Hohe Verfügbarkeit: Das Programm stürzt nicht leicht ab und gewährleistet jederzeit eine hohe Verfügbarkeit
  • Hohe Leistung: Aufgrund der Sperre selbst wird die Leistung verbessert Reduzieren, alle verteilten Sperren selbst erfordern Höhere Sperrleistung und Sperrfreigabeleistung Leistung von MySQL: Bei der Verwendung verteilter Sperren kommt es tatsächlich relativ selten vor, dass MySQL als verteilte Sperre verwendet wird Wird bei der Entwicklung auf Unternehmensebene als verteilte Sperre verwendet. Wenn der Schlüssel erfolgreich eingefügt wird, bedeutet dies, dass die Sperre von anderen nicht eingefügt werden kann Satz von Logik zum Implementieren verteilter Sperren
  • Zookeeper: Zookeeper ist auch eine bessere Lösung für die Implementierung verteilter Sperren in der Entwicklung auf Unternehmensebene

    2. Implementieren Sie die Verteilung basierend auf Redis Type Lock
  • Zwei grundlegende Methoden die bei der Implementierung verteilter Sperren implementiert werden müssen:
  • Erwerb der Sperre:
  • Gegenseitiger Ausschluss: Sicherstellen, dass nur ein Thread die Sperre erwerben kann
Nicht blockierend: einmal versuchen und erfolgreich true zurückgeben, bei false zurückgeben Fehler

Lassen Sie uns über das Prinzip verteilter Sperren sprechen und wie Redis verteilte Sperren implementiert

Sperre freigeben:

Manuelle Freigabe

    Timeout-Freigabe: Beim Erwerb der Sperre ein Timeout hinzufügen
    • Verteiltes Sperrprinzip basierend auf Redis implementieren:
    SET resource_name my_random_value NX PX 30000
Ressourcenname : Ressourcenname, Verschiedene Sperren können je nach Unternehmen unterschieden werden
  • my_random_value: Zufälliger Wert, der Zufallswert jedes Threads ist unterschiedlich und wird zur Überprüfung beim Aufheben der Sperre verwendet

      NX: Erfolgreich festlegen, wenn der Schlüssel nicht vorhanden ist, ist der Schlüssel vorhanden Die Einstellung ist fehlgeschlagen Die Sperre wird erhalten und kann ausgeführt werden. Wenn eine Ausnahme auftritt und die Sperre abläuft, wird die Sperre automatisch aufgehoben Basierend auf Redis - RedisLock
    • public interface ILock extends AutoCloseable {
          /**
           * 尝试获取锁
           *
           * @param timeoutSec 锁持有的超时时间,过期后自动释放
           * @return true代表获取锁成功;false代表获取锁失败
           */
          boolean tryLock(long timeoutSec);
      
          /**
           * 释放锁
           * @return
           */
          void unLock();
      }
    • Problem beim versehentlichen Löschen der Sperre
  • Problembeschreibung:

    Thread 1, der die Sperre hält, ist innerhalb der Sperre blockiert. Zu diesem Zeitpunkt wird die Sperre automatisch freigegeben 2 versucht, die Sperre zu erhalten, und dann führt Thread 2 die Sperre aus. Während des Vorgangs reagiert Thread 1, setzt die Ausführung fort und erreicht die Sperre, die zu Thread 2 gehören sollte Dies ist der Fall, wenn die Sperre versehentlich gelöscht wird.

      Lösung:
    • Beurteilen Sie beim Speichern der Sperre, ob es sich um die ID der aktuellen Sperre handelt. Wenn nicht, löschen Sie sie Es wird keine Löschung durchgeführt.
    • Version 2: Lösung des Problems der versehentlichen Sperrenlöschung
    • public class SimpleRedisLock {
          private final StringRedisTemplate stringRedisTemplate;
          private final String name;
      
          public SimpleRedisLock(StringRedisTemplate stringRedisTemplate, String name) {
              this.stringRedisTemplate = stringRedisTemplate;
              this.name = name;
          }
      
          private static final String KEY_PREFIX = "lock:";
      
          @Override
          public boolean tryLock(long timeoutSec) {
              //获取线程标识
              String threadId = Thread.currentThread().getId();
              //获取锁
              Boolean success = stringRedisTemplate.opsForValue()
                      .setIfAbsent(KEY_PREFIX + name, threadId, timeoutSec, TimeUnit.SECONDS);
              return Boolean.TRUE.equals(success);
          }
      
          @Override
          public void unLock() {
              //通过del删除锁
              stringRedisTemplate.delete(KEY_PREFIX + name);
          }
      
          @Override
          public void close() {
              unLock();
          }
      }
    • Das Atomizitätsproblem der Sperrenfreigabe

    Problemanalyse:

    Der obige Code zum Freigeben der Sperre weist immer noch das Problem der versehentlichen Sperrenlöschung auf, wenn Thread 1 erhalten wird Die Thread-ID in der Sperre wird anhand der Identifizierung als eigene Sperre beurteilt. Zu diesem Zeitpunkt wird die Sperre automatisch aufgehoben, wenn sie abläuft. Es kommt vor, dass Thread 2 versucht, die Sperre zu erhalten Zu diesem Zeitpunkt führt Thread 1 noch den Vorgang zum Aufheben der Sperre aus, was zum versehentlichen Löschen der von Thread 2 gehaltenen Sperre führt.

    Der Grund dafür ist, dass der durch Java-Code implementierte Sperrfreigabeprozess keine atomare Operation ist und Probleme mit der Thread-Sicherheit aufweist.

    Lösung:

    Redis bietet eine Lua-Skriptfunktion. Durch das Schreiben mehrerer Redis-Befehle in einem Skript kann die Atomizität der Ausführung mehrerer Befehle sichergestellt werden.

    Version 3: Lua-Skript aufrufen, um verteilte Sperre umzuwandeln

    public class SimpleRedisLock {
        private final StringRedisTemplate stringRedisTemplate;
        private final String name;
    
        public SimpleRedisLock(StringRedisTemplate stringRedisTemplate, String name) {
            this.stringRedisTemplate = stringRedisTemplate;
            this.name = name;
        }
    
        private static final String KEY_PREFIX = "lock:";
        private static final String ID_PREFIX = UUID.randomUUID().toString(true) + "-";
    
        @Override
        public boolean tryLock(long timeoutSec) {
            //获取线程标识
            String threadId = ID_PREFIX + Thread.currentThread().getId();
            //获取锁
            Boolean success = stringRedisTemplate.opsForValue()
                    .setIfAbsent(KEY_PREFIX + name, threadId, timeoutSec, TimeUnit.SECONDS);
            return Boolean.TRUE.equals(success);
        }
    
        @Override
        public void unLock() {
            // 获取线程标示
            String threadId = ID_PREFIX + Thread.currentThread().getId();
            // 获取锁中的标示
            String id = stringRedisTemplate.opsForValue().get(KEY_PREFIX + name);
            // 判断标示是否一致
            if(threadId.equals(id)) {
                // 释放锁
                stringRedisTemplate.delete(KEY_PREFIX + name);
            }
        }
    
        @Override
        public void close() {
            unLock();
        }
    }
    Empfohlenes Lernen: „Redis-Video-Tutorial

    Das obige ist der detaillierte Inhalt vonLassen Sie uns über das Prinzip verteilter Sperren sprechen und wie Redis verteilte Sperren implementiert. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

    Stellungnahme:
    Dieser Artikel ist reproduziert unter:juejin.im. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen