Heim >Datenbank >Redis >Lassen Sie uns über Transaktionen in Redis sprechen: Transaktionsmodus, Lua-Skript

Lassen Sie uns über Transaktionen in Redis sprechen: Transaktionsmodus, Lua-Skript

青灯夜游
青灯夜游nach vorne
2023-04-10 19:29:361623Durchsuche

Dieser Artikel vermittelt Ihnen ein umfassendes Verständnis der Redis-Transaktionen und vergleicht die beiden Modi von Redis-Transaktionen (Transaktionsmodus und Lua-Skript). Ich hoffe, dass er für alle hilfreich ist!

Um genau zu sein, umfassen Redis-Transaktionen zwei Modi: Transaktionsmodus und Lua-Skript#🎜 🎜 #.

Lassen Sie uns zunächst über die Schlussfolgerung sprechen:

Das Transaktionsmodell von Redis weist die folgenden Merkmale auf:

    Garantieisolation; #🎜🎜 ##🎜 🎜# Haltbarkeit kann nicht garantiert werden;
  • hat einen gewissen Grad an Atomizität, unterstützt aber kein Rollback;
  • Das Konzept der Konsistenz ist anders, vorausgesetzt, der Kern Konsistenz ist Unter der Semantik von Einschränkungen können Redis-Transaktionen Konsistenz gewährleisten.
  • Aber das Lua-Skript hat praktischere Szenarien. Es ist eine gewisse Atomizität, aber wenn das Skript einen Fehler meldet, wird die Transaktion nicht zurückgesetzt. Lua-Skripte können die Isolation gewährleisten und können nachfolgende Schritte perfekt unterstützen, abhängig von den Ergebnissen der vorherigen Schritte
  • . [Verwandte Empfehlungen:
Redis-Video-Tutorial

]Der Lua-Skriptmodus ist fast überall, z. B. verteilte Sperren, Verzögerungswarteschlangen, das Ergreifen roter Umschläge und andere Szenarien.

1 Transaktionsprinzip

Redis-Transaktionen umfassen die folgenden Befehle:

SeriennummerBefehl und Beschreibung1 # 🎜🎜#MULTI Markiert den Beginn eines Transaktionsblocks. 2EXEC führt alle Befehle innerhalb des Transaktionsblocks aus. 3DISCARD bricht die Transaktion ab und bricht die Ausführung aller Befehle innerhalb des Transaktionsblocks ab. 4WATCH-Taste [Taste ...] Beobachten Sie eine (oder mehrere) Taste, wenn diese (oder wenn diese) Tasten geändert werden Durch andere Befehle wird die Transaktion unterbrochen. 5UNWATCH bricht die Überwachung aller Tasten durch den WATCH-Befehl ab.

Transaktion besteht aus drei Phasen:

  1. Transaktion wird geöffnet, mit MULTI markiert dieser Befehl den Client, der den Befehl ausführt, vom nicht-transaktionalen Zustand in den transaktionalen Zustand zu wechseln;
  2. Befehl in die Warteschlange stellen, nachdem MULTI die Transaktion geöffnet hat, wird der Befehl des Clients angezeigt wird nicht sofort ausgeführt, sondern in eine Transaktionswarteschlange gestellt.
  3. Führen Sie die Transaktion aus oder verwerfen Sie sie. Wenn ein EXEC-Befehl empfangen wird, wird der Befehl in der Transaktionswarteschlange ausgeführt. Wenn es DISCARD ist, wird die Transaktion verworfen.

Das Folgende zeigt ein Beispiel einer Transaktion.

1
 redis> MULTI 
2
 OK
3
 redis> SET msg "hello world"
4
 QUEUED
5
 redis> GET msg
6
 QUEUED
7
 redis> EXEC
8
 1) OK
9
 1) hello world

Haben Sie hier eine Frage? Kann der Redis-Schlüssel beim Starten einer Transaktion geändert werden?

Bevor die Transaktion den EXEC-Befehl ausführt, kann der Redis-Schlüssel noch geändert werden.

