Heim häufiges Problem Was sind die drei Implementierungsmethoden verteilter Sperren?

Was sind die drei Implementierungsmethoden verteilter Sperren?

Dec 14, 2020 am 11:29 AM
分布式锁

Drei Möglichkeiten zur Implementierung verteilter Sperren: 1. Implementieren Sie verteilte Sperren basierend auf der Datenbank. 2. Implementieren Sie verteilte Sperren basierend auf dem Cache (Redis usw.). 3. Implementieren Sie verteilte Sperren basierend auf Zookeeper. Aus Leistungssicht (von hoch nach niedrig): „Cache-Modus > Zookeeper-Modus > = Datenbankmodus“.

Was sind die drei Implementierungsmethoden verteilter Sperren?

Die Betriebsumgebung dieses Artikels: Windows-System, Redis 6.0, Thinkpad T480-Computer.

Drei Möglichkeiten zur Implementierung verteilter Sperren:

. Implementieren Sie verteilte Sperren basierend auf dem Cache (Redis usw.);

1. Implementieren Sie eine verteilte Sperre basierend auf der Datenbank Verwenden Sie select … where … für die Aktualisierung der exklusiven Sperre Hinweis: Andere zusätzliche Funktionen sind grundsätzlich die gleichen wie bei der Implementierung ist „where name= lock“, das Namensfeld muss indiziert werden, sonst wird die Tabelle gesperrt. In einigen Fällen, beispielsweise wenn die Tabelle nicht groß ist, verwendet der MySQL-Optimierer diesen Index nicht, was zu Problemen mit der Tabellensperre führt.

2. Optimistische Sperre

Der größte Unterschied zwischen der sogenannten optimistischen Sperre und den vorherigen besteht darin, dass sie sich nicht gegenseitig ausschließt und während des Betriebs keine Sperre verursacht Es wird davon ausgegangen, dass kein Parallelitätskonflikt vorliegt, erst wenn die Aktualisierung der Version fehlschlägt. Unsere Eilverkäufe und Flash-Verkäufe nutzen diese Implementierung, um Überverkäufe zu verhindern.

Implementieren Sie eine optimistische Sperre, indem Sie ein inkrementelles Versionsnummernfeld hinzufügen


2. Implementieren Sie eine verteilte Sperre basierend auf dem Cache (Redis usw.)

1. Einführung in die Verwendung von Befehlen: (1) SETNXSETNX Schlüsselwert: Nur wenn der Schlüssel nicht vorhanden ist, legen Sie eine Zeichenfolge mit dem Schlüsselwert fest und geben Sie 1 zurück. Wenn der Schlüssel vorhanden ist, tun Sie nichts und geben Sie 0 zurück. (2) Ablaufdatum des Schlüssels: Legen Sie ein Zeitlimit für den Schlüssel fest. Das Gerät wird nach dieser Zeit automatisch freigegeben, um einen Deadlock zu vermeiden. (3) delete

delete key: delete key


Bei Verwendung von Redis zur Implementierung verteilter Sperren werden hauptsächlich diese drei Befehle verwendet.

2. Implementierungsidee:
(1) Verwenden Sie beim Erwerb der Sperre setnx, um sie zu sperren, und fügen Sie der Sperre mit dem Befehl „expire“ eine Zeitüberschreitung hinzu lock ist eine zufällig generierte UUID, die zur Beurteilung verwendet wird, wann die Sperre aufgehoben wird.
(2) Beim Erwerb der Sperre wird auch eine Timeout-Zeit für den Erwerb festgelegt. Bei Überschreitung dieser Zeit wird der Erwerb der Sperre aufgegeben.
(3) Wenn Sie eine Sperre aufheben, verwenden Sie die UUID, um festzustellen, ob es sich um die Sperre handelt. Wenn es sich um die Sperre handelt, führen Sie „Delete“ aus, um die Sperre aufzuheben.

