>  기사  >  데이터 베이스  >  Redis의 트랜잭션에 대해 자세히 알아보기

Redis의 트랜잭션에 대해 자세히 알아보기

青灯夜游
青灯夜游앞으로
2021-04-13 10:57:321886검색

이 기사에서는 Redis의 트랜잭션에 대해 자세히 설명합니다. 도움이 필요한 친구들이 모두 참고할 수 있기를 바랍니다. ㅋㅋㅋ

Redis의 트랜잭션에 대해 자세히 알아보기WATCH

WATCH 키 [ key...]

주어진 모니터링 상태로 트랜잭션 실행항상 OK를 표시합니다.UNWATCH UNWATCH트랜잭션에서 모니터링 상태를 삭제하세요. EXECUNWATCH
또는 DISCARD가 호출되면 를 수동으로 호출할 필요가 없습니다. 항상 OK. Keys标记为监测态,作为事务执行的条件 always OK.
UNWATCH UNWATCH 清除事务中Keys监测态,如果调用了EXEC or DISCARD,则没有必要再手动调用UNWATCH always OK.
MULTI MULTI 显式开启redis事务,后续commands将排队,等候使用EXEC进行原子执行 always OK.
EXEC EXEC 执行事务中的commands队列,恢复连接状态。如果WATCH在之前被调用,只有监测中的Keys没有被修改,命令才会被执行,否则停止执行(详见下文,CAS机制 成功: 返回数组 —— 每个元素对应着原子事务中一个 command的返回结果;
失败: 返回NULLRuby 返回`nil`);
DISCARD DISCARD 清除事务中的commands队列,恢复连接状态。如果WATCH在之前被调用,释放 监测中的Keys MULTI
MULTI🎜🎜🎜명시적으로 redis 트랜잭션을 열면 후속 명령이 대기열에 추가됩니다. 대기 중 원자 실행을 위해 🎜EXEC🎜를 사용하세요 🎜🎜항상 괜찮습니다.🎜🎜🎜🎜🎜EXEC🎜🎜🎜🎜EXEC🎜🎜🎜트랜잭션에서 명령 대기열을 실행하고 연결 상태를 복원하세요. 🎜WATCH🎜가 이전에 호출된 경우 모니터링가 수정되지 않은 경우에만 명령이 실행되고, 그렇지 않으면 실행이 중지됩니다(자세한 내용은 아래 참조, CAS 메커니즘) 🎜🎜🎜성공: 🎜 반환 배열 - 각 요소는 원자 트랜잭션에서 명령의 반환 결과에 해당합니다.
🎜실패: 🎜 반환 NULL (Ruby`nil`을 반환함) 🎜🎜🎜🎜🎜DISCARD🎜🎜🎜🎜DISCARD🎜🎜🎜명령 지우기큐에서 연결 상태를 복원합니다. 🎜WATCH🎜가 이전에 호출된 경우 <code>Monitor🎜🎜에서 Release Keys는 항상 OK입니다.🎜🎜🎜🎜

참고:

------MULTI, EXEC, DISCARD명시적트랜잭션을 열고 제어하는 ​​일반적인 명령은 <code>관계형 데이터베이스BEGAIN, COMMIT, ROLLBACK과 비교할 수 있습니다. >( 실제로 그 차이는 엄청납니다.) MULTI,EXEC,DISCARD才是显式开启并控制事务的常用命令,可类比关系型数据库中的  BEGAIN,COMMIT,ROLLBACK(事实上,差距很大);

------WATCH命令的使用是为了解决 事务并发 产生的不可重复读幻读的问题(简单理解为给Key加锁);


Redis事务

MULTI, EXEC, DISCARD and WATCH 是Redis事务的基础。用来显式开启并控制一个事务,它们允许在一个步骤中执行一组命令。并提供两个重要的保证:

  • 事务中的所有命令都会被序列化并按顺序执行。在执行Redis事务的过程中,不会出现由另一个客户端发出的请求。这保证 命令队列 作为一个单独的原子操作被执行。
  • 队列中的命令要么全部被处理,要么全部被忽略。EXEC命令触发事务中所有命令的执行,因此,当客户端在事务上下文中失去与服务器的连接,
  • 如果发生在调用MULTI命令之前,则不执行任何commands
  • 如果在此之前EXEC命令被调用,则所有的commands都被执行。

同时,redis使用AOF(append-only file),使用一个额外的write操作将事务写入磁盘。如果发生宕机,进程奔溃等情况,可以使用redis-check-aof tool 修复append-only file,使服务正常启动,并恢复部分操作。


用法

使用MULTI命令显式开启Redis事务。 该命令总是以OK回应。此时用户可以发出多个命令,Redis不会执行这些命令,而是将它们排队EXEC被调用后,所有的命令都会被执行。而调用DISCARD可以清除事务中的commands队列退出事务

  • 以下示例以原子方式,递增键foo和bar。
