学习redis实现分布式锁—–自己的一个理解

学习redis实现分布式锁—–自己的一个理解

一、导入maven依赖
<!– 操作redis的java客户端jedis –>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.9.0</version>
        </dependency>
二、代码实现
import java.util.UUID;

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

/**
 * 分布式锁的思想:多个服务器集群下,只允许其中一个jvm进行操作 
 * redis实现分布式锁的思路:
 * 
 * 获取锁:在多个jvm情况下,redis实现分布式锁通过setnx方法创建同一个key ,
 *      这个key是唯一不重复,如果存入成功返回1获取锁,存入失败返回0,value使用一个唯一不重复的随机数作为线程的ID。
 * 
 * 释放锁:为了保证线程获取的锁,于释放的锁是同一个,在删除reids的key的时候,要对线程ID进行判断,是同一个ID才进行删除
 * 
 * 如何防止死锁 
 *            1.设置一个获取锁之前的一个时间段,线程如果在这个时间段还没有获取到锁,那么线程就放弃获取锁,返回null
 *         2.还要设置另一个时间段,就是线程获取到锁之后,对key设置有效时间,过了这个是时间段,key自动删除 ,释放锁  返回线程ID
 * 
 * @author zxlovey
 *
 */
public class LockRedis {

    // jedis线程池
    private JedisPool jedisPool;

    public LockRedis(JedisPool jedisPool) {

        this.jedisPool = jedisPool;
    }

    private String reidsKey = “redis_key”;

    // 获取锁
    /**
     * 
     * @param acquireTimeout
     *            获取锁之前的一个时间段
     * @param timeOut
     *            线程获取到锁之后,对key设置有效时间 一般以秒为单位
     */
    public String getLockRedis(Long acquireTimeout, Long timeOut) {

        Jedis conn = null;
        try {

            // 获取到jedis
            conn = jedisPool.getResource();

            Long endTime = System.currentTimeMillis() + acquireTimeout;
            int expireLock = (int) (timeOut / 1000);

            String identifierValue = UUID.randomUUID().toString();

            while (System.currentTimeMillis() < endTime) {

                if (conn.setnx(reidsKey, identifierValue) == 1) {

                    // 获取锁 设置有效时间
                    conn.expire(reidsKey, expireLock);
                    // 返回value,这个value作为线程id 释放锁的时候需要判断删除的key 和获取的锁是同一个
                    return identifierValue;
                }
            }

        } catch (Exception e) {

            // TODO: handle exception
        } finally {

            if (conn != null) {

                conn.close();
            }
        }

        return null;
    }

    // 释放锁
    /**
     * 
     * @param identifierValue
     *            锁的ID,就是key 对应的value
     */
    public void unLockRedis(String identifierValue) {

        Jedis conn = null;
        try {

            conn = jedisPool.getResource();

            if (conn.get(reidsKey).equals(identifierValue)) {

                // 获取的key的value相同,说明是同一个线程的锁资源
                // 删除key
                conn.del(reidsKey);
                System.out.println(“释放锁成功:” + Thread.currentThread().getName() + “—锁的ID:” + identifierValue);
            }

        } catch (Exception e) {

        } finally {

            if (conn != null) {

                conn.close();
            }
        }
    }

}

import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

public class LockServer {

    private static JedisPool pool = null;

    static {

        JedisPoolConfig config = new JedisPoolConfig();
        // 设置最大连接数
        config.setMaxTotal(200);
        // 设置最大空闲数
        config.setMaxIdle(8);
        // 设置最大等待时间
        config.setMaxWaitMillis(1000 * 100);
        // 在borrow一个jedis实例时,是否需要验证,若为true,则所有jedis实例均是可用的
        config.setTestOnBorrow(true);
        pool = new JedisPool(config, “127.0.0.1”, 6379, 3000);
    }
    
    private LockRedis lockRedis = new LockRedis(pool);
    
        //演示redis实现分布式锁
        public void seckill() {

            //1.获取到锁
            String identifierValue = lockRedis.getLockRedis(1000L, 1000L);
            if(identifierValue == null){

                System.out.println(“获取锁失败:”+Thread.currentThread().getName()+”;失败原因是获取锁的时间超时”);
                return;
            }
            System.out.println(“获取锁成功:”+Thread.currentThread().getName()+”—锁的ID:”+identifierValue);
            
            //2.释放锁
            lockRedis.unLockRedis(identifierValue);    
        }
    
}