3. Einfacher Implementierungscode der verteilten Sperre:

 /**
    * 分布式锁的简单实现代码    */
   public class DistributedLock {
   
       private final JedisPool jedisPool;
   
       public DistributedLock(JedisPool jedisPool) {
          this.jedisPool = jedisPool;
      }
  
      /**
       * 加锁
       * @param lockName       锁的key
       * @param acquireTimeout 获取超时时间
       * @param timeout        锁的超时时间
       * @return 锁标识
       */
      public String lockWithTimeout(String lockName, long acquireTimeout, long timeout) {
          Jedis conn = null;
          String retIdentifier = null;
          try {
              // 获取连接
              conn = jedisPool.getResource();
              // 随机生成一个value
              String identifier = UUID.randomUUID().toString();
              // 锁名,即key值
              String lockKey = "lock:" + lockName;
              // 超时时间,上锁后超过此时间则自动释放锁
              int lockExpire = (int) (timeout / );
  
              // 获取锁的超时时间,超过这个时间则放弃获取锁
              long end = System.currentTimeMillis() + acquireTimeout;
              while (System.currentTimeMillis()  results = transaction.exec();
                     if (results == null) {
                         continue;
                     }
                     retFlag = true;
                 }
                 conn.unwatch();
                 break;
             }
         } catch (JedisException e) {
             e.printStackTrace();
         } finally {
             if (conn != null) {
                 conn.close();
             }
         }
         return retFlag;
     }
 }
Nach dem Login kopieren

4. Testen Sie die gerade implementierte verteilte Sperre

Im Beispiel werden 50 Threads verwendet, um das sofortige Beenden eines Produkts zu simulieren, und der –-Operator wird verwendet, um die zu reduzieren Produkt und die Ergebnisse werden geordnet. Mithilfe der Funktion können Sie sehen, ob es gesperrt ist.

Simulieren Sie den Flash-Sale-Dienst, konfigurieren Sie den darin enthaltenen Jedis-Thread-Pool und übergeben Sie ihn während der Initialisierung zur Verwendung an die verteilte Sperre.

public class Service {

    private static JedisPool pool = null;

    private DistributedLock lock = new DistributedLock(pool);

    int n = 500;

    static {
        JedisPoolConfig config = new JedisPoolConfig();
        // 设置最大连接数
        config.setMaxTotal(200);
        // 设置最大空闲数
        config.setMaxIdle(8);
        // 设置最大等待时间
        config.setMaxWaitMillis(1000 * 100);
        // 在borrow一个jedis实例时,是否需要验证,若为true,则所有jedis实例均是可用的
        config.setTestOnBorrow(true);
        pool = new JedisPool(config, "127.0.0.1", 6379, 3000);
    }

    public void seckill() {
        // 返回锁的value值,供释放锁时候进行判断
        String identifier = lock.lockWithTimeout("resource", 5000, 1000);
        System.out.println(Thread.currentThread().getName() + "获得了锁");
        System.out.println(--n);
        lock.releaseLock("resource", identifier);
    }
}
Nach dem Login kopieren
Simulieren Sie Threads, um Flash-Kill-Dienste auszuführen.

public class ThreadA extends Thread {
    private Service service;

    public ThreadA(Service service) {
        this.service = service;
    }

    @Override
    public void run() {
        service.seckill();
    }
}