>MULTI
OK
>INCR foo
QUEUED
>INCR bar
QUEUED
>EXEC
1)(整数)1
2)(整数)1

从上面的命令执行中可以看出,EXEC返回一个数组其中每个元素都是事务中单个命令的返回结果,而且顺序与命令的发出顺序相同MULTI请求的上下文中时,所有命令将以字符串QUEUED从Redis协议的角度作为状态回复发送)作为回复,并在命令队列中排队。只有EXEC被调用时,排队的命令才会被执行,此时才会有真正的返回结果


事务中的错误

事务期间,可能会遇到两种命令错误:

  • 在调用EXEC命令之前出现错误(COMMAND排队失败)。
  • 例如,命令可能存在语法错误(参数数量错误,错误的命令名称...);
  • 或者可能存在某些关键条件,如内存不足的情况(如果服务器使用maxmemory指令做了内存限制)。

客户端会在EXEC调用之前检测第一种错误。 通过检查排队命令的状态回复(***注意:这里是指排队状态回复,而不是执行结果***),如果命令使用QUEUED进行响应,则它已正确排队,否则Redis将返回错误。如果排队命令时发生错误,大多数客户端将中止该事务并清除命令队列。然而:

  • Redis 2.6.5之前,这种情况下,在EXEC命令调用后,客户端会执行命令的子集(成功排队的命令)而忽略之前的错误。
  • Redis 2.6.5开始,服务端会记住在累积命令期间发生的错误,当EXEC命令调用时,将拒绝执行事务,并返回这些错误,同时自动清除命令队列
  • 示例如下:
>MULTI
+OK
>INCR a b c
-ERR wrong number of arguments for &#39;incr&#39; command

这是由于INCR命令的语法错误,将在调用EXEC之前被检测出来,并终止事务(version2.6.5+)。

  • 在调用EXEC命令之后出现错误。
  • 例如,使用错误的值对某个key执行操作(如针对String值调用List操作)

EXEC命令执行之后发生的错误并不会被特殊对待即使事务中的某些命令执行失败,其他命令仍会被正常执行------WATCH 명령은 트랜잭션 동시성반복 불가능한 읽기 문제를 해결하는 데 사용됩니다. /code> /code> 및 <code>팬텀 읽기 관련 문제(간단히 잠금으로 이해됨)


Redis 트랜잭션

🎜MULTI, EXEC, DISCARD 및 WATCH는 Redis 트랜잭션의 기본입니다. 트랜잭션을 명시적으로 시작하고 제어하는 ​​데 사용되며 일련의 명령을 한 단계로 실행할 수 있습니다. 그리고 두 가지 중요한 보장을 제공합니다: 🎜
  • 트랜잭션의 모든 명령은 직렬화되어 순서대로 실행됩니다. Redis 트랜잭션을 실행하는 동안 다른 클라이언트에서 발행한 요청은 발생하지 않습니다. 이렇게 하면 명령 대기열이 단일 원자성 작업으로 실행됩니다.
  • 큐의 모든 명령이 처리되거나 무시됩니다. EXEC 명령은 트랜잭션의 모든 명령 실행을 트리거하므로 클라이언트가 트랜잭션 컨텍스트에서 서버에 대한 연결이 끊어지면
  • MULTI 명령이 호출되기 전에 이 문제가 발생하면 가 없습니다. 명령
  • 이 실행됩니다. code>;
  • 이전에 EXEC 명령이 호출되면 모든 명령이 실행됩니다.
🎜동시에 redis는 AOF(append-only를 사용합니다. 파일🎜 a>), 추가 쓰기 작업을 사용하여 트랜잭션을 디스크에 씁니다. 다운타임이나 프로세스 충돌이 발생하면 서비스가 정상적으로 시작되고 일부 작업을 재개할 수 있도록 redis-check-aof 도구를 사용하여 추가 전용 파일을 복구할 수 있습니다. 🎜

사용법

🎜 MULTI 명령을 사용하여 Redis 트랜잭션을 명시적으로 엽니다. 이 명령은 항상 OK로 응답합니다. 사용자는 현재 여러 명령을 실행할 수 있지만 Redis는 이러한 명령을 실행하지 않고 대기열에 추가합니다. EXEC가 호출되면 모든 명령이 실행됩니다. DISCARD를 호출하면 트랜잭션의 명령 대기열삭제하고 트랜잭션을 종료할 수 있습니다. 🎜
  • 다음 예에서는 foo 및 bar 키를 원자적으로 증가시킵니다.
>MULTI
+OK
>SET a 3
+QUEUED
>LPOP a
+QUEUED
>EXEC
*2
+OK
-ERR Operation against a key holding the wrong kind of value
🎜위 명령 실행에서 볼 수 있듯이 EXEC배열을 반환하며, 각 요소는 트랜잭션에 있습니다. 단일 명령에서 반환된 결과는 명령이 실행된 순서와 동일합니다. Redis 연결이 MULTI 요청의 컨텍스트에 있는 경우 모든 명령은 STRING QUEUED로 응답됩니다(🎜Redis 프로토콜의 관점에서 상태 응답으로 전송됨🎜). ) 및 명령 대기열의 대기열에 있습니다. EXEC가 호출될 때만 대기 중인 명령이 실행되고 실제 반환 결과가 나타납니다. 🎜

