Maison > base de données > Redis > le corps du texte

Comment utiliser Redis pour verrouiller les ressources

WBOY
Libérer: 2023-05-28 11:01:45
avant
896 Les gens l'ont consulté

1. Vue d'ensemble

À mesure que cette technologie continue d'être mise à jour et itérée, le concept de distribution prend de plus en plus de poids dans les entreprises ! Lorsqu'on parle de verrous distribués, on parlera inévitablement de verrous distribués. À ce stade, il existe trois méthodes principales d'implémentation de verrous distribués, Zookeeper, DB, Redis. code>, nous utilisons Redis comme exemple dans cet article ! 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. 获取锁之后,锁的超时时间等于      设置的有效时间-获取锁花费的时间

    De notre point de vue, ces trois propriétés constituent les garanties minimales requises pour utiliser efficacement les verrous distribués.
    1. Fonctionnalités de sécurité : Exclusion mutuelle. A un moment donné, un seul client peut détenir le verrou.

    2. Attribut Vitalité : pas d'impasse. En fin de compte, le verrou peut toujours être obtenu même si le client verrouillant la ressource plante ou se partitionne.

    Liquidité : tolérance aux pannes. Tant qu'une majorité de nœuds Redis sont en cours d'exécution, les clients peuvent acquérir et libérer des verrous.

    2. Défis posés par la mise en œuvre multi-nœuds de verrous distribués dans Redis

    La façon la plus simple pour nous d'utiliser Redis pour verrouiller les ressources est : #🎜 🎜#
      1. Créez un verrou dans l'instance.

      2. Les verrous existent généralement pour une durée limitée grâce à la fonction d'expiration de Redis, ils finiront donc par être libérés et seront éventuellement supprimés après une période donnée.

      Lorsque le client doit libérer la ressource, il supprimera le verrou.

    #🎜🎜# À première vue, il ne semble y avoir rien de mal. Mais regardons de plus près. Cette solution d’implémentation ne semble poser aucun problème dans un environnement autonome Redis ! Mais que se passe-t-il si le nœud tombe en panne ? D'accord, ajoutons donc un nœud esclave ! Si le serveur principal est en panne, utilisez ce nœud ! Mais jetons un coup d’œil et voyons si sa disponibilité est vraiment garantie ? #🎜🎜##🎜🎜#Lorsque nous parlons du défaut fatal de cela, nous devons comprendre un point de connaissance, La réplication Redis est asynchrone. #🎜🎜#
      #🎜🎜##🎜🎜#Le client A acquiert le verrou sur le serveur principal. #🎜🎜##🎜🎜##🎜🎜##🎜🎜#Le maître s'est écrasé avant de copier le verrou sur l'esclave. #🎜🎜##🎜🎜##🎜🎜##🎜🎜#esclave est promu au  maître. #🎜🎜##🎜🎜##🎜🎜##🎜🎜#Le client B acquiert la serrure car l'esclave n'a pas d'objet pour la serrure, et l'acquisition est réussie ! #🎜🎜##🎜🎜##🎜🎜##🎜🎜#De toute évidence, c'est faux. Le nœud maître est tombé en panne avant d'avoir eu le temps de synchroniser les données, donc le nœud esclave n'a pas les données, provoquant le verrouillage distribué. échouer. Alors, comment l'auteur antirez résout-il ce problème ? #🎜🎜##🎜🎜#3. Algorithme Redlock#🎜🎜##🎜🎜#L'auteur pense que nous devrions utiliser plusieurs Redis. Ces nœuds sont complètement indépendants et n'ont pas besoin d'utiliser la réplication ou. tout autre Pour les systèmes qui coordonnent les données, le processus d'acquisition de verrous par plusieurs systèmes Redis se déroule comme suit : #🎜🎜#
        #🎜🎜## 🎜🎜#Obtenez l'heure actuelle du serveur en millisecondes#🎜🎜##🎜🎜##🎜🎜##🎜🎜#Essayez d'utiliser la même clé et la même valeur aléatoire pour acquérir le verrou, qui doit être utilisé pour chaque machine lors de l'acquisition du lock Un délai d'expiration, par exemple, si le délai d'expiration du verrou est de 10 secondes, le délai d'expiration pour acquérir un verrou de nœud unique doit être d'environ 5 à 50 millisecondes. Le but est de garantir que le client est connecté à la machine défaillante et gaspille plus. temps! Si les données ne sont pas obtenues dans le délai imparti, le nœud sera abandonné et le nœud suivant sera obtenu jusqu'à ce que tous les nœuds soient obtenus ! #🎜🎜##🎜🎜##🎜🎜##🎜🎜#Une fois l'acquisition terminée, obtenez l'heure actuelle moins l'heure obtenue à l'étape 1, si et seulement si plus de la moitié des clients acquièrent avec succès et l'heure pour l'acquisition du verrou est inférieure au délai d'expiration du montant du verrouillage, cela prouve que le verrouillage est efficace ! #🎜🎜##🎜🎜##🎜🎜##🎜🎜#Après l'acquisition du verrou, le délai d'expiration du verrouillage est égal à Le temps effectif défini - le temps nécessaire pour acquérir la serrure#🎜🎜##🎜🎜##🎜🎜##🎜🎜#Si plus de la moitié des machines qui acquièrent la serrure ne sont pas satisfaites , ou le délai d'expiration du verrouillage a été calculé. S'il y a une opération anormale telle qu'un nombre négatif, le système tentera de déverrouiller toutes les instances. Même si certaines instances ne parviennent pas à acquérir le verrou, elles seront quand même tentées de se déverrouiller ! #🎜🎜##🎜🎜##🎜🎜##🎜🎜#Libérez le verrou, libérez simplement le verrou dans toutes les instances, que le client pense ou non pouvoir verrouiller avec succès l'instance donnée. #🎜🎜##🎜🎜##🎜🎜##🎜🎜# 4. Mais Redlock peut-il vraiment résoudre le problème ? #🎜🎜##🎜🎜#Martin Kleppmann a publié un article tâche, Redlock ne peut garantir la sécurité de la serrure ! #🎜🎜##🎜🎜# Il estime qu'il n'y a que deux utilisations des verrous#🎜🎜##🎜🎜##🎜🎜##🎜🎜##🎜🎜#Améliorez l'efficacité et utilisez des verrous pour vous assurer qu'une tâche ne se termine pas doivent être exécutés deux fois. Par exemple (calcul très coûteux) #🎜🎜##🎜🎜##🎜🎜##🎜🎜#Pour garantir l'exactitude, un mécanisme de verrouillage est utilisé pour garantir que les tâches sont effectuées dans un ordre de processus normal afin d'éviter que deux nœuds ne traitent le mêmes données en même temps Effectuez des opérations entraînant des conflits de fichiers et des pertes de données. #🎜🎜##🎜🎜##🎜🎜##🎜🎜##🎜🎜#Pour la première raison, nous avons une certaine tolérance pour les verrous Même si deux nœuds fonctionnent en même temps, l'impact sur le système sera. petit, cela coûte simplement plus de calculs et n’a aucun impact supplémentaire. À l'heure actuelle, l'utilisation d'un seul point de Redis peut très bien résoudre le problème. Il n'est pas nécessaire d'utiliser RedLock pour maintenir autant d'instances Redis et augmenter le coût de maintenance du système. #🎜🎜#

        1. Inconvénients causés par le délai d'attente des verrous distribués

        Mais pour le deuxième scénario, il est plus prudent, car il est susceptible d'impliquer certaines transactions monétaires si le verrou échoue et que deux nœuds le traitent en même temps. sera une corruption de fichiers, une perte de données, une incohérence permanente ou une perte monétaire !

        Supposons un scénario dans lequel nous avons deux clients. Chaque client doit obtenir un verrou avant de pouvoir enregistrer des données dans la base de données. Quels problèmes se produiront si nous utilisons l'algorithme RedLock pour l'implémenter ? Dans RedLock, afin d'éviter les blocages, le verrou a un délai d'expiration, mais Martin pense que ce n'est pas sûr ! L'organigramme ressemble à ceci ! Martin 认为这是不安全的!该流程图类似于这样!

        Comment utiliser Redis pour verrouiller les ressources  

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

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

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

        Comment utiliser Redis pour verrouiller les ressources  

        客户端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

    Comment utiliser Redis pour verrouiller les ressources
    Comment utiliser Redis pour verrouiller les ressourcesUne fois que le client 1 a obtenu le verrou, il a commencé l'exécution. À mi-chemin de l'exécution, un GC complet s'est produit dans le système, le service système a été suspendu et le verrouillage a expiré après un certain temps.

    Une fois que le client 2 a attendu l'expiration du verrouillage du client 1, il obtient le verrou avec succès et commence à effectuer l'opération d'entreposage. Une fois terminé, le client 1 termine le GC complet et effectue une autre opération d'entreposage ! C'est dangereux ! Comment le résoudre ? Martin a proposé un mécanisme d'implémentation similaire au verrouillage optimiste. L'image d'exemple est la suivante : Comment utiliser Redis pour verrouiller les ressources

    🎜Après que le client 1 ait été suspendu pendant une longue période, le client 2 a acquis le verrou et a commencé à écrire la bibliothèque, portant le jeton 34 en même temps. Après avoir écrit la bibliothèque, le client 1 s'est réveillé et a commencé. pour entrer. Opération de bibliothèque, mais comme le jeton transporté est 33, ce qui est inférieur au dernier jeton, la soumission est rejetée ! 🎜🎜Même s'il y a un problème avec le système qui provoque un blocage, cette idée semble complète pour garantir que les données sont toujours traitées correctement. Mais réfléchissez-y : 🎜
    • 🎜Si seulement si votre jeton est supérieur à tous les jetons passés, la banque de données peut si elle accepte toujours les écritures , c'est une zone de stockage linéarisable, ce qui équivaut à utiliser une base de données pour implémenter un système de verrouillage distribué, donc le rôle de RedLock devient minime ! Vous n’avez même pas besoin d’utiliser Redis pour garantir les verrous distribués ! 🎜
    🎜2.RedLock dépend fortement de l'horloge système🎜🎜Rappelez les étapes de l'algorithme Redlock pour obtenir le verrou, vous constaterez que l'efficacité du verrou est lié au système actuel L'horloge est fortement dépendante, nous supposons : 🎜🎜Nous avons, A B C D E cinq nœuds redis : 🎜
    1. 🎜Client 1 obtient le verrouillage des nœuds A, B, C. D et E ne sont pas accessibles en raison de problèmes de réseau. 🎜
    2. 🎜L'horloge du nœud C avance, provoquant l'expiration du verrou. 🎜
    3. 🎜Le client 2 acquiert le verrou des nœuds C, D et E. A et B ne sont pas accessibles en raison de problèmes de réseau. 🎜
    4. 🎜Maintenant, les clients 1 et 2 pensent qu'ils détiennent le verrou. 🎜
    🎜Un problème similaire peut survenir si C plante et redémarre immédiatement avant de conserver le verrouillage sur le disque. 🎜🎜Martin estime que le saut temporel du système vient principalement de deux aspects (et de la solution donnée par l'auteur) : 🎜
    1. 🎜 Humain modification. 🎜
    • 🎜Que pouvez-vous dire sur la modification humaine ? Il n’existe aucun moyen d’empêcher les gens de provoquer des destructions. 🎜
  • 🎜Reçu une mise à jour de l'horloge de saut du service NTP. 🎜
    • 🎜Le personnel d'exploitation et de maintenance doit faire face au problème de l'acceptation par NTP des mises à jour d'horloge pas à pas. Lorsque vous devez mettre à jour le temps d'étape sur le serveur, vous devez procéder par petites étapes et exécuter rapidement. Modifiez plusieurs fois et la durée de chaque mise à jour doit être aussi courte que possible. 🎜
    🎜3. Basé sur un langage de programmation pour combler les lacunes causées par le délai d'attente des verrous distribués🎜🎜Nous passons en revue 1 point de vue et approfondissons la cause profonde de ce résumé. défaut afin de résoudre En raison de l'échec du verrouillage causé par le temps d'arrêt du système, un délai d'expiration est imposé au verrou. Dans des circonstances anormales, le temps d'exécution du programme (entreprise) est supérieur au délai d'expiration du verrou, ce qui provoque une série de problèmes. Pouvons-nous considérer cet aspect ? Alors, comment utiliser un programme pour résoudre une situation aussi morte ? 🎜🎜Nous pouvons garantir que le temps d'exécution du programme métier est absolument inférieur au délai d'expiration du verrouillage, afin d'éviter le problème selon lequel le délai d'expiration du verrouillage est inférieur au temps métier🎜🎜Dans le langage Java, redisson implémente une méthode pour garantir que le délai d'expiration du verrou est absolument supérieur au mécanisme du temps d'exécution du programme métier. Officiellement appelé mécanisme de surveillance (Watchdog), son principe principal est qu'une fois que le programme a acquis avec succès le verrou, il créera un thread enfant pour renouveler continuellement le verrou jusqu'à ce que le verrou soit libéré ! Son diagramme schématique ressemble à peu près à ceci : 🎜🎜🎜 🎜🎜redisson utilise un thread démon pour renouveler le verrou. (Le rôle du thread démon : lorsque le 🎜thread principal🎜 est détruit, il sera détruit avec le 🎜thread principal🎜.) Pour empêcher le thread de continuer à se renouveler. une fois le programme arrêté, provoquant la mort de Lock ! 🎜

    De plus, Redisson implémente et optimise également l'algorithme RedLock, le verrouillage équitable, le verrouillage réentrant, la chaîne et d'autres opérations, rendant la mise en œuvre du verrouillage distribué Redis plus facile et plus efficace !

    Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

    Étiquettes associées:
    source:yisu.com
    Déclaration de ce site Web
    Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
    Tutoriels populaires
    Plus>
    Derniers téléchargements
    Plus>
    effets Web
    Code source du site Web
    Matériel du site Web
    Modèle frontal
    À propos de nous Clause de non-responsabilité Sitemap
    Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!