public class Test {
    public static void main(String[] args) {
        Service service = new Service();
        for (int i = 0; i Die Ergebnisse sind wie folgt, die Ergebnisse sind in der richtigen Reihenfolge: <p></p><p></p><p>Wenn Sie den Teil mit Sperren auskommentieren: </p><pre class="brush:php;toolbar:false">public void seckill() {
    // 返回锁的value值,供释放锁时候进行判断
    //String indentifier = lock.lockWithTimeout("resource", 5000, 1000);
    System.out.println(Thread.currentThread().getName() + "获得了锁");
    System.out.println(--n);
    //lock.releaseLock("resource", indentifier);
}
Nach dem Login kopieren

Wie aus den Ergebnissen ersichtlich ist , einige werden asynchron ausgeführt:

Was sind die drei Implementierungsmethoden verteilter Sperren?

Drei, Implementierung verteilter Sperren basierend auf Zookeeper

Was sind die drei Implementierungsmethoden verteilter Sperren?

ZooKeeper ist eine Open-Source-Komponente, die Konsistenzdienste für verteilte Anwendungen bereitstellt. Intern handelt es sich um eine hierarchische Dateisystemverzeichnisbaumstruktur , das Gleiche festlegen Es kann nur einen eindeutigen Dateinamen in einem Verzeichnis geben. Die Schritte zum Implementieren verteilter Sperren basierend auf ZooKeeper sind wie folgt:

(1) Erstellen Sie ein Verzeichnis mylock; (2) Wenn Thread A die Sperre erwerben möchte, erstellen Sie einen temporären Sequenzknoten im mylock-Verzeichnis (3) Holen Sie sich alle untergeordneten Knoten im Mylock-Verzeichnisknoten und rufen Sie dann den Geschwisterknoten ab, der kleiner als er selbst ist. Wenn er nicht vorhanden ist, bedeutet dies, dass der aktuelle Thread die kleinste Sequenznummer hat und die Sperre erhält. (4) Thread B erhält alle Knoten, stellt fest, dass es sich nicht um den kleinsten Knoten handelt, und richtet Überwachungsknoten ein, die kleiner als er selbst sind.

(5) Nachdem Thread A die Verarbeitung abgeschlossen hat, löscht er seinen eigenen Knoten und stellt fest, ob er der kleinste ist Wenn ja, erhält er die Sperre.

Hier empfehlen wir Curator, eine Apache-Open-Source-Bibliothek, bei der es sich um einen ZooKeeper-Client handelt. Der von Curator bereitgestellte InterProcessMutex dient zum Erfassen von Sperren und die Release-Methode zum Freigeben von Sperren.


Der Implementierungsquellcode lautet wie folgt:

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.RetryNTimes;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.data.Stat;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

/**
 * 分布式锁Zookeeper实现
 *
 */
@Slf4j
@Component
public class ZkLock implements DistributionLock {
private String zkAddress = "zk_adress";
    private static final String root = "package root";
    private CuratorFramework zkClient;

    private final String LOCK_PREFIX = "/lock_";

    @Bean
    public DistributionLock initZkLock() {
        if (StringUtils.isBlank(root)) {
            throw new RuntimeException("zookeeper 'root' can't be null");
        }
        zkClient = CuratorFrameworkFactory
                .builder()
                .connectString(zkAddress)
                .retryPolicy(new RetryNTimes(2000, 20000))
                .namespace(root)
                .build();
        zkClient.start();
        return this;
    }

    public boolean tryLock(String lockName) {
        lockName = LOCK_PREFIX+lockName;
        boolean locked = true;
        try {
            Stat stat = zkClient.checkExists().forPath(lockName);
            if (stat == null) {
                log.info("tryLock:{}", lockName);
                stat = zkClient.checkExists().forPath(lockName);
                if (stat == null) {
                    zkClient
                            .create()
                            .creatingParentsIfNeeded()
                            .withMode(CreateMode.EPHEMERAL)
                            .forPath(lockName, "1".getBytes());
                } else {
                    log.warn("double-check stat.version:{}", stat.getAversion());
                    locked = false;
                }
            } else {
                log.warn("check stat.version:{}", stat.getAversion());
                locked = false;
            }
        } catch (Exception e) {
            locked = false;
        }
        return locked;
    }

    public boolean tryLock(String key, long timeout) {
        return false;
    }

    public void release(String lockName) {
        lockName = LOCK_PREFIX+lockName;
        try {
            zkClient
                    .delete()
                    .guaranteed()
                    .deletingChildrenIfNeeded()
                    .forPath(lockName);
            log.info("release:{}", lockName);
        } catch (Exception e) {
            log.error("删除", e);
        }
    }

    public void setZkAddress(String zkAddress) {
        this.zkAddress = zkAddress;
    }
}
Nach dem Login kopieren

Vorteile: Es verfügt über Funktionen für hohe Verfügbarkeit, Wiedereintrittsfähigkeit und blockierende Sperren, die das Problem des Fehler-Deadlocks lösen können.
Nachteile: Da Knoten häufig erstellt und gelöscht werden müssen, ist die Leistung nicht so gut wie bei Redis.

Viertens, Vergleich

Implementierung verteilter DatenbanksperrenNachteile:

1. Die Leistung des Datenbankvorgangs ist schlecht und es besteht die Gefahr einer Tabellensperre.
2 Nachdem der nicht blockierende Vorgang fehlgeschlagen ist, werden CPU-Ressourcen beansprucht.
3 Lange Zeit kann mehr Verbindungsressourcen beanspruchen

Redis (Cache) verteilte Sperrenimplementierung
Nachteile:

1 Die Ablaufzeit des Sperrlöschfehlers ist schwer zu kontrollieren
2. Nicht blockierend, nachdem der Vorgang fehlgeschlagen ist Erforderlich und CPU-Ressourcen sind belegt dann mit den Followern synchronisiert.

Kurz gesagt: ZooKeeper bietet eine gute Leistung und Zuverlässigkeit. Aus Sicht der Benutzerfreundlichkeit (von niedrig nach hoch) Datenbank > Cache > Zookeeper

Aus Sicht der Implementierungskomplexität (von niedrig nach hoch) Zookeeper >= Cache > (Von hoch nach niedrig) Cache > Zookeeper > Aus Sicht der Zuverlässigkeit (von hoch nach niedrig) Cache >

Das obige ist der detaillierte Inhalt vonWas sind die drei Implementierungsmethoden verteilter Sperren?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

Video Face Swap

Video Face Swap

Tauschen Sie Gesichter in jedem Video mühelos mit unserem völlig kostenlosen KI-Gesichtstausch-Tool aus!

Heiße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Verteiltes Schloss: 5 Fälle, vom Eintritt bis zur Beerdigung Verteiltes Schloss: 5 Fälle, vom Eintritt bis zur Beerdigung Aug 24, 2023 pm 02:48 PM

Was ich heute mit Ihnen teilen möchte, sind verteilte Sperren. In diesem Artikel werden fünf Fälle, Diagramme, Quellcodeanalysen usw. verwendet. Gängige Sperren wie „synced“ und „Lock“ werden alle auf der Grundlage einer einzigen JVM implementiert. Was sollten wir in einem verteilten Szenario tun? Zu diesem Zeitpunkt erschienen verteilte Sperren.

Verwendung von ZooKeeper für die verteilte Sperrenverarbeitung in der Java-API-Entwicklung Verwendung von ZooKeeper für die verteilte Sperrenverarbeitung in der Java-API-Entwicklung Jun 17, 2023 pm 10:36 PM

Da sich moderne Anwendungen ständig weiterentwickeln und der Bedarf an Hochverfügbarkeit und Parallelität wächst, werden verteilte Systemarchitekturen immer häufiger eingesetzt. In einem verteilten System laufen mehrere Prozesse oder Knoten gleichzeitig und erledigen Aufgaben gemeinsam, wobei die Synchronisierung zwischen Prozessen besonders wichtig wird. Da viele Knoten in einer verteilten Umgebung gleichzeitig auf gemeinsam genutzte Ressourcen zugreifen können, ist der Umgang mit Parallelitäts- und Synchronisierungsproblemen zu einer wichtigen Aufgabe in einem verteilten System geworden. In dieser Hinsicht hat sich ZooKeeper zu einer sehr beliebten Lösung entwickelt. ZooKee

Vergleich der Etcd-Implementierung verteilter Sperren in Redis Vergleich der Etcd-Implementierung verteilter Sperren in Redis Jun 20, 2023 pm 05:51 PM

Mit der allmählichen Verbreitung verteilter Systeme sind verteilte Sperren zu einem wichtigen Mittel zur Gewährleistung der Systemstabilität und Datenkonsistenz geworden. Als leistungsstarke Datenbank mit verteiltem Speicher ist Redis natürlich zu einer der wichtigsten Implementierungen verteilter Sperren geworden. In den letzten Jahren hat Etcd jedoch als aufstrebende verteilte Konsistenzlösung immer mehr Aufmerksamkeit erhalten. In diesem Artikel werden die Ähnlichkeiten und Unterschiede zwischen der Implementierung verteilter Sperren durch Redis und Etcd unter Aspekten wie Implementierungsprinzipien und vergleichender Analyse erörtert. Das Prinzip der Implementierung verteilter Sperren durch Redis Die Implementierung verteilter Sperren durch Redis

Die Königslösung unter den verteilten Schlössern – Redisson Die Königslösung unter den verteilten Schlössern – Redisson Aug 24, 2023 pm 03:31 PM

Wenn Sie Redis bereits verwendet haben, erzielen Sie mit Redisson das doppelte Ergebnis mit halbem Aufwand. Redisson bietet die einfachste und bequemste Möglichkeit, Redis zu verwenden. Der Zweck von Redisson besteht darin, die Trennung der Benutzer von Redis zu fördern, damit sich Benutzer mehr auf die Verarbeitung der Geschäftslogik konzentrieren können.

Verwendung von Redis zur Implementierung verteilter Sperren in PHP Verwendung von Redis zur Implementierung verteilter Sperren in PHP May 15, 2023 pm 03:51 PM

Mit der rasanten Entwicklung des Internets und dem starken Anstieg der Website-Besuche ist die Bedeutung verteilter Systeme allmählich in den Vordergrund gerückt. In verteilten Systemen sind zwangsläufig Probleme der Parallelitätssynchronisation und der Datenkonsistenz verbunden. Verteilte Sperren als Mittel zur Lösung von Parallelitätssynchronisationsproblemen werden in verteilten Systemen nach und nach weit verbreitet eingesetzt. In PHP kann Redis zur Implementierung verteilter Sperren verwendet werden, die in diesem Artikel vorgestellt werden. Was ist eine verteilte Sperre? Wenn in einem verteilten System mehrere Maschinen dieselbe Aufgabe gemeinsam verarbeiten, wird das Auftreten mehrerer Maschinen vermieden

Wie verwende ich verteilte Sperren, um den gleichzeitigen Zugriff in MySQL zu steuern? Wie verwende ich verteilte Sperren, um den gleichzeitigen Zugriff in MySQL zu steuern? Jul 30, 2023 pm 10:04 PM

Wie verwende ich verteilte Sperren, um den gleichzeitigen Zugriff in MySQL zu steuern? In Datenbanksystemen ist ein hoher gleichzeitiger Zugriff ein häufiges Problem, und verteilte Sperren sind eine der häufigsten Lösungen. In diesem Artikel wird die Verwendung verteilter Sperren in MySQL zur Steuerung des gleichzeitigen Zugriffs vorgestellt und entsprechende Codebeispiele bereitgestellt. 1. Prinzip Verteilte Sperren können zum Schutz gemeinsam genutzter Ressourcen verwendet werden, um sicherzustellen, dass nur ein Thread gleichzeitig auf die Ressource zugreifen kann. In MySQL können verteilte Sperren folgendermaßen implementiert werden: Erstellen Sie eine Datei mit dem Namen lock_tabl

Detaillierte Erläuterung der verteilten Sperrimplementierung in Redis Detaillierte Erläuterung der verteilten Sperrimplementierung in Redis Jun 21, 2023 am 11:02 AM

Mit der rasanten Entwicklung des mobilen Internets und dem explosionsartigen Wachstum des Datenvolumens erfreuen sich verteilte Systeme immer größerer Beliebtheit. In verteilten Systemen tritt das Problem gleichzeitiger Vorgänge immer stärker in den Vordergrund. Wenn mehrere Threads gleichzeitig gemeinsam genutzte Ressourcen anfordern, müssen diese Ressourcen gesperrt werden, um die Datenkonsistenz sicherzustellen. Verteilte Sperren sind eine der effektivsten Lösungen für die Implementierung gleichzeitiger Vorgänge in verteilten Systemen. In diesem Artikel wird detailliert beschrieben, wie Sie Redis zur Implementierung verteilter Sperren verwenden. Redis-Grundlagen Redis ist ein speicherbasiertes Schlüsselwertspeichersystem, das verteilt ist

Consul-Vergleich der Redis-Implementierung verteilter Sperren Consul-Vergleich der Redis-Implementierung verteilter Sperren Jun 20, 2023 pm 02:38 PM

Vergleich der Implementierung verteilter Sperren durch Consul in Redis In verteilten Systemen sind Sperren ein wesentlicher Synchronisierungsmechanismus. Als häufig verwendete NoSQL-Datenbank hat die von Redis bereitgestellte verteilte Sperrfunktion große Aufmerksamkeit und Anwendung gefunden. Bei der Implementierung verteilter Sperren weist Redis jedoch bestimmte Probleme auf, z. B. die erneute Erfassung von Sperren und die Verarbeitung von Zeitüberschreitungen. Daher wurden einige neue Tools zur Lösung dieser Probleme entwickelt, darunter Consul. In diesem Artikel werden verteilte Sperren in Redis und Consul implementiert