public class ThreadLock extends Thread{

    private LockServer lockServer;
    
      public ThreadLock(LockServer lockServer) {

        this.lockServer = lockServer;
    }
    
    @Override
    public void run() {

         lockServer.seckill();
    }
    
}

public class Test001 {

    public static void main(String[] args) {

        LockServer lockServer = new LockServer();
        for (int i = 0; i < 500; i++) {

            ThreadLock tl = new ThreadLock(lockServer);
            tl.start();
        }
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/100803.html原文链接:https://javaforall.net

(0)
上一篇 2021年7月10日 下午2:00
下一篇 2021年7月10日 下午3:00


相关推荐

  • matlab差值报错,matlab插值介绍「建议收藏」

    matlab差值报错,matlab插值介绍「建议收藏」1、一维插值:已知离散点上的数据集,即已知在点集X=上的函数值Y=,构造一个解析函数(其图形为一曲线)通过这些点,并能够求出这些点之间的值,这一过程称为一维插值。MATLAB命令:yi=interp1(X,Y,xi,method)该命令用指定的算法找出一个一元函数,然后以给出处的值。xi可以是一个标量,也可以是一个向量,是向量时,必须单调,method可以下列方法之一:‘neares…

    2022年5月29日
    34
  • 单调栈用法_栈函数

    单调栈用法_栈函数单调栈,是指栈内元素从栈底到栈顶单调递增或单调递减的栈。简单来讲,单调栈=单调+栈,它同时满足两个特性:单调性、栈。以单调递增栈来讲解单调栈原理。假设当前元素为x,(1)若x<栈顶元素,那就不满足单调递增性,这时将栈中元素y弹出,若此时条件仍然不满足,则继续弹出栈顶元素,直到满足条件,再将x入栈;(2)若x>=栈顶元素,满足单调递增性,将x入栈;如此不断重复以上步骤,直到所有满足条件的元素都入栈。以一个具体例子[3,5,2,6,8]为例:(1)首先将3入栈,此时栈中元素为[3];(2

    2026年2月16日
    3
  • 异步FIFO原理及其实现

    异步FIFO原理及其实现FPGA 一 异步 FIFO 实现 包含源码和仿真文件 一 异步 FIFO 的重要参数及其作用 1 FIFO FirstInputFi 即先入先出队列 本质是 RAM FIFO 有几个最重要的参数 2 wr clk 写时钟 所有与写有关的操作都是基于写时钟 3 rd clk 读时钟 所有与读有关的操作都是基于读时钟 4 FIFO WIDTH FIFO 的位宽 即 FIFO 中每个地址对应的数据的位宽 5 FIFO DEPTH FIFO 的深度 即 FIFO 中能存入多少个 位宽为 FIFO

    2026年3月16日
    2
  • Hystrix服务熔断

    Hystrix服务熔断1 简介 1 1 什么是 Hystrix 1 2 服务雪崩 2 线程隔离 amp 服务降级 2 1 原理 2 2 案例 1 引入依赖 2 开启熔断 3 编写降级逻辑 4 默认的 fallback5 超时设置 3 服务熔断 3 1 熔断原理 3 2 案例 1 简介 1 1 什么是 Hystrix Hystrix 是一个应用于处理分布式系统的延迟和容错的开源库 在分布式系统里 许多依赖不可避免的会调用失败 比如超时 异常等 Hystrix 能够保证在一个依赖出问题的情况下 不会导致整个体系服务失败 避免级联故障 以提高分布式系

    2026年3月26日
    3
  • 养龙虾实战日记(Deepseek+Openclaw本地部署)Day1-遇事不决问豆包

    养龙虾实战日记(Deepseek+Openclaw本地部署)Day1-遇事不决问豆包

    2026年3月13日
    4
  • swagger @ApiParam 参数设置为可为空却还是要求输入参数

    swagger @ApiParam 参数设置为可为空却还是要求输入参数

    2020年11月9日
    289

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号