Redis入门第三天:主要介绍了如何用idea连接redis、Redis事务以及Redis分布式锁的相关内容。
Redis
IDEA连接Redis
安装
首先先要下载驱动包,确保下载合适的驱动包下载jar包
在classpath中包含此驱动包
测试连接
1import redis.clients.jedis.Jedis;
2
3public class jedisUtils {
4 public static void main(String[] args) {
5 Jedis jedis = new Jedis("localhost");
6 System.out.println("连接成功");
7 System.out.println("服务正在运行"+jedis.ping());
8 }
9}
结果:
存储数据
1import redis.clients.jedis.Jedis;
2
3import java.util.Iterator;
4import java.util.List;
5import java.util.Set;
6
7public class RedisTest {
8 public static void main(String[] args) {
9 // 连接到本地的redis服务
10 Jedis jedis = new Jedis("127.0.0.1");
11 System.out.println("连接成功");
12 System.out.println("服务器正在运行"+jedis.ping());
13 // 设置redis 字符串数据
14 jedis.set("name","zhonghu");
15 System.out.println("redis 存储的字符串为:"+jedis.get("name"));
16 System.out.println("============================================");
17 // 设置redis list数据
18 jedis.lpush("list","redis");
19 jedis.lpush("list","java");
20 jedis.lpush("list","zhonghu");
21 // 获取存储的数据并输出
22 List<String> list = jedis.lrange("list",0,2);
23 for(String i:list){
24 System.out.println(i);
25 }
26 System.out.println("============================================");
27 // 设置redis set数据
28 jedis.sadd("set","hello");
29 jedis.sadd("set","world");
30 jedis.sadd("set","zhonghu");
31 // 获取数据并输出
32 Set<String> keys=jedis.smembers("set");
33 // 定义迭代器输出
34 Iterator<String> it = keys.iterator();
35 while (it.hasNext()){
36 System.out.println(it.next());
37 }
38 }
39}
结果
Redis 事务
事务介绍
Redis事务是通过MULTI,EXEC,DISCARD和WATCH这四个命令来完成的
Redis的单个命令都是原子性的,所以这里确保事务性的对象是命令集合
Redis将命令集合序列化并确保处于 事务的命令集合连续且不被打断的执行
Redis不支持回滚的操作
相关命令
MULTI
用于标记事务块的开始
- Redis会将后续的命令逐个放入队列中,然后使用EXEC命令原子化的执行这个命令序列
EXEC
在一个事务中执行所有先前放入队列的命令,然后恢复正常的连接状态
DISCARD
清除所有先前在一个事务中放入队列的命令,然后恢复正常连接状态
WATCH
当某个事务需要按条件执行时,就需要这个命令将给定的键设置为受监控的状态
语法:
- WATCH key [key …]
可以实现Redis的乐观锁
UNWARCH
清楚所有先前为一个事务监控的锁
Demo
标记开始与执行
监控
在Redis中使用watch可以决定事务时执行还是回滚,
在MULTI 命令前使用watch监控某些键值对,然后使用multi命令开启事务,执行各类对数据结构进行操作的命令,这些命令就会进入队列
当Redis使用EXEC命令执行事务的时候,首先会去对比被watch命令所监控的键值对
发生变化就不会执行任何事务中的命令,而是去回滚事务
不发生变化就执行事务队列中的命令、提交事务
无论事务是否回滚,Redis都会去取消执行事务前的watch命令
Redis为什么不支持回滚
大多数事务失败都是语法错误或者类型错误,都是可以在开发阶段进行避免的
Redis为了性能方面,忽略了事务回滚
Redis实现分布式锁
锁的处理
单应用中使用锁:单线程多线程
- synchronize lock
分布式应用中使用锁:多线程
分布式锁的实现方式
数据库的乐观锁
给予zookeeper的分布式锁
给予redis的分布式锁
分布式锁的注意事项
互斥性:在任意时刻,只有一个客户端能持有锁
同一性:加锁和解锁必须是同一个客户端,客户端子集不能把别人加的锁给解了
避免死锁:即使只有一个客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续其他客户端能加锁
实现分布式锁
获取锁
方式一:使用set命令
- SET KEY VALUE [EX seconds] [PX milliseconds] [NX|XX]
- - EX seconds:设置指定的到期时间 秒
PX milliseconds:设置指定的到期时间 毫秒
NX:仅在键不存在时设置键
XX:只有在键已存在时才设置
方式二:使用setnx命令:先拿setnx来抢锁,抢到后再用expire给锁加一个过期时间防止锁忘记释放
1package com.cyb.redis.utils;
2
3import redis.clients.jedis.Jedis;
4import redis.clients.jedis.JedisPool;
5
6public class jedisUtils {
7 private static String ip = "192.168.31.200";
8 private static int port = 6379;
9 private static JedisPool pool;
10 static {
11 pool = new JedisPool(ip, port);
12 }
13 public static Jedis getJedis() {
14 return pool.getResource();
15 }
16 public static boolean getLock(String lockKey, String requestId, int timeout) {
17 //获取jedis对象,负责和远程redis服务器进行连接
18 Jedis je=getJedis();
19 //参数3:NX和XX
20 //参数4:EX和PX
21 String result = je.set(lockKey, requestId, "NX", "EX", timeout);
22 if (result=="ok") {
23 return true;
24 }
25 return false;
26 }
27
28 public static synchronized boolean getLock2(String lockKey, String requestId, int timeout) {
29 //获取jedis对象,负责和远程redis服务器进行连接
30 Jedis je=getJedis();
31 //参数3:NX和XX
32 //参数4:EX和PX
33 Long result = je.setnx(lockKey, requestId);
34 if (result==1) {
35 je.expire(lockKey, timeout); //设置有效期
36 return true;
37 }
38 return false;
39 }
40}
释放锁
1package com.cyb.redis.utils;
2
3import redis.clients.jedis.Jedis;
4import redis.clients.jedis.JedisPool;
5
6public class jedisUtils {
7 private static String ip = "192.168.31.200";
8 private static int port = 6379;
9 private static JedisPool pool;
10 static {
11 pool = new JedisPool(ip, port);
12 }
13 public static Jedis getJedis() {
14 return pool.getResource();
15 }
16 /**17 * 释放分布式锁18 * @param lockKey19 * @param requestId20 */
21 public static void releaseLock(String lockKey, String requestId) {
22 Jedis je=getJedis();
23 if (requestId.equals(je.get(lockKey))) {
24 je.del(lockKey);
25 }
26 }
27}
最后
如果觉得看完有收获,希望能给我点个赞,这将会是我更新的最大动力,感谢各位的支持
欢迎各位关注我的公众号【java冢狐】,专注于java和计算机基础知识,保证让你看完有所收获,不信你打我
如果看完有不同的意见或者建议,欢迎多多评论一起交流。感谢各位的支持以及厚爱。