Bevor die Transaktion gestartet wird, können wir den Befehl watch verwenden, um den Redis-Schlüssel zu überwachen. Bevor die Transaktion ausgeführt wird, ändern wir den Schlüsselwert. Wenn die Transaktion fehlschlägt, wird nil zurückgegeben.

Durch das obige Beispiel kann der Watch-Befehl „einen Effekt erzielen, der dem optimistischen Sperren ähnelt“.

2 ACID der Transaktion

2.1 AtomizitätAtomizität bedeutet: Alle Vorgänge in einer Transaktion sind entweder vollständig abgeschlossen oder nicht abgeschlossen und enden nicht in einer Zwischenverbindung. Wenn während der Ausführung der Transaktion ein Fehler auftritt, wird sie auf den Zustand vor Beginn der Transaktion zurückgesetzt, als ob die Transaktion nie ausgeführt worden wäre.

Erstes Beispiel:

Vor der Ausführung des EXEC-Befehls ist der vom Client gesendete Betriebsbefehl falsch, z. B. ein Syntaxfehler oder ein nicht vorhandener Befehl.

1
 redis> MULTI
2
 OK
3
 redis> SET msg "other msg"
4
 QUEUED
5
 redis> wrongcommand  ### 故意写错误的命令
6
 (error) ERR unknown command 'wrongcommand' 
7
 redis> EXEC
8
 (error) EXECABORT Transaction discarded because of previous errors.
9
 redis> GET msg
10
 "hello world"

In diesem Beispiel haben wir einen Befehl verwendet, der nicht existiert, was dazu führte, dass das Einreihen in die Warteschlange fehlschlug und die gesamte Transaktion nicht ausgeführt werden konnte.

Zweites Beispiel:

Wenn die Transaktionsoperation in die Warteschlange gestellt wird, stimmen die Datentypen des Befehls und der Operation nicht überein. Das Einreihen in die Warteschlange ist normal, aber die Ausführung des EXEC-Befehls ist abnormal.

1
 redis> MULTI  
2
 OK
3
 redis> SET msg "other msg"
4
 QUEUED
5
 redis> SET mystring "I am a string"
6
 QUEUED
7
 redis> HMSET mystring name  "test"
8
 QUEUED
9
 redis> SET msg "after"
10
 QUEUED
11
 redis> EXEC
12
 1) OK
13
 2) OK
14
 3) (error) WRONGTYPE Operation against a key holding the wrong kind of value
15
 4) OK
16
 redis> GET msg
17
 "after"

Wenn in diesem Beispiel ein Fehler auftritt, wenn Redis den EXEC-Befehl ausführt, beendet Redis die Ausführung anderer Befehle nicht und die Transaktion wird nicht zurückgesetzt, da die Ausführung eines bestimmten Befehls fehlschlägt.

Zusammenfassend ist mein Verständnis der Atomizität von Redis-Transaktionen wie folgt:

Wenn beim Einreihen des Befehls ein Fehler gemeldet wird, wird die Transaktionsausführung abgebrochen, um die Atomizität sicherzustellen.
  1. Das ist normal eingereiht, und nach der Ausführung des EXEC-Befehls wird ein Fehler gemeldet, der keine Atomizitätseigenschaften garantiert
  2. Das heißt:
Redis-Transaktionen haben nur unter bestimmten Bedingungen eine bestimmte Atomizität

.

2.2 Isolation Die Isolation der Datenbank bezieht sich auf die Fähigkeit der Datenbank, mehreren gleichzeitigen Transaktionen das gleichzeitige Lesen, Schreiben und Ändern ihrer Daten zu ermöglichen. Durch die Isolation kann verhindert werden, dass mehrere Transaktionen gleichzeitig ausgeführt werden Ausführung führt zu Dateninkonsistenzen.

Die Transaktionsisolation ist in verschiedene Ebenen unterteilt:

read uncommitted
  • read commit
  • repeatable read
  • serializable
  • Zunächst muss klar sein: Redis hat nicht das Konzept der Transaktion Isolationsstufe. Hier diskutieren wir die Isolation von Redis:
In einem gleichzeitigen Szenario können Transaktionen eine gegenseitige Beeinträchtigung vermeiden

