Redis事务

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

Redis事务没有隔离级别的概念,所有的命令在事务中没有被直接执行,只有发起执行命令的时候才会执行 Exec

Redis事务本质:一组命令的集合,一个事务中的所有的命令都会被序列化,在事务执行过程中,会按照顺序执行。
在这里插入图片描述

三个特性

一次性、顺序性、排他性

Redis事务

  1. 开启事务(multi)
  2. 命令入队(…)
  3. 执行事务(exec)
    在这里插入图片描述
    执行完一组就要重新开启

放弃事务
在这里插入图片描述

编译型异常(代码有问题!命令有错! ),事务中所有的命令都不会被执行!
在这里插入图片描述

运行时异常(1/0),如果事务队列中存在语法性错误,那么执行命令的时候,其他命令是可以正常执行的,错误命令抛出异常!
在这里插入图片描述

原子性定义:1.要么全部执行成功,要么异常全不执行;2.异常发生后,可以回滚,就像没执行过一样;Redis事务异常以后其他命令依旧执行,没有发生回滚,Redis大部分是命令语法错误引发异常。

监控(Watch)

悲观锁:
很悲观,无论执行什么操作都会出现问题,所以会对所有的操作加锁
乐观锁
很乐观,任何情况下都不会出问题,所以不会加锁!但是在数据更新时需要判断在此之前是否有人修改过这个数据
可以添加一个字段叫version用来查询(标记号)
在进行数据更新时对version进行比较
测试多线程修改值,使用watch可以当做redis的乐观锁操作!

Redis监视测试
在这里插入图片描述

127.0.0.1:6379> WATCH money
OK
127.0.0.1:6379> MULTI 
OK
127.0.0.1:6379> DECRBY money 30
QUEUED
127.0.0.1:6379> INCRBY out 30
QUEUED
# 这个时候开始模拟另外一个客户端恶意修改被监控的key
# =======================================================表示另一个客户端==============================================================
127.0.0.1:6379> get money
"80"
127.0.0.1:6379> INCRBY money 200 # 修改被监控的数据
(integer) 280
127.0.0.1:6379> get money
"280"
# ===================================================================================================================================
# 再次执行事务,会直接返回nil,代表执行失败
127.0.0.1:6379> EXEC 
(nil)
127.0.0.1:6379> get money # 再次查看,当前监控的key已经被修改
"280"
# 多聊一嘴:实际上关于WATCH,还有一个命令,UNWATCH,意思是解除所有监控,但是官网的原话是,一旦你执行了DISCARD或者EXEC,就没必要在执行UNWATCH
127.0.0.1:6379> MGET money out
1) "280"
2) "20"
127.0.0.1:6379> WATCH money 
OK
127.0.0.1:6379> MULTI 
OK
127.0.0.1:6379> DECRBY money 30 
QUEUED
127.0.0.1:6379> INCRBY out 30
QUEUED
127.0.0.1:6379> EXEC 
1) (integer) 250
2) (integer) 50

如果修改失败获取最新的值
在这里插入图片描述

Jedis

什么是Jedis
Jedis是Redis官方推荐的Java连接Redis的连接开发工具!使用Java操作Redis的中间件

<!--导入Jedis-->
<dependency>
  <groupId>redis.clients</groupId>
  <artifactId>jedis</artifactId>
  <version>3.2.0</version>
</dependency>
<!--fastjson-->
<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>fastjson</artifactId>
  <version>1.2.70</version>
</dependency>

编码测试

  1. 连接数据库
  2. 操作命令
  3. 断开连接

先在服务器中开放安全组6379端口,之后
2.xshell连接服务器。然后输入ifconfig

得到以下的图片
在这里插入图片描述
这两个ip请记住,尤其第一个,第二个是默认的。
3.使用vim打开redis.conf (文件目录自己清楚)
然后找到bind 配置第二步找到的ip地址。

如图
在这里插入图片描述
运行:wq!保存
之后重启redis
在这里插入图片描述


import redis.clients.jedis.Jedis;

public class TestPing {
    public static void main(String[] args) {
        // new一个Jedis对象
        Jedis jedis = new Jedis("121.4.127.10", 6379);
        // Jedis中的API就是之前学习的命令
        System.out.println(jedis.ping());
        System.out.println("清空数据"+jedis.flushDB());

        // String
        System.out.println(jedis.set("k1", "v1"));
        System.out.println(jedis.get("k1")); // v1
        System.out.println(jedis.append("k1", "+value"));
        System.out.println(jedis.get("k1")); // v1+value
        System.out.println(jedis.strlen("k1")); // 8
        System.out.println("=====================================================");
        // List
        System.out.println(jedis.lpush("listKey", "l1", "l2", "l3"));
        System.out.println(jedis.lrange("listKey", 0, -1)); // [l3, l2, l1]
        System.out.println(jedis.llen("listKey"));
        System.out.println("=====================================================");
        // Hash
        System.out.println(jedis.hset("hashKey", "k1", "v1"));
        System.out.println(jedis.hset("hashKey", "k2", "v2"));
        System.out.println(jedis.hset("hashKey", "k3", "v3"));
        System.out.println(jedis.hmget("hashKey", "k1", "k2", "k3")); // [v1, v2, v3]
        System.out.println(jedis.hgetAll("hashKey")); // {k3=v3, k2=v2, k1=v1}
        System.out.println("=====================================================");
        // Set
        System.out.println(jedis.sadd("setKey", "s1", "s2", "s3", "s4"));
        System.out.println(jedis.smembers("setKey")); // [s2, s1, s4, s3]
        System.out.println(jedis.scard("setKey"));
        System.out.println("=====================================================");
        // ZSet
        System.out.println(jedis.zadd("ZKey", 90, "z1"));
        System.out.println(jedis.zadd("ZKey", 80, "z2"));
        System.out.println(jedis.zadd("ZKey", 85, "z3"));
        System.out.println(jedis.zrange("ZKey", 0, -1)); // [z2, z3, z1]
    }
}
PONG
清空数据OK
OK
v1
8
v1+value
8
=====================================================
3
[l3, l2, l1]
3
=====================================================
1
1
1
[v1, v2, v3]
{k3=v3, k1=v1, k2=v2}
=====================================================
4
[s4, s1, s3, s2]
4
=====================================================
1
1
1
[z2, z3, z1]

Process finished with exit code 0

事务

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

public class TestTx {
    public static void main(String[] args) {
        Jedis jedis = new Jedis("192.168.1.107", 6379);
        jedis.flushDB();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("name", "xiaohuang");
        jsonObject.put("age", "21");
        jsonObject.put("sex", "boy");
        Transaction multi = jedis.multi(); //  开启事务
        String user = jsonObject.toJSONString();
        try {
            multi.set("user1", user);
            multi.set("user2", user);
            multi.exec();
        } catch (Exception e) {
            multi.discard(); // 出现问题,放弃事务
            e.printStackTrace();
        } finally {
            System.out.println(jedis.mget("user1", "user2"));
            jedis.close(); // 关闭连接
        }
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值