Redis 事务和Pipeline--JAVA(系列文章三)

本文探讨了Redis中的事务特性,指出其不同于传统数据库的事务处理,没有回滚功能,更像是批处理。介绍了Redis事务的基本命令如watch、unwatch、multi、exec和discard,并展示了使用Jedis进行事务操作的代码示例。同时,文章提到了watch命令在乐观锁中的应用,但指出在高并发场景下可能存在的问题。为了解决这些问题,文章推荐使用setnx命令进行锁操作。此外,文章还讲解了Pipeline的概念,它用于批量操作,速度比事务更快,但需要注意避免阻塞Redis服务器。最后,提供了使用Pipeline的示例。
摘要由CSDN通过智能技术生成

在传统的关系型数据当中,使用事务是我们最常见的操作。来到Redis当中这里有事务吗,Redis是支持事务的。但是这个事务跟关系型数据库的传统事务不一样,在关系型数据库当中我们可以对出现错误的sql进行回滚,但是在redis是没有这一说的。

在Redis事务当中,所有操作都是在提交的统一执行的,所以并没有回归操作,其实这个事务更像是批处理的感觉。以下就是事务常用的命令:

1、watch

2、unwatch

3、multi

4、exec

5、discard


以下就是使用Jedis使用事务的代码:

public static void main(String args[]){

    GenericObjectPoolConfig config = new GenericObjectPoolConfig();
    config.setMaxIdle(8);
    config.setMaxTotal(10);
    config.setMinIdle(2);
    config.setMaxWaitMillis(3000);

    jedisPool = new JedisPool(config, "localhost");

    Jedis conn = jedisPool.getResource();

    Transaction transaction = conn.multi();

    Response<Long> newListPushResult = transaction.rpush("newList","A","B","C");

    Response<List<String>> newListResponse =  transaction.lrange("newList",0,-1);

    transaction.exec();

    System.out.println("newListPushResult : " + newListPushResult.get());

    for (String item : newListResponse.get()) {
        System.err.println( item + " ");
    }

    conn.close();
}

通过代码我们可以看到我们的执行结果是在exec之后才统一返回,所以Jedis会用一个Response对象最为事务对象transaction的执行放回值。如果我们在transaction执行exec方法之前调用response对象的get方法会出现异常:

Exception in thread "main" redis.clients.jedis.exceptions.JedisDataException: Please close pipeline or multi block before calling this method.

事实上我们还可以使用exec方法的返回值获得事务执行过程的结果,但是这个显然是不够方便的:

public static void main(String args[]){

    GenericObjectPoolConfig config = new GenericObjectPoolConfig();
    config.setMaxIdle(8);
    config.setMaxTotal(10);
    config.setMinIdle(2);
    config.setMaxWaitMillis(3000);

    jedisPool = new JedisPool(config, "localhost");

    Jedis conn = jedisPool.getResource();

    Transaction transaction = conn.multi();

    transaction.rpush("newList","A","B","C");

    transaction.lrange("newList",0,-1);

    List<Object> result = transaction.exec();

    System.out.println("newListPushResult : " + result.get(0));

    List<String> newListValues = (List<String>) result.get(1);

    for (String item : newListValues) {
        System.err.println( item + " ");
    }

    conn.close();
}

事务其中最为只要的功能是实现锁,redis提供一个watch命令。watch是一种乐观锁,watch命令的参数为key,当我们watch了一个key的时候,在事务执行之前被修改了,事务是不会执行成功的。只要我们在watch到事务执这段时间未被修改事务才会执行成功。当然如果我们在业务的中途不需要监控这个key的变化了也可以使用unwatch命令进行取消watch。以下是watch在jedis事务代码上的使用(下面会模拟一段购买商品的业务):

public static void main(String args[]){

    GenericObjectPoolConfig config = new GenericObjectPoolConfig();
    config.setMaxIdle(8);
    config.setMaxTotal(10);
    config.setMinIdle(2);
    config.setMaxWaitMillis(3000);

    jedisPool = new JedisPool(config, "localhost");

    Jedis conn = jedisPool.getResource();


    //market 有序集合 score 商品价格  member 商品名称
    conn.zadd("market",100,"ProductA");
    conn.zadd("market",33,"ProductB");

    //用户对象
    conn.hset("user:1","funds","900");

    //监控market和user:1两个KEY的变化
    conn.watch("user:1"
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值