Redis入门第三天

Redis入门第三天:主要介绍了idea连接redis、Redis事务、和Redis分布式锁

Redis

IDEA连接Redis

安装

  • 首先先要下载驱动包,确保下载合适的驱动包下载jar包
  • 在classpath中包含此驱动包

测试连接

import redis.clients.jedis.Jedis;

public class jedisUtils {
    public static void main(String[] args) {
        Jedis jedis = new Jedis("localhost");
        System.out.println("连接成功");
        System.out.println("服务正在运行"+jedis.ping());
    }
}

结果:

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命令

    package com.cyb.redis.utils;
    
    import redis.clients.jedis.Jedis;
    import redis.clients.jedis.JedisPool;
    
    public class jedisUtils {
        private static String ip = "192.168.31.200";
        private static int port = 6379;
        private static JedisPool pool;
        static {
            pool = new JedisPool(ip, port);
        }
        public static Jedis getJedis() {
            return pool.getResource();
        }
        public static boolean getLock(String lockKey, String requestId, int timeout) {
            //获取jedis对象,负责和远程redis服务器进行连接
            Jedis je=getJedis();
            //参数3:NX和XX
            //参数4:EX和PX
            String result = je.set(lockKey, requestId, "NX", "EX", timeout);
            if (result=="ok") {
                return true;
            }
            return false;
        }
    
        public static synchronized boolean getLock2(String lockKey, String requestId, int timeout) {
            //获取jedis对象,负责和远程redis服务器进行连接
            Jedis je=getJedis();
            //参数3:NX和XX
            //参数4:EX和PX
            Long result = je.setnx(lockKey, requestId);
            if (result==1) {
                je.expire(lockKey, timeout); //设置有效期
                return true;
            }
            return false;
        }
    }
    
释放锁
package com.cyb.redis.utils;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

public class jedisUtils {
    private static String ip = "192.168.31.200";
    private static int port = 6379;
    private static JedisPool pool;
    static {
        pool = new JedisPool(ip, port);
    }
    public static Jedis getJedis() {
        return pool.getResource();
    }
    /**
     * 释放分布式锁
     * @param lockKey
     * @param requestId
     */
    public static void releaseLock(String lockKey, String requestId) {
        Jedis je=getJedis();
        if (requestId.equals(je.get(lockKey))) {
            je.del(lockKey);
        }
    }
}
发布了47 篇原创文章 · 获赞 35 · 访问量 3235

猜你喜欢

转载自blog.csdn.net/issunmingzhi/article/details/103984987