分布式锁

使用redis来完成分布式锁

pom.xml

<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-redis</artifactId>
		</dependency>

application.properties

#redis jedis配置
# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器地址
spring.redis.host=127.0.0.1
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
#spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=-1
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=-1
# 连接池中的最大空闲连接
spring.redis.pool.max-idle=10
# 连接池中的最小空闲连接
spring.redis.pool.min-idle=8
# 连接超时时间(毫秒)
spring.redis.timeout=4000

对jedispool进行配置

package com.example.demo.RedisUtil;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

/**
 * @program: demoA
 * @description
 * @author: dajitui
 * @create: 2019-01-03 23:17
 **/
@EnableCaching
@Configuration
public class JedisConfig extends CachingConfigurerSupport {
    private Logger logger = LoggerFactory.getLogger(JedisConfig.class);

    /**
     * SpringSession  需要注意的就是redis需要2.8以上版本,然后开启事件通知,在redis配置文件里面加上
     * notify-keyspace-events Ex
     * Keyspace notifications功能默认是关闭的(默认地,Keyspace 时间通知功能是禁用的,因为它或多或少会使用一些CPU的资源)。
     * 或是使用如下命令:
     * redis-cli config set notify-keyspace-events Egx
     * 如果你的Redis不是你自己维护的,比如你是使用阿里云的Redis数据库,你不能够更改它的配置,那么可以使用如下方法:在applicationContext.xml中配置
     * <util:constant static-field="org.springframework.session.data.redis.config.ConfigureRedisAction.NO_OP"/>
     * @return
     */

    @Value("${spring.redis.host}")
    private String host;

    @Value("${spring.redis.port}")
    private int port;

    @Value("${spring.redis.timeout}")
    private int timeout;

    @Value("${spring.redis.pool.max-active}")
    private int maxActive;

    @Value("${spring.redis.pool.max-idle}")
    private int maxIdle;

    @Value("${spring.redis.pool.min-idle}")
    private int minIdle;

    @Value("${spring.redis.pool.max-wait}")
    private long maxWaitMillis;



    @Bean
    public JedisPool redisPoolFactory(){
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxIdle(maxIdle);
        jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
        jedisPoolConfig.setMaxTotal(maxActive);
        jedisPoolConfig.setMinIdle(minIdle);
        JedisPool jedisPool = new JedisPool(jedisPoolConfig,host,port,timeout);

        logger.info("JedisPool注入成功!");
        logger.info("redis地址:" + host + ":" + port);
        return  jedisPool;
    }

}

编写分布式锁

package com.example.demo.RedisUtil;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import java.util.Collections;

/**
 * @program: demoA
 * @description
 * @author: dajitui
 * @create: 2019-01-03 23:03
 **/
@Component
public class Rlock {


    private static final String LOCK_SUCCESS = "OK";
    private static final String SET_IF_NOT_EXIST = "NX";
    private static final String SET_WITH_EXPIRE_TIME = "PX";
    private static final long expireTime = 5000;
    private static final Long RELEASE_SUCCESS = 1L;


    private static String lockKey="message";

    @Autowired
    JedisPool jedisPool;

    /**
     * 请求id
     * @param requestid
     * @return
     */
    public boolean lock(String requestid){
        Jedis jedis=jedisPool.getResource();

        String result=jedis.set(lockKey, requestid, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);
        if (LOCK_SUCCESS.equals(result)) {
            return true;
        }
        return false;
    }

    /**
     * 请求id
     * @param requestid
     * @return
     */
    public boolean unlock(String requestid){
        Jedis jedis=jedisPool.getResource();

        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
        Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestid));

        if (RELEASE_SUCCESS.equals(result)) {
            return true;
        }
        return false;
    }
}

具体的自行百度哦~

测试类

package com.example.demo;

/**
 * @program: demoA
 * @description
 * @author: dajitui
 * @create: 2019-01-04 02:16
 **/
public class A {

    public static int a=1000;

    public static void f(){
        a--;
    }
}
package com.example.demo;

import com.example.demo.RedisUtil.Rlock;
import com.example.demo.entity.message;
import com.example.demo.mq.JMSProducer;
import org.apache.activemq.command.ActiveMQQueue;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementSetter;
import org.springframework.test.context.junit4.SpringRunner;
import redis.clients.jedis.JedisPool;

import javax.jms.Destination;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CountDownLatch;

@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {
	


	@Test
	public void testa(){
		CountDownLatch countDownLatch=new CountDownLatch(100);

		for(int i=0;i<100;i++){
			//countDownLatch.countDown();

			/*MyThread myThread=new MyThread();
			myThread.start();*/

			new Thread(new Runnable() {
                @Override
                public void run() {
                    while (true){
                        if (rlock.lock("1")){
                            System.out.println("获取到锁,开始执行减一操作");
                            A.f();
                            System.out.println(A.a);
                            if(rlock.unlock("1")){
                                System.out.println("释放锁成功");
                                break;
                            }else {
                                System.out.println("释放锁失败!!!");
                            }
                        }else {
                            System.out.println("获取不到锁,等待......");
                            int random= (int) (Math.random()*10000);
                            try {
                                Thread.sleep(random);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }

                    /*if (rlock.lock("1")){
                        System.out.println("获取到锁,开始执行减一操作");
                        A.f();
                        System.out.println(A.a);
                        if(rlock.unlock("1")){
                            System.out.println("释放锁成功");
                            //break;
                        }else {
                            System.out.println("释放锁失败!!!");
                        }
                    }else{
                        System.out.println("获取不到锁,等待2秒......");
                        int random= (int) (Math.random()*10000);
                        try {
                            Thread.sleep(1000+ random);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        if (rlock.lock("1")){
                            A.f();
                            System.out.println(A.a);
                            if(rlock.unlock("1")){
                                System.out.println("释放锁成功");
                                //break;
                            }else {
                                System.out.println("释放锁失败!!!");
                            }
                        }else {
                            //System.out.println("获取不到锁.......");
                            try {
                                Thread.sleep(random);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            if (rlock.lock("1")){
                                A.f();
                                System.out.println(A.a);
                                if(rlock.unlock("1")){
                                    System.out.println("释放锁成功");
                                    //break;
                                }else {
                                    System.out.println("释放锁失败!!!");
                                }
                            }else {
                                System.out.println("获取不到锁.......");
                            }
                        }
                    }*/
                }
            }).start();

		}
		/*try {
			countDownLatch.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}*/

    }

	@Autowired
	Rlock rlock;

   

}

 

如何续期

使用Redisson进行续期,参考肥哥大佬的分析https://mp.weixin.qq.com/s?__biz=MzA4NjgxMjQ5Mg==&mid=2665761573&idx=1&sn=5479cb1bc051c7397229742fc36c625c&chksm=84d21906b3a59010964338ae28825cd9cf7ede6d2f199698c70c009035555151942f30d3902c&mpshare=1&scene=24&srcid=0509ZXnNwMzLCKZtdIOoXN7l#rd

 

我们可以看到在调用lock()的时候会调用tryAcquire尝试获取锁,在获取到锁的时候会开启一个开门狗的线程,默认锁30秒过期,当

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值