博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
redis-事务
阅读量:5968 次
发布时间:2019-06-19

本文共 1810 字,大约阅读时间需要 6 分钟。

hot3.png

 

Redis 在形式上看起来也差不多,分别是 multi/exec/discard。multi 指示事务的开始,exec 指示事务的执行,discard 指示事务的丢弃。因为 Redis 的单线程特性,它不用担心自己在执行队列的时候被其它指令打搅,可以保证他们能得到的「原子性」执行。

 Redis 的事务根本不能算「原子性」,而仅仅是满足了事务的「隔离性」,隔离性中的串行化——当前执行的事务有着不被其它事务打断的权利。

Redis 为事务提供了一个 discard 指令,用于丢弃事务缓存队列中的所有指令,在 exec 执行之前。

> get books(nil)> multiOK> incr booksQUEUED> incr booksQUEUED> discardOK> get books(nil)

我们可以看到 discard 之后,队列中的所有指令都没执行,就好像 multi 和 discard 中间的所有指令从未发生过一样。

Redis 提供了这种 watch 的机制,它就是一种乐观锁。有了 watch 我们又多了一种可以用来解决并发修改的方法

watch 会在事务开始之前盯住 1 个或多个关键变量,当事务执行时,也就是服务器收到了 exec 指令要顺序执行缓存的事务队列时,Redis 会检查关键变量自 watch 之后,是否被修改了 (包括当前事务所在的客户端)。如果关键变量被人动过了,exec 指令就会返回 null 回复告知客户端事务执行失败,这个时候客户端一般会选择重试。

注意事项

Redis 禁止在 multi 和 exec 之间执行 watch 指令,而必须在 multi 之前做好盯住关键变量,否则会出错。

下面我们再使用 Java 语言实现一遍。

import java.util.List;import redis.clients.jedis.Jedis;import redis.clients.jedis.Transaction;public class TransactionDemo {  public static void main(String[] args) {    Jedis jedis = new Jedis();    String userId = "abc";    String key = keyFor(userId);    jedis.setnx(key, String.valueOf(5));  # setnx 做初始化    System.out.println(doubleAccount(jedis, userId));    jedis.close();  }  public static int doubleAccount(Jedis jedis, String userId) {    String key = keyFor(userId);    while (true) {      jedis.watch(key);      int value = Integer.parseInt(jedis.get(key));      value *= 2; // 加倍      Transaction tx = jedis.multi();      tx.set(key, String.valueOf(value));      List res = tx.exec();      if (res != null) {        break; // 成功了      }    }    return Integer.parseInt(jedis.get(key)); // 重新获取余额  }  public static String keyFor(String userId) {    return String.format("account_%s", userId);  }}

redis为什么不支持回滚?

不支持回滚操作是因为redis是先执行指令然后做日志,所以即使发生异常,没有可以用来执行回滚操作的日志。所以这也回答了上篇文章的第二问,为什么传统的数据库都是先做日志然后再做操作。

 

转载于:https://my.oschina.net/u/3098425/blog/2996174

你可能感兴趣的文章
电信网络拓扑图自动布局
查看>>
C#中List〈string〉和string[]数组之间的相互转换
查看>>
洛谷P1108 低价购买[DP | LIS方案数]
查看>>
通达信里的统计函数及区块背景函数
查看>>
redis主从配置<转>
查看>>
8 行 Node.js 代码实现代理服务器
查看>>
水印,图片验证码
查看>>
C#编程(七十六)----------使用指针实现基于栈的高性能数组
查看>>
PostgreSql 分页limit
查看>>
在MySQL中创建cm-hive使用的数据库及账号
查看>>
linux下限制ip访问
查看>>
linux添加环境变量
查看>>
Dumpsys Input Diagnostics
查看>>
ASP.NET MVC 入门8、ModelState与数据验证
查看>>
Understanding the Router
查看>>
组件居中显示 安卓
查看>>
delete
查看>>
sql server生成不重复的时间字符串
查看>>
DataBase 之 数据库设计六大范式
查看>>
比特币钱包安全
查看>>