素手烹茶|Redis 事务也叫事务吗?,不支持原子性的

推荐学习Redis让我凉在美团一面 , 摸爬滚打3个月 , 二战逆袭成功斩获Offer真真香!耗时大半个月收整全套「Java架构进阶pdf」没白费假设现在有这样一个业务 , 用户获取的某些数据来自第三方接口信息 , 为避免频繁请求第三方接口 , 我们往往会加一层缓存 , 缓存肯定要有时效性 , 假设我们要存储的结构是hash(没有String的'SETanotherkey"willexpireinaminute"EX60'这种原子操作) , 我们既要批量去放入缓存 , 又要保证每个key都加上过期时间(以防key永不过期) , 这时候事务操作是个比较好的选择
为了确保连续多个操作的原子性 , 我们常用的数据库都会有事务的支持 , Redis也不例外 。 但它又和关系型数据库不太一样 。
每个事务的操作都有begin、commit和rollback , begin指示事务的开始 , commit指示事务的提交 , rollback指示事务的回滚 。 它大致的形式如下
begin();try{command1();command2();....commit();}catch(Exceptione){rollback();}Redis在形式上看起来也差不多 , 分为三个阶段
开启事务(multi)命令入队(业务操作)执行事务(exec)或取消事务(discard)>multiOK>incrstarQUEUED>incrstarQUEUED>exec(integer)1(integer)2上面的指令演示了一个完整的事务过程 , 所有的指令在exec之前不执行 , 而是缓存在服务器的一个事务队列中 , 服务器一旦收到exec指令 , 拆开执行整个事务队列 , 执行完毕后一次性返回所有指令的运行结果 。
Redis事务可以一次执行多个命令 , 本质是一组命令的集合 。 一个事务中的所有命令都会序列化 , 按顺序地串行化执行而不会被其它命令插入 , 不许加塞 。
可以保证一个队列中 , 一次性、顺序性、排他性的执行一系列命令(Redis事务的主要作用其实就是串联多个命令防止别的命令插队)
官方文档是这么说的
事务可以一次执行多个命令 , 并且带有以下两个重要的保证:
事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行 。 事务在执行的过程中 , 不会被其他客户端发送来的命令请求所打断 。 事务是一个原子操作:事务中的命令要么全部被执行 , 要么全部都不执行
这个原子操作 , 和关系型DB的原子性不太一样 , 它不能完全保证原子性 , 后边会介绍 。
Redis事务的几个命令
另一方面 , 通过调用DISCARD , 客户端可以清空事务队列 , 并放弃执行事务 。
废话不多说 , 直接操作起来看结果更好理解~
一帆风顺正常执行(可以批处理 , 挺爽 , 每条操作成功的话都会各取所需 , 互不影响)
事务中的错误上边规规矩矩的操作 , 看着还挺好 , 可是事务是为解决数据安全操作提出的 , 我们用Redis事务的时候 , 可能会遇上以下两种错误:
事务在执行EXEC之前 , 入队的命令可能会出错 。 比如说 , 命令可能会产生语法错误(参数数量错误 , 参数名错误等等) , 或者其他更严重的错误 , 比如内存不足(如果服务器使用maxmemory设置了最大内存限制的话) 。 命令可能在EXEC调用之后失败 。 举个例子 , 事务中的命令可能处理了错误类型的键 , 比如将列表命令用在了字符串键上面 , 诸如此类 。Redis针对如上两种错误采用了不同的处理策略 , 对于发生在EXEC执行之前的错误 , 服务器会对命令入队失败的情况进行记录 , 并在客户端调用EXEC命令时 , 拒绝执行并自动放弃这个事务(Redis2.6.5之前的做法是检查命令入队所得的返回值:如果命令入队时返回QUEUED , 那么入队成功;否则 , 就是入队失败)


推荐阅读