. Wir können die Transaktionsausführung in zwei Phasen unterteilen:

vor der Ausführung des EXEC-Befehls

und EXEC-Befehl nach der Ausführung und sie separat besprechen.

Vor der Ausführung des EXEC-Befehls
  1. Im Abschnitt über Transaktionsprinzipien haben wir festgestellt, dass der Redis-Schlüssel noch geändert werden kann, bevor die Transaktion ausgeführt wird. Zu diesem Zeitpunkt können Sie den
WATCH-Mechanismus

verwenden, um den Effekt einer optimistischen Sperre zu erzielen.

Nachdem der EXEC-Befehl ausgeführt wurde
  1. Da Redis ein Single-Threaded-Ausführungsbefehl ist, stellt Redis nach der Ausführung des EXEC-Befehls sicher, dass alle Befehle in der Befehlswarteschlange ausgeführt werden. Dies stellt die Transaktionsisolation sicher.

2.3 HaltbarkeitDie Persistenz der Datenbank bedeutet: Nach Abschluss der Transaktion ist die Änderung der Daten dauerhaft und geht auch bei einem Systemausfall nicht verloren.

Ob Redis-Daten beibehalten werden, hängt vom Persistenzkonfigurationsmodus von Redis ab.

Ohne konfiguriertes RDB oder AOF kann die Haltbarkeit der Transaktion nicht garantiert werden.
  1. Bei Verwendung des RDB-Modus gilt nach der Ausführung einer Transaktion und vor der Ausführung des nächsten RDB-Snapshots die Haltbarkeit der Transaktion, wenn ein Instanzabsturz auftritt Es gibt auch keine Garantie;
  2. verwendet den AOF-Modus; die drei Konfigurationsoptionen des AOF-Modus, nein und jede Sekunde, führen zu Datenverlust. Die Dauerhaftigkeit von Transaktionen kann immer garantiert werden. Da die Leistung jedoch zu gering ist, wird die Verwendung in Produktionsumgebungen im Allgemeinen nicht empfohlen.
  3. Zusammenfassend kann die Haltbarkeit von
Redis-Transaktionen nicht garantiert werden

.

2.4 KonsistenzDas Konzept der Konsistenz war schon immer verwirrend. In den von mir gesuchten Informationen gibt es zwei verschiedene Definitionen.

  1. wikipedia

Schauen wir uns zunächst die Definition von Konsistenz auf Wikipedia an:

Konsistenz stellt sicher, dass eine Transaktion möglich ist Bringen Sie die Datenbank nur von einem gültigen Zustand in einen anderen und behalten Sie dabei die Datenbankinvarianten bei: Alle in die Datenbank geschriebenen Daten müssen gemäß allen definierten Regeln, einschließlich Einschränkungen, Kaskaden, Triggern und jeder Kombination davon, gültig sein. Dies verhindert eine Beschädigung der Datenbank durch eine illegale Transaktion , garantiert aber nicht, dass eine Transaktion korrekt ist.

In diesem Text ist der Kern der Konsistenz „#🎜 🎜#Einschränkung#“ 🎜🎜#", "Alle in die Datenbank geschriebenen Daten müssen gemäß allen definierten Regeln gültig sein". Wie versteht man Einschränkungen? Hier ist ein Zitat aus der Zhihu-Frage

Wie man die interne und externe Konsistenz der Datenbank versteht

, beantwortet von Han Fusheng, einem OceanBase-Forschungs- und Entwicklungsexperten bei Ant Financial: # 🎜🎜#" „Einschränkungen“ werden vom Datenbankbenutzer der Datenbank mitgeteilt, dass der Benutzer verlangt, dass die Daten dieser oder jener Einschränkung entsprechen müssen. Wenn die Daten geändert werden, prüft die Datenbank, ob die Daten noch den Einschränkungen entsprechen. Wenn die Einschränkungen nicht mehr erfüllt sind, wird der Änderungsvorgang nicht durchgeführt.

