Redis之事务

Redis 事务

正常来说,一个可以商用的数据库往往都有比较完善的事务支持,Redis 当然也不例外。相对于 关系型数据库中的事务模型,Redis 中的事务要简单很多。因为简单,所以 Redis 中的事务模型不太严格,所以我们不能像使用关系型数据库中的事务那样来使用 Redis。
在关系型数据库中,和事务相关的三个指令分别是:

  • begin
  • commit
  • rollback

在 Redis 中,当然也有对应的指令:

  • multi
  • exec
  • discard

1.原子性

注意,Redis 中的事务并不能算作原子性。它仅仅具备隔离性,也就是说当前的事务可以不被其他事务打断。

由于每一次事务操作涉及到的指令还是比较多的,为了提高执行效率,我们在使用客户端的时候,可以通过 pipeline 来优化指令的执行。

Redis 中还有一个 watch 指令,watch 可以用来监控一个 key,通过这种监控,我们可以确保在 exec之前,watch 的键的没有被修改过。

2.java代码实现

public class TransactionTest {
    public Integer saveMoney(Jedis jedis,String userId, Integer money){
        while (true){
            //监控userId,如果userId被修改,则重新执行一次
            jedis.watch(userId);
            System.out.println(jedis.get(userId));
            if (jedis.get(userId)!=null){
                int v=Integer.parseInt(jedis.get(userId))+money;
                Transaction tx = jedis.multi();
                tx.set(userId,String.valueOf(v));
                List<Object> exec = tx.exec();
                if (exec!=null){
                    break;
                }
            }else{
                jedis.append(userId,"0");
                int v=Integer.parseInt(jedis.get(userId))+money;
                Transaction tx = jedis.multi();
                tx.set(userId,String.valueOf(v));
                List<Object> exec = tx.exec();
                if (exec!=null){
                    break;
                }
            }
        }
        return Integer.parseInt(jedis.get(userId));
    }

    public static void main(String[] args) {
        new Redis().execute(jedis -> {
            new TransactionTest().saveMoney(jedis,"zhong",1000);
            System.out.println(jedis.get("zhong"));
        });
    }
}
posted @ 2021-09-11 10:09  Ishton  阅读(40)  评论(0)    收藏  举报