经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 数据库/运维 » Redis » 查看文章
一文了解:Redis事务
来源:cnblogs  作者:阿克西斯教成员污米饭  时间:2019/8/7 8:43:47  对本文有异议

Redis事务

事务提供了一种"将多个命令打包,一次性提交并按顺序执行"的机制,提交后在事务执行中不会中断。只有在执行完所有命令后才会继续执行来自其他客户的消息。

Redis中的使用

Redis通过multi,exec,discard,watch实现事务功能。

  1. multi:开始事务
  2. exec:提交事务并执行
  3. discard:取消事务
  4. watch:事务开始之前监视任意数量的键
  1. > multi
  2. OK
  3. > set bookName "Redis"
  4. QUEUED
  5. > get bookName
  6. QUEUED
  7. > sadd tag "Redis" "New Book"
  8. QUEUED
  9. > smembers tag
  10. QUEUED
  11. > exec
  12. 1) OK
  13. 2) "Redis"
  14. 3) (integer) 2
  15. 4) 1) "Redis"
  16. 2) "New Book"

开始事务

  1. > multi
  2. OK

这个命令将Redis_multi选项打开,让客户端从非事务状态变为事务状态

multi命令

命令入队

  1. > set bookName "Redis"
  2. QUEUED
  3. > get bookName
  4. QUEUED
  5. > sadd tag "Redis" "New Book"
  6. QUEUED
  7. > smembers tag
  8. QUEUED

在事务状态中,Redis命令并不是立即执行的,而是进入一个先进先出的事务队列。QUEUED表示这个命令已经入了事务队列。

执行事务

  1. > exec
  2. 1) OK
  3. 2) "Redis"
  4. 3) (integer) 2
  5. 4) 1) "Redis"
  6. 2) "New Book"

当执行exec命令时,Redis根据客户端所保存的事务队列, 以先进先出的方式执行事务队列中的命令: 最先入队的命令最先执行, 而最后入队的命令最后执行。
当exec命令执行完毕时,Redis会将结果保存到一个回复队列,并将回复队列返回给客户端。客户端从事务状态退出,一个事务执行完毕。

discard命令

  1. > multi
  2. OK
  3. > set author "lisi"
  4. QUEUED
  5. > discard
  6. OK
  7. > get author
  8. (nil)

discard取消一个事务的命令,表示这个事务被取消。客户端从事务状态退出,回到非事务状态,Redis_multi选项关闭。

事务中exec和discard

watch命令

  1. # Redis客户端1
  2. > watch letter
  3. OK
  4. > multi
  5. OK
  6. > set letter a
  7. QUEUED
  8. > exec
  9. (nil)
  10. # Redis客户端2
  11. > set letter b
  12. OK
  13. # Redis客户端1
  14. > get letter
  15. "b"

设置监控letter键,客户端1进入事务,设置letter的value为a,未提交事务。客户端2设置letter的value为b。回到客户端1提交事务返回的结果为nil,调用get命令得到letter为b。这说明当letter键在其他客户端改变后,事务被取消了,不会被执行,返回失败。

watch命令在事务开始之前监视任意数量的键:当调用exce命令执行事务时,如果任意一个被监视的键已经被其他客户端修改了,那么整个事务不再执行,直接返回失败。

watch命令

事务异常

命令错误

  1. > set letter ac
  2. QUEUED
  3. > get letter ac
  4. (error) ERR wrong number of arguments for 'get' command
  5. > exec
  6. (error) EXECABORT Transaction discarded because of previous errors.

事务中命令异常属于语法错误,将导致事务无法执行。

运行时异常

  1. > multi
  2. OK
  3. > lpush books "Redis"
  4. QUEUED
  5. > incr books
  6. QUEUED
  7. > lpush books "Python"
  8. QUEUED
  9. > lrange books 0 -1
  10. QUEUED
  11. > exec
  12. 1) (integer) 1
  13. 2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
  14. 3) (integer) 2
  15. 4) 1) "Python"
  16. 2) "Redis"

上面的例子是事务执行到中间遇到失败了,因为不能对一个字符串进行incr命令,事务在遇到命令执行失败后,后续的命令还继续执行,所以books的值能继续得到设置。这种异常只有程序员在代码中避免。

事务的ACID

原子性

原子意味着要么一起成功执行,要么一起失败回滚。Redis提供的所有API都是原子操作。那么Redis事务只要保证在一批操作中保证原子性,但是在运行时异常中,在一个事务中一个命令出现异常,其他命令还是会继续执行,事务没有回滚机制,所以Redis事务是不保证原子性的。

一致性

事务异常

如果命令错误事务无法执行,如果是运行时异常,Redis会将错误包含在返回结果中,并不影响后续执行,所以事务是一致性的。

Redis进程被终结

在纯内存模式下,Redis没有做持久化,重启之后数据库是空白的,所以是事务一致性的。

在RDB模式下,事务并不会在中途执行保存RDB文件的工作,只有在事务执行完后,RDB工作才可能会开始。所以在事务执行过程中Redis进程被杀死,不管成功多少都不会保存到RDB文件中,所以是一致性的。

在AOF模式下,事务部分语句被写入AOF文件并保存成功,不完整的事务被保存到了AOF文件,当重启Redis时,检查AOF文件不完整,Redis退出并报错。需要把这段不完整的事务删除后才能重启成功,所以是一致性的。

在AOF模式下,事务并未被写入AOF文件,所以重启后Redis数据库是最近一次成功保存到AOF文件中的数据。并没有这次事务的数据,所以是以一致性的。

隔离性

Redis 是单进程程序,并且它保证在执行事务时,不会对事务进行中断,事务可以运行直到执行完所有事务队列中的命令为止。所以事务是带有隔离性的。

持久性

在纯内存模式下,事务肯定不是持续性的。

在RDB模式下,服务器可能在事务执行之后、RDB文件更新之前的这段时间失败,所以 RDB模式下的事务也是不持久的。

在AOF模式下,将命令添加到AOF文件中,但是对文件进行写入并不会马上写到磁盘上,而是先存储到缓冲区。所以数据保存到磁盘上有一段非常小的时间间隔。这种模式下事务也不是持久的。

结语

本人深知水平有限,欢迎指正本文错误之处。

参考资料

《Redis 设计与实现》

《Redis 开发与运维》

《Redis 深度历险:核心原理与应用实践》


欢迎关注公众号:bate喵

专注于Java相关技术:Linux、JVM、SpringCloud、SpringBoot、Docker、Redis、Netty、微服务、高并发等领域,偶尔聊聊学习之道、自控力等方法,致力于成就更好的自己,欢迎大家关注交流,共同成长

原文链接:http://www.cnblogs.com/imeng/p/11307319.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号