Die beiden häufigsten Arten von Einschränkungen in relationalen Datenbanken sind „Eindeutige Einschränkungen“ und „Integritätsbeschränkungen“. Der in der Tabelle definierte Primärschlüssel und der eindeutige Schlüssel stellen sicher, dass die angegebenen Datenelemente niemals wiederholt werden. Die zwischen Tabellen definierte referenzielle Integrität gewährleistet auch die Konsistenz desselben Attributs in verschiedenen Tabellen.

„Konsistenz in ACID“ ist so einfach zu verwenden, dass es den meisten Benutzern bewusst in den Sinn gekommen ist, die erforderlichen Einschränkungen beim Entwerfen von Tabellen hinzuzufügen.

Also

hängt die Konsistenz der Transaktion mit den vordefinierten Einschränkungen zusammen, sodass sichergestellt wird, dass die Einschränkungen die Konsistenz
gewährleisten.

Schauen wir uns diesen Satz genauer an: Dies verhindert eine Datenbankbeschädigung durch eine illegale Transaktion, garantiert aber nicht, dass eine Transaktion korrekt ist

.

Vielleicht sind alle immer noch etwas verwirrt, nachdem wir das geschrieben haben. Nehmen wir den klassischen Transfer

-Fall.

Wir starten eine Transaktion. Der Anfangssaldo auf den Konten von Zhang San und Li Si beträgt jeweils 1.000 Yuan, und es gibt keine Einschränkungen im Saldofeld. Zhang San überwies 1.200 Yuan an Li Si. Der Kontostand von Zhang San wird auf -200 aktualisiert und der Kontostand von Li Si wird auf 2200 aktualisiert.

Auf Anwendungsebene ist diese Transaktion offensichtlich illegal, da in realen Szenarien der Benutzersaldo nicht weniger als 0 sein darf, aber sie folgt vollständig den Einschränkungen der Datenbank, also auf Datenbankebene Die Transaktion ist weiterhin konsistent. Die Konsistenz ist gewährleistet.

Die Transaktionskonsistenz von Redis bedeutet, dass die Redis-Transaktion während der Ausführung den Einschränkungen der Datenbank entspricht und keine illegalen oder ungültigen Fehlerdaten enthält.

Wir diskutieren jeweils drei Ausnahmeszenarien:

Vor der Ausführung des EXEC-Befehls ist der vom Client gesendete Operationsbefehl falsch, die Transaktion ist falsch beendet, und die Daten behalten ihre Konsistenz bei;
  1. Nach der Ausführung des EXEC-Befehls stimmen der Datentyp des Befehls und der Operation nicht überein. Es wird ein Fehler gemeldet Befehl, aber die Transaktion wird aufgrund des falschen Befehls nicht abgebrochen, sondern weiter ausgeführt. Korrekte Befehle werden normal ausgeführt, und falsche Befehle melden Fehler. Aus dieser Perspektive können die Daten auch konsistent bleiben runter . Hier müssen Sie den Persistenzmodus der Dienstkonfiguration berücksichtigen.

  2. Kein Persistenzspeichermodus: Nach dem Neustart des Dienstes behält die Datenbank keine Daten bei, sodass die Daten konsistent bleiben.

    RDB-/AOF-Modus: Nachher Der Dienst wird neu gestartet, Redis stellt Daten über RDB/AOF-Dateien wieder her und die Datenbank wird in einen konsistenten Zustand zurückversetzt.
    • Zusammenfassend:
    • Unter der Semantik, dass der Kern der Konsistenz die Einschränkung ist, können Redis-Transaktionen Konsistenz garantieren#🎜🎜 #.
    • "Designing Data-Intensive Applications"
Dieses Buch ist ein heiliges Buch für den Einstieg in verteilte Systeme. Im Transaktionskapitel gibt es eine Erklärung zu ACID:

  1. Atomizität, Isolation und Haltbarkeit sind Eigenschaften der Datenbank, wohingegen Konsistenz ( im ACID-Sinne) ist eine Eigenschaft der Anwendung. Die Anwendung kann sich auf die Atomizitäts- und Isolationseigenschaften der Datenbank verlassen, um Konsistenz zu erreichen, aber es liegt nicht allein an der Datenbank. Daher gehört der Buchstabe C nicht wirklich zu ACID .

