Redis ist ein In-Memory-Schlüsselwertspeichersystem, das eine Vielzahl von Datenstrukturen unterstützt, einschließlich Zeichenfolgen, Hashes, Listen usw. Redis bietet zwei Sperrmechanismen, nämlich optimistisches Sperren und pessimistisches Sperren.
Optimistische Sperre ist eine optimistische Parallelitätskontrollstrategie. Sie geht davon aus, dass die Daten in den meisten Fällen nicht von anderen Threads belegt werden. Daher wird die Sperre nicht jedes Mal erfasst, wenn die Daten geändert werden müssen, sondern direkt . Überarbeiten. In Redis kann optimistisches Sperren über die Befehle WATCH und CAS implementiert werden. Der Befehl WATCH wird zum Überwachen eines oder mehrerer Schlüssel verwendet, und der Befehl CAS dient zum Überprüfen und Aktualisieren des Werts des Schlüssels.
Wenn beispielsweise ein Zähler mit dem Schlüsselnamenzähler vorhanden ist, müssen mehrere Clients damit arbeiten. Sie können optimistisches Sperren verwenden, um den Zählerschlüssel vor jeder Client-Operation zu überwachen, indem Sie den WATCH-Befehl
WATCH counter current_count = GET counter new_count = current_count + 1 MULTI SET counter new_count EXEC
ausführen. Bevor der EXEC-Befehl ausgeführt wird, verwenden Sie dann den GET-Befehl, um den Wert des Zählerschlüssels erneut abzurufen und ihn mit dem vorherigen zu vergleichen erhaltene Werte werden verglichen. Wenn die Werte gleich sind, bedeutet dies, dass während des Zeitraums kein anderer Client den Zählerschlüssel geändert hat. Zu diesem Zeitpunkt können Sie den CAS-Befehl verwenden, um den neuen Wert auf den Zählerschlüssel festzulegen. Wenn die Werte unterschiedlich sind, bedeutet dies, dass andere Clients den Zählerschlüssel in diesem Zeitraum geändert haben und der Vorgang erneut ausgeführt werden muss.
GET counter
Pessimistische Sperre ist eine pessimistische Parallelitätskontrollstrategie. Sie geht davon aus, dass die Daten in den meisten Fällen von anderen Threads belegt werden. Daher wird jedes Mal, wenn die Daten geändert werden müssen, zuerst die Sperre erworben, um dies sicherzustellen Es gibt keine anderen Threads, die auf diese Daten zugreifen können. In Redis kann pessimistisches Sperren über den WATCH-Befehl implementiert werden, der einen oder mehrere Schlüssel überwachen kann. Wenn sich der Wert eines überwachten Schlüssels während der Transaktionsausführung ändert, wird die gesamte Transaktion zurückgesetzt.
Immer noch das obige Beispiel
WATCH counter current_count = GET counter new_count = current_count + 1 MULTI SET counter new_count EXEC
Wenn andere Clients den Zählerschlüssel während der Ausführung der Transaktion ändern, wird die gesamte Transaktion zurückgesetzt und muss erneut ausgeführt werden.
Obwohl pessimistische Sperren den Vorteil der Datenkonsistenz gewährleisten können, besteht ihr Nachteil darin, dass zuerst die Sperre erworben werden muss, was zu einer Thread-Blockierung führen und dadurch die Parallelitätsleistung beeinträchtigen kann.
Angenommen, es gibt eine E-Commerce-Plattform, auf der Benutzer Waren kaufen können. Um sicherzustellen, dass die Reduzierung des Produktbestands konsistent ist, kann der optimistische Sperrmechanismus von Redis verwendet werden, um dies zu erreichen.
Zuerst müssen wir die Bestandsinformationen jedes Artikels in Redis mithilfe einer Hash-Datenstruktur speichern, zum Beispiel:
Wenn der Benutzer dann in der Geschäftslogik einen Artikel kauft, müssen die folgenden Schritte ausgeführt werden:
Verwenden Sie den WATCH-Befehl, um Produktbestandsschlüssel zu überwachen, z. B. stock:sku001;
Verwenden Sie den GET-Befehl, um die aktuelle Produktbestandsmenge abzurufen.
Überprüfen Sie, ob der Produktbestand ausreichend ist. Geben Sie direkt eine Fehlermeldung zurück.
Berechnen Sie die neue Lagerbestandsmenge und starten Sie eine Transaktion.
Verwenden Sie den HSET-Befehl, um die neue Lagerbestandsmenge in Redis zu speichern. Wenn andere Kunden während der Ausführung den Produktbestand ändern, wird die Transaktion zurückgesetzt und muss erneut ausgeführt werden.
Das Folgende ist ein Beispielcode, der mit Spring Boot implementiert wurde:
@Service public class OrderService { private final RedisTemplate<String, Integer> redisTemplate; @Autowired public OrderService(RedisTemplate<String, Integer> redisTemplate) { this.redisTemplate = redisTemplate; } public void placeOrder(String sku, int quantity) { String stockKey = "stock:" + sku; while (true) { // 监视商品库存键,以便在事务开始前检测是否有其他客户端修改了库存 redisTemplate.watch(stockKey); // 获取当前库存数量 int currentStock = redisTemplate.opsForHash().get(stockKey, sku); // 检查库存是否足够 if (currentStock < quantity) { // 库存不足,放弃事务并抛出异常 redisTemplate.unwatch(); throw new RuntimeException("Out of stock"); } // 计算新的库存数量 int newStock = currentStock - quantity; // 开始事务 redisTemplate.multi(); // 更新库存数量 redisTemplate.opsForHash().put(stockKey, sku, newStock); // 提交事务 List<Object> results = redisTemplate.exec(); // 如果事务执行成功,则退出循环 if (results != null) { break; } // 如果事务执行失败,则重试 } } }
Beispiel für eine pessimistische Sperre
Neben der optimistischen Sperre unterstützt Redis auch eine pessimistische Sperre, die durch Setzen der Flags NX (Not Exist) oder XX (Exist) erreicht werden kann. Wenn beispielsweise das NX-Flag auf „true“ gesetzt ist und die Sperre nicht vorhanden ist, wird „OK“ zurückgegeben. Wenn die Sperre bereits vorhanden ist, wird „null“ zurückgegeben, was darauf hinweist, dass die Sperre nicht erfasst werden konnte. Wenn das XX-Flag hingegen auf „true“ gesetzt ist und die Sperre bereits vorhanden ist, wird „OK“ zurückgegeben, was darauf hinweist, dass die Sperre erfolgreich erworben wurde .
@Service public class OrderService { private final RedisTemplate<String, String> redisTemplate; @Autowired public OrderService(RedisTemplate<String, String> redisTemplate) { this.redisTemplate = redisTemplate; } public void placeOrder(String sku, int quantity) { String lockKey = "lock:" + sku; // 尝试获取锁,如果锁已经存在,说明有其他线程正在执行相关操作 Boolean locked = redisTemplate.opsForValue().setIfAbsent(lockKey, "locked"); if (!locked) { // 获取锁失败,抛出异常 throw new RuntimeException("Unable to acquire lock"); } // 设置锁的过期时间,防止锁被一直占用 redisTemplate.expire(lockKey, 10, TimeUnit.SECONDS); try { // 执行订单创建、扣减库存等操作 } finally { // 释放锁 redisTemplate.delete(lockKey); } } }
Im obigen Code verwenden wir die setIfAbsent-Methode, um zu versuchen, die Sperre zu erhalten, was bedeutet, dass andere Threads verwandte Vorgänge ausführen Zu diesem Zeitpunkt wird „false“ zurückgegeben, was darauf hinweist, dass die Sperrenerfassung fehlgeschlagen ist. Andernfalls wird „true“ zurückgegeben, was darauf hinweist, dass die Sperrenerfassung erfolgreich war. Wir erwerben zuerst die Sperre, legen dann die Ablaufzeit der Sperre fest, führen entsprechende Vorgänge aus und geben schließlich die Sperre frei.
Das obige ist der detaillierte Inhalt vonSo verwenden Sie die optimistische und die pessimistische Sperre von Redis. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!