redis加锁

废话不多说,直接上代码


import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import java.util.UUID;

public class JedisService {

    @Autowired
    private JedisPool jedisPool;

    /**
     *
     * @param lockKey   需要锁的key
     * @param second   锁的时长(单位秒)
     * @param t 操作对象
     * @return
     * @throws Exception
     */
    public String redisLock(String lockKey,int second, T t)throws Exception{

        String requestId = UUID.randomUUID().toString();
        //加锁时长
        int expireTime = second*1000;

        boolean isRun = true;
        while (isRun) {
            try (Jedis jedis = jedisPool.getResource()){
                //尝试获得锁
                boolean getLock = RedisLockTool.tryGetDistributedLock(jedis, lockKey, requestId, expireTime);
                if (getLock) {
                    //TODO 进行其他操作(例如数据库,建议首先查是否存在数据库)

                    //释放锁
                    RedisLockTool.releaseDistributedLock(jedis, lockKey, requestId);
                    isRun = false;
                }
            } catch (Exception e) {
                isRun = false;
                return "程序出错,错误信息:"+e.getMessage();
            } finally {
                Thread.sleep(50);
            }
        }

        return "SUCCESS";
    }
}

RedisLockTool类代码:


import redis.clients.jedis.Jedis;

import java.util.Collections;


public class RedisLockTool {

    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 RELEASE_SUCCESS = 1L;

    /**
     * 尝试获取分布式锁
     * @param jedis Redis客户端
     * @param lockKey 锁
     * @param requestId 请求标识
     * @param expireTime 超期时间
     * @return 是否获取成功
     */
    public static boolean tryGetDistributedLock(Jedis jedis, String lockKey, String requestId, int expireTime) {

        String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);

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

    }


    /**
     * 释放分布式锁
     * @param jedis Redis客户端
     * @param lockKey 锁
     * @param requestId 请求标识
     * @return 是否释放成功
     */
    public static boolean releaseDistributedLock(Jedis jedis, String lockKey, String requestId) {

        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;

    }
}

redis相关配置:

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.time.Duration;

@Configuration
@Slf4j
public class RedisConfig {
    @Value("${spring.redis.host}")
    private String host;
    @Value("${spring.redis.password}")
    private String password;
    @Value("${spring.redis.port}")
    private int port;
    @Value("${spring.redis.timeout}")
    private Duration timeout;

    @Value("${spring.redis.jedis.pool.max-active:500}")
    private int jedisMaxActive;

    @Value("${spring.redis.jedis.pool.max-idle:50}")
    private int jedisMaxIdle;

    @Value("${spring.redis.jedis.pool.max-wait:30s}")
    private Duration jedisMaxWait;

    @Bean("userRedisTemplate")
    public RedisTemplate redisTemplate(
            RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate template = new RedisTemplate<>();

        //使用fastjson序列化
        Jackson2JsonRedisSerializer j = new Jackson2JsonRedisSerializer(Object.class);
        // value值的序列化采用fastJsonRedisSerializer
        template.setValueSerializer(j);
        template.setHashValueSerializer(j);
        // key的序列化采用StringRedisSerializer
        template.setKeySerializer(new StringRedisSerializer());
        template.setHashKeySerializer(new StringRedisSerializer());

        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }

    @Bean
    public JedisPool redisPoolFactory()  throws Exception {
        log.info("redis地址:" + host + ":" + port);
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        // 是否启用pool的jmx管理功能, 默认true
        jedisPoolConfig.setJmxEnabled(true);
        int redisTimeout = (int)timeout.getSeconds();
        //设置最大连接数500
        jedisPoolConfig.setMaxTotal(jedisMaxActive);
        //设置最大空闲连接50
        jedisPoolConfig.setMaxIdle(jedisMaxIdle);
        //设置等待时间30s
        jedisPoolConfig.setMaxWaitMillis(jedisMaxWait.getSeconds() * 1000);
        /*//在获取Jedis连接时,自动检验连接是否可用
        jedisPoolConfig.setTestOnBorrow(true);
        //在将连接放回池中前,自动检验连接是否有效
        jedisPoolConfig.setTestOnReturn(true);
        //自动测试池中的空闲连接是否都是可用连接
        jedisPoolConfig.setTestWhileIdle(true);*/
        JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port, redisTimeout, password);
        return jedisPool;
    }

} 
  

 

你可能感兴趣的:(java)