Heim  >  Artikel  >  Datenbank  >  So verwenden Sie Redis zum Sperren von Ressourcen

So verwenden Sie Redis zum Sperren von Ressourcen

WBOY
WBOYnach vorne
2023-05-28 11:01:45933Durchsuche

1. Überblick

Da diese Technologie weiterhin aktualisiert und iteriert wird, gewinnt das Konzept der Verteilung in Unternehmen immer mehr an Bedeutung! Wenn es um verteilte Sperren geht, werden unweigerlich verteilte Sperren erwähnt. In dieser Phase gibt es drei gängige Implementierungsmethoden für verteilte Sperren: Zookeeper, DB, Rediscode>, wir verwenden Redis in diesem Artikel als Beispiel! ZookeeperDBRedis,我们本篇文章以Redis为例!

从我们的角度来看,这三个属性是有效使用分布式锁所需的最低保证。

  1. 安全特性:互斥。在任何给定时刻,只有一个客户端可以持有锁。

  2. 活力属性:无死锁。最终,即使锁定资源的客户端崩溃或分区,也始终可以获得锁。

  3. 活动性:容错能力。只要大多数Redis节点都处于运行状态,客户端就可以获取和释放锁。

二、redis多节点实现分布式锁带来的挑战

我们使用Redis锁定资源的最简单方法是:

  1. 在实例中创建锁。

  2. 锁通常使用Redis过期功能在有限时间存在,因此最终将被释放,最终超过给定期限会被删除。

  3. 当客户端需要释放资源时,它将删除锁。

乍一看,似乎并没有什么问题。但是不妨我们深究一下,这种实现方案在redis单机环境下似乎并没有什么问题!但是如果节点宕了呢?好吧,那么让我们添加一个slave节点!如果主服务器宕机了,就使用这个节点!但是我们不妨来看看她真的能保证可用吗?

在谈论这个的致命缺陷时,我们需要了解一个知识点,Redis复制是异步的。

  1. 客户端A获取主服务器中的锁。

  2. 在将锁复制传输到从机之前,主机崩溃。

  3. slave晋升为      master

  4. 客户端B获取锁,因为从机并没有该锁的对象,获取成功!

显然,这样是不对的,主节点因为没来得及同步数据就宕机了,所以从节点没有该数据,从而造成分布式锁的失效,那么作者antirez的观点是如何解决这个呢?

三、Redlock算法

