이 기사에서는 Redis의 트랜잭션에 대해 자세히 설명합니다. 도움이 필요한 친구들이 모두 참고할 수 있기를 바랍니다. ㅋㅋㅋ
WATCH
주어진키
를 모니터링 상태
로 트랜잭션 실행UNWATCH | UNWATCH | ||
---|---|---|---|
또는 DISCARD가 호출되면 | UNWATCH를 수동으로 호출할 필요가 없습니다. 항상 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 的返回结果;失败: 返回 NULL (Ruby 返回`nil` ); |
DISCARD | DISCARD | 清除事务中的commands 队列,恢复连接状态。如果WATCH在之前被调用,释放 监测 中的Keys
|
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加锁
);
MULTI, EXEC, DISCARD and WATCH 是Redis事务的基础。用来显式开启并控制一个事务,它们允许在一个步骤中执行一组命令
。并提供两个重要的保证:
命令队列
作为一个单独的原子操作被执行。commands
;commands
都被执行。同时,redis使用AOF(append-only file),使用一个额外的write操作
将事务写入磁盘。如果发生宕机,进程奔溃等情况,可以使用redis-check-aof tool 修复append-only file,使服务正常启动,并恢复部分操作。
使用MULTI
命令显式开启
Redis事务。 该命令总是以OK回应。此时用户可以发出多个命令,Redis不会执行这些命令,而是将它们排队
。EXEC
被调用后,所有的命令都会被执行。而调用DISCARD
可以清除
事务中的commands队列
并退出事务
。
>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 'incr' command
这是由于
INCR
命令的语法错误,将在调用EXEC
之前被检测出来,并终止事务(version2.6.5+)。
EXEC
命令之后出现错误。错误的值
对某个key
执行操作(如针对String
值调用List
操作)EXEC
命令执行之后发生的错误并不会被特殊对待:即使事务中的某些命令执行失败,其他命令仍会被正常执行
------WATCH
명령은 트랜잭션 동시성반복 불가능한 읽기 문제를 해결하는 데 사용됩니다. /code> /code> 및 <code>팬텀 읽기
관련 문제(간단히 키
잠금으로 이해됨)
트랜잭션을 명시적으로 시작하고 제어하는 데 사용되며 일련의 명령을 한 단계로 실행할 수 있습니다
. 그리고 두 가지 중요한 보장을 제공합니다: 🎜명령 대기열
이 단일 원자성 작업으로 실행됩니다. 가 없습니다. 명령
명령
이 실행됩니다. 쓰기 작업
을 사용하여 트랜잭션을 디스크에 씁니다. 다운타임이나 프로세스 충돌이 발생하면 서비스가 정상적으로 시작되고 일부 작업을 재개할 수 있도록 redis-check-aof 도구를 사용하여 추가 전용 파일을 복구할 수 있습니다. 🎜MULTI
명령을 사용하여 Redis 트랜잭션을 명시적으로 엽니다
. 이 명령은 항상 OK로 응답합니다. 사용자는 현재 여러 명령을 실행할 수 있지만 Redis는 이러한 명령을 실행하지 않고 대기열에 추가합니다
. EXEC
가 호출되면 모든 명령이 실행됩니다. DISCARD
를 호출하면 트랜잭션의 명령 대기열
을 삭제
하고 트랜잭션을 종료
할 수 있습니다. 🎜>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
가 대기열에 실패함). 🎜구문 오류
(잘못된 매개변수 수, 잘못된 명령 이름...)가 있을 수 있습니다.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命令
可能会执行失败,仅仅是由于错误的语法被调用(命令排队时检测不出来的错误),或者使用错误的数据类型操作某个Key
: 这意味着,实际上失败的命令都是编程错误造成的,都是开发中能够被检测出来的,生产环境中不应该存在。(这番话,彻底甩锅,“都是你们自己编程错误,与我们无关”。)Rollback
,Redis
内部简洁并且更加高效。“如果错误就是发生了呢?”这是一个反对Redis
观点的争论
。然而应该指出的是,通常情况下,回滚并不能挽救编程错误。鉴于没有人能够挽救程序员的错误,并且Redis命令
失败所需的错误类型不太可能进入生产环境,所以我们选择了不支持错误回滚(Rollback)这种更简单快捷的方法。
DISCARD
被用来中止事务。事务中的所有命令将不会被执行,连接将恢复正常状态。
> SET foo 1 OK > MULTI OK > INCR foo QUEUED > DISCARD OK > GET foo "1"
更多编程相关知识,请访问:编程视频!!
위 내용은 Redis의 트랜잭션에 대해 자세히 알아보기의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!