La position actuelle:Accueil du site>Comment renouveler automatiquement les serrures distribuées redis (solution classique)

Comment renouveler automatiquement les serrures distribuées redis (solution classique)

2022-07-23 00:14:36Les dragons montent des officiels.

Table des matières

Redis Réaliser des serrures distribuées

1、Questions

1.1.Renouvellement automatique

2.Chien de garde

2.1.Comment les chiens de garde renouvellent automatiquement

2.1.1Principe de renouvellement


Redis Réaliser des serrures distribuées

  • Spécifiez un key Comme marque de verrouillage,Dépôt Redis Moyenne,Spécifiez un Un identifiant utilisateur unique comme value.

  • Quand key La valeur ne peut être définie que lorsqu'elle n'existe pas,Assurez - vous qu'un seul processus client obtient le verrouillage en même temps,Satisfaire aux caractéristiques d'exclusion mutuelle.

  • Fixer un délai d'expiration,Empêcher que cela ne puisse être supprimé en raison d'une exception au système key,Satisfait aux caractéristiques anti - blocage.

  • Vous devez effacer ceci après avoir traité l'affaire key Pour libérer la serrure,Effacer key Vérification requise value Valeur,Besoin de satisfaire que seule la personne qui a ajouté la serrure peut libérer la serrure .

1、Questions

Si cette serrure expire30Secondes,Mais les affaires ont dépassé30Secondes,Par exemple,40Secondes,Quand les affaires tournent30En quelques secondes,La serrure est expirée.,Les autres clients ont cette serrure,Comment faire?

On peut fixer un délai raisonnable,Permettre aux entreprises de compléter la logique d'entreprise dans ce délai,Mais...LockTimeLe réglage de n'était pas facile.

  • LockTimeRéglage trop petit,La probabilité que la serrure s'éteigne automatiquement augmente,La probabilité de défaillance anormale de la serrure augmente également;

  • LockTimeRéglage trop grand,En cas d'exception au service qui ne libère pas correctement la serrure,Plus il faudra de temps pour que cette serrure anormale se produise.

Nous ne pouvons configurer que par expérience,Une valeur acceptable,En gros, c'est le temps moyen que ce service a pris dans l'histoire, un peu plusbuff.Dans l'ensemble,Il n'est pas facile de fixer un délai d'expiration raisonnable

On peut aussi ne pas fixer de délai d'expiration,Déverrouiller une fois l'opération terminée,Mais si le client a une fin anormale ou un temps d'arrêt,Alors cette serrure ne se déverrouillera pas,C'est devenu une impasse;

1.1.Renouvellement automatique

On peut d'abord régler la serrureLockTime,Puis lancez un Thread de démon,Laissez le thread du démon,Pour réinitialiser cette serrureLockTime.

Ça a l'air simple,Mais ce n'est pas facile à réaliser

  • Comme pour le déverrouillage,Nous devons d'abord déterminer s'il y a un changement dans le client hold Lock.Sinon, celui qui tient la serrure,Les fils du démon vont réinitialiser la serrureLockTime.

  • Le thread du démon doit réinitialiser la serrure dans un délai raisonnableLockTime,Sinon, les ressources seront gaspillées.On ne peut pas continuer sans bouger.

  • Si le thread qui détient la serrure a fini de traiter l'affaire,Alors le thread du démon devrait aussi être détruit.L'opération n'est pas terminée,Le gardien est toujours là,Gaspiller des ressources.

2.Chien de garde

RedissonC'est ce mécanisme qui permet le renouvellement automatique:

 Redissson tryLock