作者认为,我们应该使用多个Redis,这些节点是完全独立的,不需要使用复制或者任何协调数据的系统,多个redis系统获取锁的过程就变成了如下步骤:

  1. 以毫秒为单位获取当前的服务器时间

  2. 尝试使用相同的key和随机值来获取锁,对每一个机器获取锁时都应该有一个超时时间,比如锁的过期时间为10s那么获取单个节点锁的超时时间就应该为5到50毫秒左右,他这样做的目的是为了保证客户端与故障的机器连接,耗费多余的时间!超时间时间内未获取数据就放弃该节点,从而去下一个节点获取,直至将所有节点全部获取一遍!

  3. 获取完成后,获取当前时间减去步骤一获取的时间,当且仅当客户端半数以上获取成功且获取锁的时间小于锁额超时时间,则证明该锁生效!

  4. 获取锁之后,锁的超时时间等于      设置的有效时间-获取锁花费的时间

    Aus unserer Sicht sind diese drei Eigenschaften die Mindestgarantien, die für die effektive Nutzung verteilter Sperren erforderlich sind.
    1. Sicherheitsfunktionen: Gegenseitiger Ausschluss. Nur ein Client kann die Sperre zu einem bestimmten Zeitpunkt halten.

    2. Vitalitätsattribut: kein Deadlock. Letztendlich kann die Sperre immer erhalten werden, auch wenn der Client, der die Ressource sperrt, abstürzt oder Partitionen erstellt.

    Mobilität: Fehlertoleranz. Solange die meisten Redis-Knoten ausgeführt werden, können Clients Sperren erwerben und freigeben.

    2. Herausforderungen, die die Redis-Mehrknotenimplementierung verteilter Sperren mit sich bringt

    Der einfachste Weg für uns, Redis zum Sperren von Ressourcen zu verwenden, ist: #🎜 🎜#
      1. Erstellen Sie eine Sperre in der Instanz.

      2. Sperren bestehen normalerweise für eine begrenzte Zeit mithilfe der Redis-Ablauffunktion, sodass sie schließlich freigegeben und nach einem bestimmten Zeitraum gelöscht werden.

      Wenn der Client die Ressource freigeben muss, wird die Sperre aufgehoben.

    #🎜🎜# Auf den ersten Blick scheint nichts falsch zu sein. Aber werfen wir einen genaueren Blick darauf, dass dieses Implementierungsschema in einer eigenständigen Redis-Umgebung keine Probleme bereitet! Was aber, wenn der Knoten ausfällt? Okay, also fügen wir einen Slave-Knoten hinzu! Wenn der Hauptserver ausgefallen ist, verwenden Sie diesen Knoten! Aber schauen wir mal nach, ob sie wirklich garantiert verfügbar ist? #🎜🎜##🎜🎜#Wenn wir über den schwerwiegenden Fehler sprechen, müssen wir einen Wissenspunkt verstehen: Redis-Replikation ist asynchron. #🎜🎜#
      #🎜🎜##🎜🎜#Client A erhält die Sperre im Hauptserver. #🎜🎜##🎜🎜##🎜🎜##🎜🎜#Der Master stürzte ab, bevor er die Sperre auf den Slave kopierte. #🎜🎜##🎜🎜##🎜🎜##🎜🎜#slave wird zum befördert  master. #🎜🎜##🎜🎜##🎜🎜##🎜🎜#Client B erhält die Sperre, da der Slave kein Objekt für die Sperre hat und die Erfassung erfolgreich ist! #🎜🎜##🎜🎜##🎜🎜##🎜🎜#Das ist offensichtlich falsch. Der Master-Knoten ist ausgefallen, bevor er Zeit hatte, die Daten zu synchronisieren, sodass der Slave-Knoten nicht über die Daten verfügt, was die verteilte Sperre verursacht Wie löst der Autor antirez dieses Problem? #🎜🎜##🎜🎜#3. Redlock-Algorithmus#🎜🎜##🎜🎜#Der Autor ist der Meinung, dass wir mehrere Redis verwenden sollten und keine Replikation oder Verwendung benötigen alle anderen Für Systeme, die Daten koordinieren, wird der Prozess des Erwerbs von Sperren durch mehrere Redis-Systeme zu den folgenden Schritten: #🎜🎜#
        #🎜🎜## 🎜🎜#Erhalten Sie die aktuelle Serverzeit in Millisekunden#🎜🎜##🎜🎜##🎜🎜##🎜🎜#Versuchen Sie, den gleichen Schlüssel und Zufallswert zu verwenden, um die Sperre zu erhalten, die für jede Maschine beim Erwerb verwendet werden sollte Sperre Eine Zeitüberschreitung: Wenn die Ablaufzeit der Sperre beispielsweise 10 Sekunden beträgt, sollte die Zeitüberschreitung für den Erwerb einer Einzelknotensperre etwa 5 bis 50 Millisekunden betragen. Der Zweck besteht darin, sicherzustellen, dass der Client mit der ausgefallenen Maschine verbunden ist und zusätzliche Zeit verschwendet wird Zeit! Wenn die Daten nicht innerhalb des Timeout-Zeitraums abgerufen werden, wird der Knoten aufgegeben und der nächste Knoten abgerufen, bis alle Knoten abgerufen sind! #🎜🎜##🎜🎜##🎜🎜##🎜🎜#Nachdem die Akquise abgeschlossen ist, erhalten Sie die aktuelle Zeit abzüglich der in Schritt 1 erhaltenen Zeit, und zwar genau dann, wenn mehr als die Hälfte der Kunden erfolgreich akquiriert haben und die Zeit dazu Der Erwerb der Sperre ist kürzer als die Zeitüberschreitungszeit für die Sperrmenge. Dies beweist, dass die Sperre wirksam ist! #🎜🎜##🎜🎜##🎜🎜##🎜🎜#Nach dem Erwerb der Sperre ist das Sperrzeitlimit gleich Die eingestellte effektive Zeit – die Zeit, die benötigt wird, um die Sperre zu erhalten#🎜🎜##🎜🎜##🎜🎜##🎜🎜#Wenn mehr als die Hälfte der Maschinen, die die Sperre erwerben, nicht zufrieden sind , oder das Sperrzeitlimit wurde berechnet. Wenn ein abnormaler Vorgang vorliegt, z. B. eine negative Zahl, versucht das System, alle Instanzen zu entsperren. Auch wenn es einigen Instanzen nicht gelingt, die Sperre erfolgreich zu erhalten, wird dennoch versucht, sie zu entsperren. #🎜🎜##🎜🎜##🎜🎜##🎜🎜#Sperre freigeben, einfach die Sperre in allen Instanzen aufheben, unabhängig davon, ob der Client glaubt, dass er die gegebene Instanz erfolgreich sperren kann. #🎜🎜##🎜🎜##🎜🎜##🎜🎜# 4. Aber kann Redlock das Problem wirklich lösen? #🎜🎜##🎜🎜#Martin Kleppmann hat eine Artikelaufgabe gepostet, Redlock kann die Sicherheit des Schlosses nicht garantieren! #🎜🎜##🎜🎜# Er glaubt, dass Sperren nur zwei Verwendungszwecke haben zweimal ausgeführt werden Zweitklassig. Zum Beispiel (sehr teure Berechnung) #🎜🎜##🎜🎜##🎜🎜##🎜🎜#Um die Genauigkeit zu gewährleisten, wird ein Sperrmechanismus verwendet, um sicherzustellen, dass Aufgaben in einer normalen Prozessreihenfolge ausgeführt werden, um zu vermeiden, dass zwei Knoten sie verarbeiten dieselben Daten gleichzeitig ausführen. Führen Sie Vorgänge aus, die zu Dateikonflikten und Datenverlust führen. #🎜🎜##🎜🎜##🎜🎜##🎜🎜##🎜🎜#Aus dem ersten Grund haben wir eine gewisse Toleranz für Sperren. Auch wenn zwei Knoten gleichzeitig arbeiten, wird es Auswirkungen auf das System geben klein. Es kostet nur mehr Berechnungen und hat keine zusätzlichen Auswirkungen. Derzeit kann die Verwendung eines einzigen Redis-Punkts das Problem sehr gut lösen. Es besteht keine Notwendigkeit, RedLock zu verwenden, um so viele Redis-Instanzen zu verwalten und die Wartungskosten des Systems zu erhöhen. #🎜🎜#

        1. Nachteile durch die Zeitüberschreitung verteilter Sperren

        Beim zweiten Szenario ist es jedoch vorsichtiger, da es wahrscheinlich zu einigen Geldtransaktionen kommt, wenn die Sperre fehlschlägt und zwei Knoten sie gleichzeitig verarbeiten Dies kann Dateibeschädigung, Datenverlust, dauerhafte Inkonsistenz oder finanziellen Verlust zur Folge haben!

        Nehmen wir ein Szenario an, in dem wir zwei Clients haben, die eine Sperre erhalten müssen, bevor sie Daten in der Datenbank speichern können. Welche Probleme treten auf, wenn wir sie mit dem RedLock-Algorithmus implementieren? Um Deadlocks zu verhindern, hat die Sperre in RedLock eine Ablaufzeit, aber Martin hält dies für unsicher! Das Flussdiagramm sieht so aus! Martin 认为这是不安全的!该流程图类似于这样!

        So verwenden Sie Redis zum Sperren von Ressourcen  

        客户端1获取到锁成功后,开始执行,执行到一半系统发生Full GC ,系统服务被挂起,过段时间锁超时了。

        客户端2等待客户端1的锁超时后,成功的获取到锁,开始执行入库操作,完成后,客户端1完成了Full GC,又做了一次入库操作!这是不安全的!如何解决呢?

        Martin 提出来一种类似乐观锁的实现机制,示例图如下:

        So verwenden Sie Redis zum Sperren von Ressourcen  

        客户端1长时间被挂起后,客户端2获取到锁,开始写库操作,同时携带令牌 34,写库完成后,客户端1苏醒,开始进行入库操作,但是因为携带的令牌为33 小于最新令牌,该次提交就被拒绝!

        即使系统出现问题导致挂起,该思路似乎完备,可确保数据仍能得到正确处理。但是仔细想一下:

  • 如果仅当您的令牌大于所有过去的令牌时,数据存储区才能始终接受写入,则它是可线性化的存储区,相当与使用数据库来实现一个 分布式锁系统,那么RedLock的作用就变的微乎其微!甚至不在需要使用redis保证分布式锁! 