Atomizität, Isolation und Haltbarkeit sind Eigenschaften der Datenbank, während Konsistenz (im ACID-Sinn) eine Eigenschaft der Anwendung ist. Anwendungen können auf die Atomizitäts- und Isolationseigenschaften der Datenbank angewiesen sein, um Konsistenz zu erreichen, dies hängt jedoch nicht nur von der Datenbank ab. Daher gehört der Buchstabe C nicht zu ACID.

Oft bezieht sich die Konsistenz, mit der wir zu kämpfen haben, tatsächlich auf Konsistenz im Einklang mit der realen Welt

Konsistenz in der realen Welt ist das ultimative Ziel, das von Affären verfolgt wird.

Um Konsistenz in der realen Welt zu erreichen, müssen folgende Punkte erfüllt sein:

  1. Garantie für Atomizität, Haltbarkeit und Isolation, dann kann die Konsistenz der Transaktion nicht garantiert werden.
  2. Einschränkungen der Datenbank selbst, wie z. B. die Spaltenlänge oder Eindeutigkeitseinschränkungen dürfen nicht überschritten werden Ebene muss ebenfalls geschützt werden.

2.5 TransaktionsfunktionenWir bezeichnen Redis normalerweise als In-Memory-Datenbank. Um eine höhere Leistung und eine schnellere Schreibgeschwindigkeit zu gewährleisten, wurden einige Dinge auf der Design- und Implementierungsebene getan Ausgewogen, unterstützt transaktionales ACID nicht vollständig.

Redis-Transaktionen haben die folgenden Eigenschaften:

garantiert keine Haltbarkeit;
  • hat einen gewissen Grad an Atomizität, unterstützt aber kein Rollback; Konsistenz besteht darin, dass Redis-Transaktionen unter der Semantik von Einschränkungen Konsistenz gewährleisten können.
  • Aus technischer Sicht muss unter der Annahme, dass jeder Schritt in einem Transaktionsvorgang auf dem vom vorherigen Schritt zurückgegebenen Ergebnis basieren muss, eine optimistische Sperre durch Überwachung implementiert werden.
  • 3 Lua-Skript

3.1 Einführung

Lua ist in Standard C geschrieben. Der Code ist einfach und schön und kann auf fast allen Betriebssystemen und Plattformen kompiliert und ausgeführt werden. Lua-Skripte können einfach über C/C++-Code aufgerufen werden und können wiederum C/C++-Funktionen aufrufen, wodurch Lua in Anwendungen weit verbreitet ist.

Lua-Skripte haben im Spielebereich glänzt. Sowohl das bekannte „Westward Journey II“ als auch „World of Warcraft“ nutzen Lua-Skripte ausgiebig. Lua-Skripte sind in API-Gateways zu sehen, mit denen Java-Backend-Ingenieure in Kontakt gekommen sind, wie zum Beispiel

Openresty und

Kong

.

Ab Redis Version 2.6.0 kann der integrierte Lua-Interpreter von Redis Lua-Skripte in Redis ausführen. Vorteile der Verwendung von Lua-Skripten:

Reduzieren Sie den Netzwerkaufwand. Senden Sie mehrere Anfragen gleichzeitig in Form eines Skripts, um die Netzwerklatenz zu reduzieren.

Atomoperationen. Redis führt das gesamte Skript als Ganzes aus und es werden keine weiteren Befehle in die Mitte eingefügt.

Wiederverwendung. Das vom Client gesendete Skript wird dauerhaft in Redis gespeichert, und andere Clients können dieses Skript wiederverwenden, ohne Code zur Vervollständigung derselben Logik verwenden zu müssen.
  • Allgemeine Befehle für Redis Lua-Skripte:
Seriennummer

