P21 Redis事务
Redis单条命令是保存原子性的,但是事务不保证原子性
Redis事务本质:一组命令的集合,一个事务中所有命令都会被序列化,
在事务执行过程中按照顺序执行
-----队列 set xx set xx set xx 执行----
Redis事务没有隔离级别的概念
Redis的事务:
1.开启事务(multi)
2.命令入队()
3.执行事务(exec)
– 先输入multi开启事务,然后输入要在事务中执行的操作,然后exec执行事务
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set key1 xuse
QUEUED
127.0.0.1:6379(TX)> set key2 fden
QUEUED
127.0.0.1:6379(TX)> get key2
QUEUED
127.0.0.1:6379(TX)> set key3 xueheng
QUEUED
127.0.0.1:6379(TX)> exec
- OK
- OK
- “fden”
- OK
– 放弃事务:discard
先multi开启事务,输入之后,再输入discard就放弃事务了,
事务队列中的所有命令都不会被执行。
1.编译型异常(代码有问题,命令有错),事务中所有命令都不会被执行
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set key1 xs
QUEUED
127.0.0.1:6379(TX)> set key2 fd
QUEUED
127.0.0.1:6379(TX)> get key1
QUEUED
127.0.0.1:6379(TX)> set key3
(error) ERR wrong number of arguments for ‘set’ command #出现异常
127.0.0.1:6379(TX)> set key3 fdxs
QUEUED
127.0.0.1:6379(TX)> exec
(error) EXECABORT Transaction discarded because of previous errors. #所有命令都不会被执行
2.运行时异常(1/0), 如果事务队列中存在运行时错误,那么其他命令是可以正常执行,错误的命令抛异常
127.0.0.1:6379> set key1 “v1”
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> INCR key1 #字符串不能自增1,运行时会报错
QUEUED
127.0.0.1:6379(TX)> set key2 v2
QUEUED
127.0.0.1:6379(TX)> set key3 v3
QUEUED
127.0.0.1:6379(TX)> exec
- (error) ERR value is not an integer or out of range
- OK
- OK
127.0.0.1:6379> get key2 #不影响其他的命令
“v2”
P22 Redis实现乐观锁
1.悲观锁
很悲观,认为什么时候都会出问题,无论做什么都会加锁
2.乐观锁
很乐观,认为什么时候都不会出现问题,所以不会上锁。更新数据的时候去判断一下,在此期间是否有人修改过这个数据
监控:Watch,相当于乐观锁(面试常问)
127.0.0.1:6379> get money
“170”
127.0.0.1:6379> WATCH money #监控money,监控完每次更新会对money的值做比较,如果变了则改变money的事务会失败
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> INCRBY money 20
QUEUED
127.0.0.1:6379(TX)> exec
(nil) #另一个线程修改了money,事务失败
如果修改失败,那么就先unwatch解锁,再重新监控
P23 Jedis
1.导入对应的依赖
<!-- https://mvnrepository.com/artifact/redis.clients/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.62</version>
</dependency>
2.测试连接
public static void main(String[] args) {
Jedis jedis = new Jedis("127.0.0.1", 6379);
System.out.println(jedis.ping());
}
输出:PONG
常用API:
String
List
Set
Zset
Hash
Redis事务
package com.xus;
import com.alibaba.fastjson.JSONObject;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;
/**
-
Redis事务
*/
public class TestTX {
public static void main(String[] args) {
Jedis jedis = new Jedis(“127.0.0.1”, 6379);
JSONObject json = new JSONObject();
json.put(“user1”,“xusheng”);
json.put(“user2”, “fengding”);
String result = json.toJSONString();jedis.flushDB(); Transaction multi = jedis.multi(); try { multi.set("key11", result); int a = 1/0; //代码抛出异常 multi.set("key21", result); multi.exec();//执行事务 } catch (Exception e) { multi.discard();//放弃事务 }finally { System.out.println(jedis.get("key11")); jedis.close();//关闭连接 }
}
}