Pipeline
概念
Redis 客户端执行一条命令分为如下四个过程:
-
发送命令
-
命令排队
-
命令执行
-
返回结果
其中1) +4) 称为 Round Trip Time(RTT, 往返时间) 。
Pipeline(流水线) 将一组 Redis 命令进行组装, 通过一次 RTT 传输给 Redis, 再将这组Redis命令的执行结果按顺序,Pipeline只能操作一个Redis实例。
每个命令在管道中是原子执行的,但整个管道中的命令并不具有事务的 ACID(原子性、一致性、隔离性、持久性)特性。如果在管道执行期间出现错误,服务器将中止执行,但已执行的命令不会回滚。
管道适用于需要高性能批量执行命令的场景,但并不提供事务的原子性和隔离性。
Pipeline 使用方法
-
将要执行的多个 Redis 命令按照 Redis 协议的格式编码,并通过管道发送给 Redis 服务器。
-
Redis 服务器收到命令后会将它们暂时保存在内存中,而不是立即执行。
-
客户端可以继续向服务器发送其他命令,或者等待执行结果。
-
当客户端需要获取管道中各个命令的执行结果时,可以通过一次性读取服务器的响应来获取所有命令的执行结果。
原生批量与 Pipiline 区别
-
原生批量命令是原子的, Pipeline是非原子的。
-
原生批量命令是一个命令对应多个key, Pipeline支持多个命令。
-
原生批量命令是Redis服务端支持实现的, 而Pipeline需要服务端和客户端的共同实现。
example:
echo -en '*3\r\n$3\r\nSET\r\n$5\r\nkey1\r\n$5\r\nvalue\r\n*3\r\n$3\r\nSET\r\n$5\r\nkey2\r\n$5\r\nvalue\r\n' | redis-cli --pipe
事务
事务是通过 MULTI、EXEC、DISCARD 和 WATCH 等命令实现的。事务中的命令在 MULTI 和 EXEC 之间排队,然后一起原子性地执行,最后通过 EXEC 提交事务。
事务提供原子性操作,要么所有的命令都执行成功,要么所有的命令都失败。这符合 ACID 特性,确保了一组命令的原子性。
事务适用于需要一组命令以原子方式执行的场景,例如将多个命令作为一个逻辑单元执行。
Redis提供了简单的事务功能, 将一组需要一起执行的命令放到 multi
和 exec
两个命令之间。 multi
命令代表事务开始, exec
命令代表事务结束, 它们 之间的命令是原子顺序执行的:
example:
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set num 1
QUEUED
127.0.0.1:6379(TX)> incr num
QUEUED
127.0.0.1:6379(TX)> exec
1) OK
2) (integer) 2
只有当 exec
执行后, 用户A关注用户B的行为才算完成
如果要停止事务的执行, 可以使用 discard
命令代替 exec
命令即可。
127.0.0.1:6379> discard
OK
watch
Redis并不支持回滚功能,有些应用场景需要在事务之前, 确保事务中的key没有被其他客户端修改过, 才执行事务, 否则不执行(类似乐观锁) 。 Redis提供了watch
命令来解决这类问题。
watch key [key ...]
总结:
-
性能: 管道通常比事务执行速度更快,因为它批量发送和接收响应,减少了往返时间。
-
原子性: 事务提供原子性保证,而管道中的命令在整体上并不具备原子性。
-
应用场景: 使用管道时,要注意一组命令之间的独立性,而事务更适用于需要一组命令以原子方式执行的场景。
参考资料:《Redis 开发与运维》