트랜잭션 오류

🎜🎜트랜잭션 중에 두 가지 명령 오류가 발생할 수 있습니다: 🎜🎜
  • 🎜호출할 때 오류 EXEC 명령 전에 발생했습니다(COMMAND가 대기열에 실패함). 🎜
  • 예를 들어 명령에 구문 오류(잘못된 매개변수 수, 잘못된 명령 이름...)가 있을 수 있습니다.
  • 또는 some 일부 핵심 조건
, 예를 들어 메모리 부족(서버가 maxmemory 지시문을 사용하여 메모리 제한을 설정하는 경우). 🎜🎜클라이언트는 EXEC를 호출하기 전에 첫 번째 오류🎜를 감지합니다. 대기 중인 명령의 상태 응답을 확인하여(***참고: 이는 대기 중인상태 응답을 의미하며, >실행 결과***), 명령이 <code>QUEUED로 응답하면 올바르게 대기열에 추가된 것입니다. 그렇지 않으면 Redis가 오류를 반환합니다. 명령을 대기열에 넣는 동안 오류가 발생하면 대부분의 클라이언트는 트랜잭션을 중단하고 명령 대기열을 지웁니다. 그러나: 🎜
  • Redis 2.6.5 이전에는 이 경우 EXEC 명령이 호출된 후 클라이언트가 명령의 하위 집합을 실행합니다( 성공적으로 대기열에 추가된 명령) 이전 오류를 무시합니다.
  • Redis 2.6.5부터 서버는 EXEC 명령이 호출될 때 명령이 누적되는 동안 발생한 오류를 기억하게 됩니다. > 트랜잭션 실행이 거부되고 해당 오류가 반환되며 명령 대기열이 자동으로 지워집니다
.
  • 예제는 다음과 같습니다.
  • > SET foo 1
    OK
    > MULTI
    OK
    > INCR foo
    QUEUED
    > DISCARD
    OK
    > GET foo
    "1"
    🎜🎜INCR 명령의 구문 오류로 인해 발생합니다. code>EXEC 이를 감지하고 트랜잭션을 종료합니다(버전2.6.5+). 🎜
    • 🎜EXEC 명령을 호출한 후 오류가 발생했습니다. 🎜
    • 예를 들어 잘못된 값을 사용하여 에 대한 작업을 수행하는 경우(예: 문자열에서 호출) code> 값 목록 작업)
    🎜🎜 EXEC 명령 실행 후 발생하는 오류는 특별히 처리되지 않습니다.🎜: 일부 명령이 발생하더라도 실패하더라도 다른 명령은 정상적으로 실행됩니다. 🎜
    • 示例如下:
    >MULTI
    +OK
    >SET a 3
    +QUEUED
    >LPOP a
    +QUEUED
    >EXEC
    *2
    +OK
    -ERR Operation against a key holding the wrong kind of value
    • EXEC返回一个包含两个元素的字符串数组,一个元素是OK,另一个是-ERR……
    • 能否将错误合理的反馈给用户这取决于客户端library(如:Spring-data-redis.redisTemplate)的自身实现。
    • 需要注意的是,即使命令失败,队列中的所有其他命令也会被处理----Redis不会停止命令的处理

    Redis事务不支持Rollback(重点

    事实上Redis命令在事务执行时可能会失败,但仍会继续执行剩余命令而不是Rollback(事务回滚)。如果你使用过关系数据库,这种情况可能会让你感到很奇怪。然而针对这种情况具备很好的解释:

    • Redis命令可能会执行失败,仅仅是由于错误的语法被调用(命令排队时检测不出来的错误),或者使用错误的数据类型操作某个Key: 这意味着,实际上失败的命令都是编程错误造成的,都是开发中能够被检测出来的,生产环境中不应该存在。(这番话,彻底甩锅,“都是你们自己编程错误,与我们无关”。)
    • 由于不必支持Rollback,Redis内部简洁并且更加高效。

    如果错误就是发生了呢?”这是一个反对Redis观点的争论。然而应该指出的是,通常情况下,回滚并不能挽救编程错误。鉴于没有人能够挽救程序员的错误,并且Redis命令失败所需的错误类型不太可能进入生产环境,所以我们选择了不支持错误回滚(Rollback)这种更简单快捷的方法。


    清除命令队列

    DISCARD被用来中止事务。事务中的所有命令将不会被执行,连接将恢复正常状态。

    > SET foo 1
    OK
    > MULTI
    OK
    > INCR foo
    QUEUED
    > DISCARD
    OK
    > GET foo
    "1"

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

    위 내용은 Redis의 트랜잭션에 대해 자세히 알아보기의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

    성명:
    이 기사는 juejin.cn에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제