2.RedLock对于系统时钟强依赖

回想一下Redlock算法获取锁的几个步骤,你会发现锁的有效性是与当前的系统时钟强依赖,我们假设:

我们有,A B C D E 五个redis节点:

  1. 客户端1获取节点A,B,C的锁定。由于网络问题,无法访问D和E。

  2. 节点C上的时钟向前跳,导致锁过期。

  3. 客户端2获取节点C,D,E的锁定。由于网络问题,无法访问A和B。

  4. 现在,客户1和2都认为他们持有该锁。

如果C在将锁持久保存到磁盘之前崩溃并立即重新启动,则可能会发生类似的问题。

Martin认为系统时间的阶跃主要来自两个方面(以及作者给出的解决方案):

  1. 人为修改。

  • 对于人为修改,能说啥呢?人要搞破坏没办法避免。

  • 从NTP服务收到了一个跳跃时时钟更新。

    • 需要运维人员处理NTP接受阶跃时钟更新的问题。需要将阶跃的时间更新到服务器的时候,应当采取小步快跑的方式。多次修改,每次更新时间尽量小。

    3.基于程序语言弥补分布式锁的超时性所带来的缺点

    我们回顾 1 观点,深究抽象出现这个缺陷的根本原因,就是为了解决由于系统宕机带来的锁失效而给锁强加了一个失效时间,异常情况下,程序(业务)执行的时间大于锁失效时间从而造成的一系列的问题,我们能否从这方面去考虑,从而用程序来解决这个样一个死局 呢?

    我们可以保证业务程序执行时间绝对小于锁超时时间,这样就可以避免锁失效时间小于业务时间的问题

    java语言中redisson

    So verwenden Sie Redis zum Sperren von Ressourcen
    So verwenden Sie Redis zum Sperren von RessourcenNachdem Client 1 die Sperre erfolgreich erhalten hatte, begann er mit der Ausführung. In der Mitte der Ausführung kam es zu einem vollständigen GC im System, der Systemdienst wurde angehalten und die Sperre lief nach einer Weile ab.

    Nachdem Client 2 darauf gewartet hatte, dass die Sperre von Client 1 abgelaufen war, erhielt er die Sperre erfolgreich und begann mit der Durchführung des Lagervorgangs. Nach Abschluss schloss Client 1 den vollständigen GC ab und führte einen weiteren Lagervorgang durch! Das ist unsicher! Wie kann man es lösen? Martin schlug einen Implementierungsmechanismus ähnlich dem optimistischen Sperren vor. Das Beispielbild sieht wie folgt aus: So verwenden Sie Redis zum Sperren von Ressourcen

    🎜Nachdem Client 1 für längere Zeit angehalten wurde, erhält Client 2 die Sperre und beginnt mit dem Schreiben der Bibliothek, wobei er gleichzeitig das Token 34 trägt. Nachdem das Schreiben der Bibliothek abgeschlossen ist, wacht Client 1 auf und beginnt mit dem Betreten des Bibliotheksbetriebs, aber da der mitgeführte Token 33 ist, was kleiner als der letzte Token ist, wird die Übermittlung abgelehnt! 🎜🎜Selbst wenn es ein Problem mit dem System gibt, das einen Hang verursacht, scheint diese Idee vollständig zu sein, um sicherzustellen, dass die Daten weiterhin korrekt verarbeitet werden. Aber denken Sie darüber nach: 🎜
    • 🎜Wenn Ihr Token nur größer als alle vorherigen Token ist, kann der Datenspeicher dies tun. Wenn er immer Schreibvorgänge akzeptiert Es handelt sich um einen linearisierbaren Speicherbereich, der der Verwendung einer Datenbank zur Implementierung eines verteilten Sperrsystems entspricht, sodass die Rolle von RedLock minimal wird! Sie müssen nicht einmal Redis verwenden, um verteilte Sperren zu gewährleisten! 🎜
    🎜2.RedLock hängt stark von der Systemuhr ab🎜🎜Erinnern Sie sich an die Schritte des Redlock-Algorithmus, um die Sperre zu erhalten. Sie werden feststellen, dass die Wirksamkeit der Sperre gleich ist bezogen auf das aktuelle System Die Uhr ist stark abhängig, wir gehen davon aus: 🎜🎜Wir haben, A B C D E fünf Redis-Knoten: 🎜
    1. 🎜Client 1 erhält Knoten A, B, C-Sperre. Auf D und E kann aufgrund von Netzwerkproblemen nicht zugegriffen werden. 🎜
    2. 🎜Die Uhr auf Knoten C springt vorwärts, wodurch die Sperre abläuft. 🎜
    3. 🎜Client 2 erhält die Sperre der Knoten C, D und E. Auf A und B kann aufgrund von Netzwerkproblemen nicht zugegriffen werden. 🎜
    4. 🎜Jetzt denken beide Clients 1 und 2, dass sie das Schloss halten. 🎜
    🎜Ein ähnliches Problem kann auftreten, wenn C abstürzt und unmittelbar neu startet, bevor die Sperre auf der Festplatte beibehalten wird. 🎜🎜Martin glaubt, dass der Systemzeitsprung hauptsächlich auf zwei Aspekte zurückzuführen ist (und auf die vom Autor angegebene Lösung): 🎜
    1. 🎜 Mensch Änderung. 🎜
    • 🎜Was können Sie über menschliche Modifikation sagen? Es gibt keine Möglichkeit, Menschen davon abzuhalten, Zerstörung anzurichten. 🎜
  • 🎜Ich habe ein Jump-Time-Clock-Update vom NTP-Dienst erhalten. 🎜
    • 🎜Betriebs- und Wartungspersonal muss sich mit dem Problem befassen, dass NTP Schritttaktaktualisierungen akzeptiert. Wenn Sie die Schrittzeit auf dem Server aktualisieren müssen, sollten Sie kleine Schritte unternehmen und schnell ausführen. Ändern Sie mehrmals, und die Zeit für jede Aktualisierung sollte so kurz wie möglich sein. 🎜
    🎜3. Machen Sie die durch die Zeitüberschreitung verteilter Sperren basierend auf der Programmiersprache wett🎜🎜Wir überprüfen einen Standpunkt und untersuchen die Grundursache dieses abstrakten Fehlers Um das Problem zu lösen, wird der Sperre aufgrund von Sperrfehlern eine Ablaufzeit auferlegt. Unter ungewöhnlichen Umständen ist die Ausführungszeit des Programms (Geschäfts) länger als die Ablaufzeit der Sperre, was zu einer Reihe von Problemen führt Können wir diesen Aspekt berücksichtigen? Wie kann man ein Programm verwenden, um eine solche tote Situation zu lösen? 🎜🎜Wir können sicherstellen, dass die Ausführungszeit des Geschäftsprogramms absolut kürzer als das Sperrzeitlimit ist, sodass wir das Problem vermeiden können, dass die Sperrablaufzeit kürzer als die Geschäftszeit ist. 🎜🎜In der Java-Sprache redisson implementiert eine Methode, um sicherzustellen, dass die Ablaufzeit der Sperre absolut größer ist als der Mechanismus der Ausführungszeit des Geschäftsprogramms. Offiziell als Watchdog-Mechanismus (Watchdog) bezeichnet, besteht sein Hauptprinzip darin, dass das Programm, nachdem es die Sperre erfolgreich erworben hat, einen untergeordneten Thread verzweigt, um die Sperre kontinuierlich zu erneuern, bis die Sperre aufgehoben wird! Sein schematisches Diagramm sieht ungefähr so ​​aus: 🎜🎜🎜 🎜🎜redisson verwendet einen Daemon-Thread, um die Sperre zu erneuern (Die Rolle des Daemon-Threads: Wenn der 🎜Haupt-Thread🎜 zerstört wird, wird er zusammen mit dem 🎜Haupt-Thread🎜 zerstört.) Um zu verhindern, dass sich der Thread weiter erneuert Nachdem das Programm heruntergefahren wurde, verursachte Lock! 🎜

    Darüber hinaus implementiert und optimiert Redisson auch den RedLock-Algorithmus, Fair Lock, Reentrant Lock, Chain und andere Vorgänge, wodurch die Implementierung der verteilten Redis-Sperre einfacher und effizienter wird!

    Das obige ist der detaillierte Inhalt vonSo verwenden Sie Redis zum Sperren von Ressourcen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

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