Dieser Artikel vermittelt Ihnen relevantes Wissen über Redis und stellt hauptsächlich vor, was verteilte Sperren sind. Wie implementiert Redis verteilte Sperren? Welche Voraussetzungen müssen erfüllt sein? Werfen wir einen Blick nach unten. Ich hoffe, dass es Freunden in Not hilfreich sein wird.
Verteilte Sperren: Sperren, die für mehrere Prozesse in einem verteilten System oder Clustermodus sichtbar sind und sich gegenseitig ausschließen.
Bedingungen, die verteilte Sperren erfüllen sollten:
Manuelle Freigabe
SET resource_name my_random_value NX PX 30000
my_random_value: Zufälliger Wert, der Zufallswert jedes Threads ist unterschiedlich und wird zur Überprüfung beim Aufheben der Sperre verwendet
public interface ILock extends AutoCloseable { /** * 尝试获取锁 * * @param timeoutSec 锁持有的超时时间,过期后自动释放 * @return true代表获取锁成功;false代表获取锁失败 */ boolean tryLock(long timeoutSec); /** * 释放锁 * @return */ void unLock(); }
Thread 1, der die Sperre hält, ist innerhalb der Sperre blockiert. Zu diesem Zeitpunkt wird die Sperre automatisch freigegeben 2 versucht, die Sperre zu erhalten, und dann führt Thread 2 die Sperre aus. Während des Vorgangs reagiert Thread 1, setzt die Ausführung fort und erreicht die Sperre, die zu Thread 2 gehören sollte Dies ist der Fall, wenn die Sperre versehentlich gelöscht wird.
public class SimpleRedisLock { private final StringRedisTemplate stringRedisTemplate; private final String name; public SimpleRedisLock(StringRedisTemplate stringRedisTemplate, String name) { this.stringRedisTemplate = stringRedisTemplate; this.name = name; } private static final String KEY_PREFIX = "lock:"; @Override public boolean tryLock(long timeoutSec) { //获取线程标识 String threadId = Thread.currentThread().getId(); //获取锁 Boolean success = stringRedisTemplate.opsForValue() .setIfAbsent(KEY_PREFIX + name, threadId, timeoutSec, TimeUnit.SECONDS); return Boolean.TRUE.equals(success); } @Override public void unLock() { //通过del删除锁 stringRedisTemplate.delete(KEY_PREFIX + name); } @Override public void close() { unLock(); } }
Problemanalyse:
Der obige Code zum Freigeben der Sperre weist immer noch das Problem der versehentlichen Sperrenlöschung auf, wenn Thread 1 erhalten wird Die Thread-ID in der Sperre wird anhand der Identifizierung als eigene Sperre beurteilt. Zu diesem Zeitpunkt wird die Sperre automatisch aufgehoben, wenn sie abläuft. Es kommt vor, dass Thread 2 versucht, die Sperre zu erhalten Zu diesem Zeitpunkt führt Thread 1 noch den Vorgang zum Aufheben der Sperre aus, was zum versehentlichen Löschen der von Thread 2 gehaltenen Sperre führt.Der Grund dafür ist, dass der durch Java-Code implementierte Sperrfreigabeprozess keine atomare Operation ist und Probleme mit der Thread-Sicherheit aufweist.
Lösung:
Redis bietet eine Lua-Skriptfunktion. Durch das Schreiben mehrerer Redis-Befehle in einem Skript kann die Atomizität der Ausführung mehrerer Befehle sichergestellt werden. Version 3: Lua-Skript aufrufen, um verteilte Sperre umzuwandelnpublic class SimpleRedisLock { private final StringRedisTemplate stringRedisTemplate; private final String name; public SimpleRedisLock(StringRedisTemplate stringRedisTemplate, String name) { this.stringRedisTemplate = stringRedisTemplate; this.name = name; } private static final String KEY_PREFIX = "lock:"; private static final String ID_PREFIX = UUID.randomUUID().toString(true) + "-"; @Override public boolean tryLock(long timeoutSec) { //获取线程标识 String threadId = ID_PREFIX + Thread.currentThread().getId(); //获取锁 Boolean success = stringRedisTemplate.opsForValue() .setIfAbsent(KEY_PREFIX + name, threadId, timeoutSec, TimeUnit.SECONDS); return Boolean.TRUE.equals(success); } @Override public void unLock() { // 获取线程标示 String threadId = ID_PREFIX + Thread.currentThread().getId(); // 获取锁中的标示 String id = stringRedisTemplate.opsForValue().get(KEY_PREFIX + name); // 判断标示是否一致 if(threadId.equals(id)) { // 释放锁 stringRedisTemplate.delete(KEY_PREFIX + name); } } @Override public void close() { unLock(); } }
Das obige ist der detaillierte Inhalt vonLassen Sie uns über das Prinzip verteilter Sperren sprechen und wie Redis verteilte Sperren implementiert. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!