redis不完整的事务实现Transaction

使用场景

redis一个命令执行是单线程的,不用担心并发冲突,如果你想有几个命令想像一个命令一样,在这几个命令执行过程中不会执行别的客户端发来的命令 ,也就是原子性,就可以用 redis Transaction

使用方式

redis 命令

multi // 标识事务起始
command-1
command-2
command-3
exec  // 开始执行 

redis-server 再接收到 exec 命令的时候,才真正开始顺序执行事务里的命令,然后返回全部命令执行结果
可以用 discard 命令取消事务

使用 Jedis 执行 Transaction (官方例子)
jedis的api和原始 redis 命令非常贴近,没有什么学习成本 知道redis command就会用

Transaction t = jedis.multi();
t.set("fool", "bar"); 
Response<String> result1 = t.get("fool");  // 这边的response 现在还是空的, 再exec后才能获取到实际的值
t.zadd("foo", 1, "barowitch"); 
t.zadd("foo", 0, "barinsky"); 
t.zadd("foo", 0, "barikoviev");
Response<Set<String>> sose = t.zrange("foo", 0, -1);   // get the entire sortedset
t.exec();                                              // dont forget it 

String foolbar = result1.get();                       // use Response.get() to retrieve things from a Response

使用限制

  1. 不支持事务回滚
    假设命令 a、b、c, a和b执行ok,执行到 c 的时候发生异常了,那么 a和b的操作结果是不会回滚的;

  2. 事务内多个命令间不能相互依赖
    收到 exec 后 redis-server 才开始执行,执行完毕后返回所有结果; 所以事务内多个命令之间不能有依赖,如 command-1 的返回值,不能作为下一个 command-2 的输入,因为此时获取不到结果

错误示范

Transaction t = jedis.multi();
if(t.get("key1").equals("something"))   // exec之前这边是拿不到结果的 
   t.set("key2", "value2");
else 
   t.set("key", "value");

t.exec();

如果多个命令间有依赖 或者要做异常处理,并且需要原子执行,可以考虑用 script lua 脚本的方式来写

参考:

本文来自博客园,作者:mushishi,转载请注明原文链接:https://www.cnblogs.com/mushishi/p/14926012.html

原文地址:https://www.cnblogs.com/mushishi/p/14926012.html