public boolean tryLock(long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException {
        long time = unit.toMillis(waitTime);
        long current = System.currentTimeMillis();
        long threadId = Thread.currentThread().getId();
        // 1.Essayer d'obtenir une serrure
        Long ttl = tryAcquire(leaseTime, unit, threadId);
        // lock acquired
        if (ttl == null) {
            return true;
        }

        // Le temps nécessaire pour demander un verrouillage est égal ou supérieur au temps d'attente maximal,La demande de verrouillage a échoué.
        time -= System.currentTimeMillis() - current;
        if (time <= 0) {
            acquireFailed(threadId);
            return false;
        }

        current = System.currentTimeMillis();

        /**
         * 2.Événement de libération des serrures d'abonnement,Et à travers await Méthode bloquée en attendant la libération de la serrure,Résoudre efficacement le problème des demandes de verrouillage invalides qui gaspillent des ressources:
         * Basé sur la quantité d'informations,Lorsque la serrure est occupée par d'autres ressources,Le thread actuel passe par Redis De channel Événement de libération de la serrure d'abonnement,Une fois le verrouillage libéré, un message est envoyé pour informer les Threads en attente de la concurrence.
         *
         * Quand this.await Retour false,Indique que le temps d'attente a dépassé le temps d'attente maximal pour obtenir la serrure,Échec de la désabonnement et du retour pour obtenir le verrouillage.
         * Quand this.await Retour true,Entrez le cycle pour essayer d'obtenir la serrure.
         */
        RFuture<RedissonLockEntry> subscribeFuture = subscribe(threadId);
        // await L'intérieur de la méthode est CountDownLatch Pour obtenir un blocage,Accès subscribe Résultats de l'exécution asynchrone(Appliqué Netty De Future)
        if (!subscribeFuture.await(time, TimeUnit.MILLISECONDS)) {
            if (!subscribeFuture.cancel(false)) {
                subscribeFuture.onComplete((res, e) -> {
                    if (e == null) {
                        unsubscribe(subscribeFuture, threadId);
                    }
                });
            }
            acquireFailed(threadId);
            return false;
        }

        try {
            // Calculer le temps total nécessaire pour obtenir la serrure,Si le temps d'attente maximal est supérieur ou égal à,Impossible d'obtenir la serrure.
            time -= System.currentTimeMillis() - current;
            if (time <= 0) {
                acquireFailed(threadId);
                return false;

              }

            /**
             * 3.Après avoir reçu le signal de déverrouillage,Dans le délai maximum d'attente,Essayez d'obtenir la serrure encore et encore
             * Obtenir la serrure avec succès,Je reviens tout de suite true,
             * Si la serrure n'a pas été obtenue dans le délai d'attente maximal,L'acquisition de la serrure est considérée comme un échec,Retour false Fin du cycle
             */
            while (true) {
                long currentTime = System.currentTimeMillis();

                // Essayez encore d'obtenir la serrure
                ttl = tryAcquire(leaseTime, unit, threadId);
                // lock acquired
                if (ttl == null) {
                    return true;
                }
                // Si le temps d'attente maximal est dépassé, il retourne false Fin du cycle,Impossible d'obtenir la serrure
                time -= System.currentTimeMillis() - currentTime;
                if (time <= 0) {
                    acquireFailed(threadId);
                    return false;
                }

                /**
                 * 6.Blocage de la serrure d'attente(Signal de passage(Serrure partagée)Blocage,Attendez le message de déverrouillage):
                 */
                currentTime = System.currentTimeMillis();
                if (ttl >= 0 && ttl < time) {
                    //Si le temps restant(ttl)Moins dewait time ,Juste là. ttl Dans le temps,DeEntryLe sémaphore de(À moins qu'il ne soit interrompu ou qu'il n'y ait pas de licence disponible).
                    getEntry(threadId).getLatch().tryAcquire(ttl, TimeUnit.MILLISECONDS);
                } else {
                    //Alors c'est justewait time L'attente dans le temps peut passer par le sémaphore
                    getEntry(threadId).getLatch().tryAcquire(time, TimeUnit.MILLISECONDS);
                }

                // Mettre à jour le temps d'attente restant(Temps d'attente maximum-Temps de blocage écoulé)
                time -= System.currentTimeMillis() - currentTime;
                if (time <= 0) {
                    acquireFailed(threadId);
                    return false;
                }
            }
        } finally {
            // 7.Avec ou sans serrure,Pour désabonner les messages de déverrouillage
            unsubscribe(subscribeFuture, threadId);
        }
        return get(tryLockAsync(waitTime, leaseTime, unit));
    }

  • Essayer d'obtenir une serrure,Retour null Cela signifie que le verrouillage est réussi,Renvoie une valeur numérique,La serrure existe déjà,ttl Pour la durée de vie restante de la serrure.

  • Si le client 2 Le processus n'a pas réussi à obtenir le verrouillage,Alors, utilisez le client 2 Les fils de id(En fait, c'est essentiellement le processus id)Adoption Redis De channel Événements pour la libération des serrures d'abonnement.Si la notification de l'événement de libération de la serrure n'est pas attendue pendant l'attente,Impossible d'obtenir la serrure lorsque le temps d'attente maximal est dépassé,Retour false,C'est la 39 Code de ligne.Si vous attendez la notification de l'événement de libération de la serrure,Commence un cycle de retry constant pour obtenir la serrure.

  • Essayez d'obtenir la serrure à chaque fois dans le cycle,Et obtenir la durée de vie restante des serrures existantes.Si vous avez la serrure en retry,Retour direct.Si la serrure est toujours occupée,Alors attendez le message pour libérer la serrure,La réalisation concrète utilise des sémaphores Semaphore Pour bloquer les fils,Lorsque la serrure est libérée et qu'un message de libération de la serrure est affiché,Sémaphore release() La méthode est appelée,Un thread dans la file d'attente bloquée par le sémaphore peut maintenant continuer à essayer d'obtenir le verrouillage.

  • Lorsque la serrure est occupée,Le processus d'attente pour obtenir la serrure ne passe pas par un while(true) Boucle morte pour obtenir la serrure,Mais en utilisant Redis Mécanisme d'abonnement à la publication pour,Adoption await Méthode pour bloquer le processus en attente de verrouillage,Résoudre efficacement le problème des demandes de verrouillage invalides qui gaspillent des ressources.