Befehl und Beschreibung
EVAL-Skript-Numkeys-Taste [key ...] arg [arg ...] Lua ausführen Skript.
1
2 EVALSHA sha1 numkeys key [key ...] arg [arg ...] Lua-Skript ausführen.
3 SCRIPT EXISTS script [script ...] Überprüfen Sie, ob das angegebene Skript im Cache gespeichert wurde.
4 SCRIPT FLUSH Entfernt alle Skripte aus dem Skript-Cache.
5 SCRIPT KILL Beende das aktuell laufende Lua-Skript.
6 SCRIPT LOAD script Fügt ein Skriptskript zum Skriptcache hinzu, führt das Skript jedoch nicht sofort aus.

3.2 EVAL 命令

命令格式:

1
 EVAL script numkeys key [key ...] arg [arg ...]

说明:

  • script是第一个参数,为 Lua 5.1脚本;
  • 第二个参数numkeys指定后续参数有几个 key;
  • key [key ...],是要操作的键,可以指定多个,在 Lua 脚本中通过KEYS[1], KEYS[2]获取;
  • arg [arg ...],参数,在 Lua 脚本中通过ARGV[1], ARGV[2]获取。

简单实例:

1
 redis> eval "return ARGV[1]" 0 100 
2
 "100"
3
 redis> eval "return {ARGV[1],ARGV[2]}" 0 100 101
4
 1) "100"
5
 2) "101"
6
 redis> eval "return {KEYS[1],KEYS[2],ARGV[1]}" 2 key1 key2 first second
7
 1) "key1"
8
 2) "key2"
9
 3) "first"
10
 4) "second"

下面演示下 Lua 如何调用 Redis 命令 ,通过redis.call()来执行了 Redis 命令 。

1
 redis> set mystring 'hello world'
2
 OK
3
 redis> get mystring
4
 "hello world"
5
 redis> EVAL "return redis.call('GET',KEYS[1])" 1 mystring
6
 "hello world"
7
 redis> EVAL "return redis.call('GET','mystring')" 0
8
 "hello world"

3.3 EVALSHA 命令

使用 EVAL 命令每次请求都需要传输 Lua 脚本 ,若 Lua 脚本过长,不仅会消耗网络带宽,而且也会对 Redis 的性能造成一定的影响。

思路是先将 Lua 脚本先缓存起来 , 返回给客户端 Lua 脚本的 sha1 摘要。 客户端存储脚本的 sha1 摘要 ,每次请求执行 EVALSHA 命令即可。

EVALSHA 命令基本语法如下:

1
 redis> EVALSHA sha1 numkeys key [key ...] arg [arg ...]

实例如下:

1
 redis> SCRIPT LOAD "return 'hello world'"
2
 "5332031c6b470dc5a0dd9b4bf2030dea6d65de91"
3
 redis> EVALSHA 5332031c6b470dc5a0dd9b4bf2030dea6d65de91 0
4
 "hello world"

4 事务 VS Lua 脚本

从定义上来说, Redis 中的脚本本身就是一种事务, 所以任何在事务里可以完成的事, 在脚本里面也能完成。 并且一般来说, 使用脚本要来得更简单,并且速度更快

因为脚本功能是 Redis 2.6 才引入的, 而事务功能则更早之前就存在了, 所以 Redis 才会同时存在两种处理事务的方法。

不过我们并不打算在短时间内就移除事务功能, 因为事务提供了一种即使不使用脚本, 也可以避免竞争条件的方法, 而且事务本身的实现并不复杂。

-- redis.io/

Lua 脚本是另一种形式的事务,他具备一定的原子性,但脚本报错的情况下,事务并不会回滚。Lua 脚本可以保证隔离性,而且可以完美的支持后面的步骤依赖前面步骤的结果

Lua 脚本模式的身影几乎无处不在,比如分布式锁、延迟队列、抢红包等场景。

不过在编写 Lua 脚本时,要注意如下两点:

  1. 为了避免 Redis 阻塞,Lua 脚本业务逻辑不能过于复杂和耗时;
  2. 仔细检查和测试 Lua 脚本 ,因为执行 Lua 脚本具备一定的原子性,不支持回滚。

更多编程相关知识,请访问:编程视频!!

Das obige ist der detaillierte Inhalt vonLassen Sie uns über Transaktionen in Redis sprechen: Transaktionsmodus, Lua-Skript. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:juejin.cn. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen