Les verrous distribués ont généralement trois méthodes de mise en œuvre : 1. Verrouillage optimiste de la base de données ; 2. Verrouillage distribué basé sur Redis 3. Verrouillage distribué basé sur ZooKeeper ;
Nous présentons ici l'implémentation de verrous distribués basés sur Redis.
Propriétés des serrures distribuées :
Fiabilité. Tout d'abord, afin de garantir que les verrous distribués soient disponibles, nous devons au moins nous assurer que la mise en œuvre du verrou remplit simultanément les quatre conditions suivantes :
Exclusivité mutuelle . A tout moment, un seul client peut détenir le verrou.
Aucune impasse ne se produira. Même si un client plante alors qu'il maintient le verrou sans le déverrouiller activement, il est garanti que d'autres clients pourront ensuite le verrouiller.
a tolérance aux pannes. Tant que la plupart des nœuds Redis fonctionnent normalement, le client peut se verrouiller et se déverrouiller.
Pour dénouer la cloche, vous devez attacher la cloche. Le verrouillage et le déverrouillage doivent être effectués par le même client. Le client lui-même ne peut pas déverrouiller le verrou ajouté par d'autres.
Dépendances des composants d'implémentation du code
Nous devons d'abord introduire les composants open source Jedis via Maven et ajouter le code suivant au fichier pom.xml :
<dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency>
Position correcte pour verrouiller le code
Parler ne coûte pas cher, montre-moi le code. Montrez d'abord le code, puis expliquez lentement pourquoi il est implémenté de cette façon :
public class RedisTool { private static final String LOCK_SUCCESS = "OK"; private static final String SET_IF_NOT_EXIST = "NX"; private static final String SET_WITH_EXPIRE_TIME = "PX"; /** * 尝试获取分布式锁 * @param jedis Redis客户端 * @param lockKey 锁 * @param requestId 请求标识 * @param expireTime 超期时间 * @return 是否获取成功 */ public static boolean tryGetDistributedLock(Jedis jedis, String lockKey, String requestId, int expireTime) { String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime); if (LOCK_SUCCESS.equals(result)) { return true; } return false; } }
Comme vous pouvez le voir, nous n'avons besoin que d'une seule ligne de code pour verrouiller : jedis.set(String key, String value, String nxxx , String expx, int time ), cette méthode set() a un total de cinq paramètres formels :
Le premier est key Nous utilisons key comme verrou car key est unique.
Le deuxième est la valeur. Ce que nous transmettons est requestId. De nombreux enfants peuvent ne pas comprendre. N'est-il pas suffisant d'avoir une clé comme serrure ? La raison en est que lorsque nous avons parlé de fiabilité ci-dessus, le verrou distribué doit remplir la quatrième condition pour déverrouiller la cloche et la personne qui tient la cloche doit être celle qui a attaché la cloche. En attribuant la valeur à requestId, nous saurons quelle requête. ajouté le verrou Lors du déverrouillage Ensuite, vous pouvez avoir une base. requestId peut être généré à l’aide de la méthode UUID.randomUUID().toString().
Le troisième est nxxx. Ce paramètre que nous remplissons est NX, ce qui signifie SET IF NOT EXIST, c'est-à-dire que lorsque la clé n'existe pas, nous effectuons l'opération set si la clé existe déjà, non ; l'opération est effectuée ;
Le quatrième est expx. Ce paramètre que nous transmettons est PX, ce qui signifie que nous voulons ajouter un paramètre d'expiration à cette clé. L'heure spécifique est déterminée par le cinquième paramètre.
Le cinquième paramètre est le temps, qui correspond au quatrième paramètre et représente le délai d'expiration de la clé.
En général, exécuter la méthode set() ci-dessus ne conduira qu'à deux résultats : 1. Il n'y a actuellement aucun verrou (la clé n'existe pas), puis effectuez l'opération de verrouillage et définissez une période de validité pour le lock et value représente le client verrouillé. 2. Le verrou existe déjà, aucune opération n'est effectuée.
Notre code de verrouillage répond aux trois conditions décrites dans notre section fiabilité. Tout d'abord, set() ajoute le paramètre NX, qui garantit que si la clé existe déjà, la fonction ne sera pas appelée avec succès, c'est-à-dire qu'un seul client peut détenir le verrou, satisfaisant ainsi l'exclusion mutuelle. Deuxièmement, puisque nous définissons un délai d'expiration pour le verrou, même si le support du verrou tombe en panne plus tard et n'est pas déverrouillé, le verrou sera automatiquement déverrouillé (c'est-à-dire que la clé sera supprimée) car le délai d'expiration est atteint et il n'y a pas de blocage. se produira. Enfin, comme nous attribuons une valeur à requestId, qui représente l'identification de la demande du client verrouillé, lorsque le client est déverrouillé, il peut être vérifié s'il s'agit du même client. Puisque nous considérons uniquement le scénario de déploiement autonome de Redis, nous ne considérerons pas la tolérance aux pannes pour le moment.
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!