2.1.Comment les chiens de garde renouvellent automatiquement

RedissonMécanisme de chien de garde, Tant que le client est verrouillé avec succès,Et ça déclenche un Watch Dog.

  • leaseTime Ça doit l'être. -1 Ça s'ouvrira Watch Dog Mécanismes,Si nécessaire Watch Dog Le mécanisme doit utiliser le temps de verrouillage par défaut de 30s.

  • Si vous Personnalisez votre temps,Au - delà de ce temps,La serrure se libère,Pas de renouvellement automatique.

2.1.1Principe de renouvellement

Le principe du renouvellement est en fait utiliséluaScript,Réinitialiser le temps de verrouillage à30s.

private void scheduleExpirationRenewal(long threadId) {
    ExpirationEntry entry = new ExpirationEntry();
    ExpirationEntry oldEntry = EXPIRATION_RENEWAL_MAP.putIfAbsent(getEntryName(), entry);
    if (oldEntry != null) {
        oldEntry.addThreadId(threadId);
    } else {
        entry.addThreadId(threadId);
        renewExpiration();
    }
}

protected RFuture<Boolean> renewExpirationAsync(long threadId) {
    return commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,
            "if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then " +
                "redis.call('pexpire', KEYS[1], ARGV[1]); " +
                "return 1; " +
            "end; " +
            "return 0;",
        Collections.<Object>singletonList(getName()),
        internalLockLeaseTime, getLockName(threadId));
}

Watch Dog Le mécanisme est en fait un fil de tâche de synchronisation de fond,Après avoir obtenu la serrure avec succès,Placez le fil qui tient la serrure dans un RedissonLock.EXPIRATION_RENEWAL_MAPÀ l'intérieur,Et puis à chaque fois 10 Secondes (internalLockLeaseTime / 3) Vérifiez,Si le client Toujours avec la serrure key(Déterminer si le client détient toujours key,En fait, c'est la traversée. EXPIRATION_RENEWAL_MAP Le fil intérieur id Et puis selon le fil id Vas - y. Redis Central check,S'il existe, il sera prolongé key Le temps),Alors ça va continuer à allonger la serrure key La durée de vie de.

Si le service s'arrête,Watch Dog Il n'y a plus de fils de mécanisme,Il n'y aura pas de prolongation pour le moment key Date d'expiration,On y est. 30s Il expirera automatiquement après,D'autres fils peuvent obtenir la serrure.

Mentions de copyright
Auteur de cet article [Les dragons montent des officiels.],Réimpression s’il vous plaît apporter le lien vers l’original, merci
https://fra.chowdera.com/2022/204/202207221332102037.html

Recommandé au hasard