redis相关

redis事务

redis事务本质: 一组命令的集合,一个事务中所有的命令都会被序列化,在事务执行的过程中,会按照顺序执行!
一次性、顺序性、排他性!执行一系列命令。

------ 队列 set set set 执行 -------

redis事务没有隔离级别的概念
所有的命令在事务中并没有直接执行,只有在发起执行命令时才执行!

redis单条命令是原子性的,但事务不保证原子性。

事务的操作

  • 开启事务 (multi)
  • 命令入队 (…)
  • 执行事务 (exec)

正常执行事务!(exec)

127.0.0.1:6379> multi    #    开启事务
OK
127.0.0.1:6379(TX)> set ex1 aaa
QUEUED
127.0.0.1:6379(TX)> set ex2 bbb
QUEUED
127.0.0.1:6379(TX)> set ex1 ccc
QUEUED
127.0.0.1:6379(TX)> get ex1 
QUEUED
127.0.0.1:6379(TX)> exec    #   执行事务
1) OK
2) OK
3) OK
4) "ccc"

放弃事务!(discard)

127.0.0.1:6379> multi    # 开启事务
OK
127.0.0.1:6379(TX)> LPUSH l1 aaa
QUEUED
127.0.0.1:6379(TX)> LPUSH l1 ddd
QUEUED
127.0.0.1:6379(TX)> DISCARD   #取消事务
OK
127.0.0.1:6379> LRANGE l1
(error) ERR wrong number of arguments for 'lrange' command
127.0.0.1:6379> LRANGE l1 0 -1
(empty array)
127.0.0.1:6379> 

编译型错误(代码语法错误)

127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set k1 v1
QUEUED
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> setget k3 v3      #   不存在setget命令,直接报错
(error) ERR unknown command `setget`, with args beginning with: `k3`, `v3`, 
127.0.0.1:6379(TX)> set k4 v4
QUEUED
127.0.0.1:6379(TX)> EXEC     #    执行事务报错
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> get k1    #     此时所有命令都没执行
(nil)
127.0.0.1:6379> 

运行时错误(语法正确,其中一条命令报错,其他命令仍能执行。不能保证原子性

127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379(TX)> INCR k1     #   对字符串进行加一操作
QUEUED
127.0.0.1:6379(TX)> set k2 1
QUEUED
127.0.0.1:6379(TX)> incr key2 
QUEUED
127.0.0.1:6379(TX)> set k3 v3
QUEUED
127.0.0.1:6379(TX)> incr k3     #   对字符串进行加一操作
QUEUED
127.0.0.1:6379(TX)> exec
1) (error) ERR value is not an integer or out of range   #  报错
2) OK
3) (integer) 1
4) OK
5) (error) ERR value is not an integer or out of range   #  报错
127.0.0.1:6379> get k3     #  仍可以正常执行
"v3"

两种锁(mysql)

  • 悲观锁
    很悲观,认为什么时候都会出错,无论做什么都会加锁!
  • 乐观锁
    很乐观,认为什么时候都不会出错,所以不加锁。在更新数据时判断在此期间是否有人修改过数据。通过获取version,在更新时去比较version。

redis监视(watch)面试常问

正常执行成功!

127.0.0.1:6379> set money 100
OK
127.0.0.1:6379> set spend 0
OK
127.0.0.1:6379> watch money    #    监视money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> DECRBY money 30
QUEUED
127.0.0.1:6379(TX)> INCRBY spend 30
QUEUED
127.0.0.1:6379(TX)> exec
1) (integer) 70
2) (integer) 30

遇到线程插队修改数据!(使用watch,可以当做redis的乐观锁操作)

#  第一个客户端
127.0.0.1:6379> WATCH money     #  监视money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> DECRBY money 10
QUEUED
127.0.0.1:6379(TX)> INCRBY spend 10
QUEUED
127.0.0.1:6379(TX)> exec    #  执行之前在第二个客户端修改money值,导致事务执行失败
(nil)
#   第二个客户端模拟线程插队修改数据
127.0.0.1:6379> set money 100     #  修改money
OK

执行失败后可以通过解锁,再加锁去更新监视的值

127.0.0.1:6379> UNWATCH    #   如果执行失败,先解锁
OK
127.0.0.1:6379> WATCH money    #  再次对money上锁,此时money数据为100
OK
127.0.0.1:6379> MULTI 
OK
127.0.0.1:6379(TX)> DECRBY money 500
QUEUED
127.0.0.1:6379(TX)> INCRBY spend 500
QUEUED
127.0.0.1:6379(TX)> exec     #   执行成功
1) (integer) -400
2) (integer) 530

补充: 每次执行exec,不管有没有成功都会释放锁

Jedis

Jedis是Redis官方推荐的java连接开发工具!是Java操作redis的中间件

测试

  1. 导入对应的依赖
<dependencies>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>3.2.0</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.76</version>
        </dependency>
    </dependencies>
  1. 编码测试:
    • 连接数据库
    • 操作命令
    • 断开连接
package com.Junior;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisShardInfo;

public class TestPing {
   
    public static void main(String[] args) {
   
        JedisShardInfo jedisShardInfo = new JedisShardInfo("121.40.46.92", 6379);
        jedisShardInfo.setPassword("Junior");   //通过此方法去加载密码
        Jedis jedis = new Jedis(jedisShardInfo);
        String ping = jedis.ping();
        System.out.println(ping);
    }
}

//   测试结果
PONG

常用的api

  • String
  • List
  • Set
  • Zset
  • Hash
  • Geo
  • Hyperloglog
  • Bitmap

jedis事务

package com.Junior;

import com.alibaba.fastjson.JSONObject;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisShardInfo;
import redis.clients.jedis.Transaction;

public class TestTx {
   
    public static void main(String[] args) {
   
        JedisShardInfo jedisShardInfo = new JedisShardInfo("121.40.46.92", 6379);
        jedisShardInfo.setPassword("Junior");
        Jedis jedis = new Jedis(jedisShardInfo);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("name", "zhangsan");
        jsonObject.put("age",22);
        jedis.flushDB();    //清空数据库
        Transaction multi = jedis.multi();   //开启事务
        String s = jsonObject.toJSONString();
        try {
   
            multi.set("key1",s);
            //int i=1/0;     //    异常代码
            multi.set("key2",s);
            multi.exec();    //执行事务
        } catch (Exception e) {
   
            multi.discard();    //放弃事务
            e.printStackTrace();
        } finally {
   
            System.out.println(jedis.get("key1"));
            System.out.println(jedis.get("key2"));
            jedis.close();   //关闭连接
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值