redis事务与管道

redis事务与管道

事务

Redis事务允许在一次单独的步骤中执行一组命令,Reids事务有两个属性:

  • 事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
  • Redis事务是原子的。原子意味着要么所有的命令都执行,要么都不执行(执行出错也算执行);

事务相关命令如下:

  • MULTI: 开启事务,之后的命令会加入命令队列,命令不会立即执行。
  • EXEC: 将命令队列中的所有命令顺序执行。执行结束自动关闭事务。
  • DISCARD: 取消事务。不会执行事务中命令,并关闭事务。
  • WATCH: 监控指定key,如果在WATCH后,EXEC前,指定key的值发生变化,那么事务运行失败。
  • UNWATCH: 取消对所有key的监控。

事务示例:银行转账,邓超给宝强转账1万元:

127.0.0.1:6379> set dengchao 60000
OK
127.0.0.1:6379> set wangbaoqiang 200
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> INCRBY dengchao -10000
QUEUED
127.0.0.1:6379> INCRBY wangbaoqiang 10000
QUEUED
127.0.0.1:6379> EXEC
1) (integer) 50000
2) (integer) 10200
127.0.0.1:6379>

因为在执行EXEC前,所有的命令都只是加入到命令队列中,即所有命令都还没有真正执行,所以在EXEC之前出现问题(redis-cli连接断开,DISCARD等),那么所有命令均不会执行:

127.0.0.1:6379> set dengchao 100
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> INCR dengchao
QUEUED
127.0.0.1:6379> exit
root@0528a4f2a0ss:/data# redis-cli
127.0.0.1:6379> get dengchao
"100"

如果在执行EXEC前出现可检查的语法错误等,事务会报错并且不执行。(在2.6.5版本前,事务不会报错,redis会将执行被添加到任务队列中的命令):

127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> sett dengchao 1
(error) ERR unknown command `sett`, with args beginning with: `dengchao`, `1`,
127.0.0.1:6379> set wangbaoqiang 2
QUEUED
127.0.0.1:6379> EXEC
(error) EXECABORT Transaction discarded because of previous errors.

如果EXEC后出现问题(非进程异常类),如类型操作错误,那么错误的语句不会影响其他命令的执行。

127.0.0.1:6379> set dengchao car
OK
127.0.0.1:6379> set wangbaoqiang air
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set dengchao 100
QUEUED
127.0.0.1:6379> INCR wangbaoqiang
QUEUED
127.0.0.1:6379> set dengchao 200
QUEUED
127.0.0.1:6379> EXEC
1) OK
2) (error) ERR value is not an integer or out of range
3) OK
127.0.0.1:6379> get dengchao
"200"
127.0.0.1:6379> get wangbaoqiang
"air"

如果EXEC后出现问题(进程异常类),如进程异常关闭,机器异常重启或断电,那么可能会出现没有执行完全部命令的情况。当使用AOF持久化时,Redis重新启动时会检查上述状态,然后退出运行,并且输出报错信息。可以使用redis-check-aof工具修复上述的只增文件,这个工具将会从上述文件中删除执行不完全的事务,这样Redis服务器才能再次启动。

pipeline 管道

通常情况下,客户端执行多条命令,每条命令会单独网络发送,并且如果在一个同步线程内,下一条命令会等待上一条返回结果后再回执行。那么命令越多,所产生的网络时延越多。
如果不需要立即获得每一条命令的结果,那么可以使用管道来一次发送并执行多个命令,管道完全是客户端的行为,管道的主要目的是将多个网络请求合并为一个请求,减少网络时延。

与事务不同的是:

  • 管道是客户端行为
  • 事务可以保证原子性,即事务执行前检测到有问题,那么事务中的所有命令都不会执行。管道不会进行命令检测,同时没有WATCH操作。
  • 事务中的命令执行时会阻塞其他客户端的命令,而管道不会。

与事务相同的是:

  • 两者都可以批量执行命令。
  • 事务执行时发生错误,均不会影响之前生效的命令,也不会影响后面的命令执行。

管道的原子性:
管道的原子性取决于客户端,例如默认情况下,python的redis pipeline可以保证执行的原子性,但是也可以通过pipe = r.pipeline(transaction=False) 来禁用这一特性。

参考

https://piaosanlang.gitbooks.io/redis/content/05_transaction.html
https://blog.csdn.net/u013967628/article/details/84501515

你可能感兴趣的:(后端,redis,队列,redis)