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
使用限制
-
不支持事务回滚
假设命令 a、b、c, a和b执行ok,执行到 c 的时候发生异常了,那么 a和b的操作结果是不会回滚的; -
事务内多个命令间不能相互依赖
收到 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 脚本的方式来写
参考: