为了保证多条命令组合的原子性,Redis提供了简单的事务功能以及集成Lua脚本来解决这个问题。本节首先简单介绍Redis中事务的使用方法,以及它的局限性,之后重点介绍Lua语言的基本使用方法,以及如何将Redis与Lua脚本进行集成。
事务
熟悉关系型数据库的同学应该对事务比较了解,简单的说事务代表一组动作,要么全部执行,要么全部不执行。例如,A给B转账100,首先,从A的账户减100,然后给B的账户加100,这两个行为要么全部执行,要么全部不执行,否则会出现数据不一致的情况。
Redis提供了简单的事务功能,将一组需要一起执行的命令放到multi和exec两个命令直接。multi命名代表事务开始,exec命名代表事务结束,它们之间的命令是原子顺序执行的。
例如:
multi
set a 100
set b 100
exec
只有当exec命令执行后,
如果要停止事务的执行,可以使用discard命令代替exec命令即可。
如果事务执行中间出错,Redis并不支持 回滚功能。
有些应用场景需要在事务之前,确保事务中的key没有被其它客户端修改过,才执行事务,否则不执行(类似乐观锁)。Redis提供了watch命令来解决这类问题。
Jedis Transaction使用
添加maven依赖:
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
在Jedis中使用事务,代码如下:
jedis.watch (key1, key2, ...);
Transaction t = jedis.multi();
t.set("foo", "bar");
t.exec();
如果事务包含的方法有返回值,可以这么做:
Transaction t = jedis.multi();
t.set("fool", "bar");
Response<String> result1 = t.get("fool");
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
int soseSize = sose.get().size(); // on sose.get() you can directly call Set methods!
// List<Object> allResults = t.exec(); // you could still get all results at once, as before
网友评论