欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

redis分布式锁

程序员文章站 2024-01-12 22:16:28
1. redis分布式锁 1.1. 实现工具 1.2. redis配置 上述主要用到 redisPoolFactory方法,用来初始化jedispool,缓存等不需要用到可以删除 1.3. 引入springboot 参考 https://www.cnblogs.com/linjiqin/p/8003 ......

1. redis分布式锁

1.1. 实现工具

public class redistool {
 
    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;

    }
 
}

1.2. redis配置

package com.zhiyis.common.config;

import com.fasterxml.jackson.annotation.jsonautodetect;
import com.fasterxml.jackson.annotation.propertyaccessor;
import com.fasterxml.jackson.databind.objectmapper;
import org.slf4j.logger;
import org.slf4j.loggerfactory;
import org.springframework.beans.factory.annotation.value;
import org.springframework.cache.cachemanager;
import org.springframework.cache.annotation.cachingconfigurersupport;
import org.springframework.cache.annotation.enablecaching;
import org.springframework.cache.interceptor.keygenerator;
import org.springframework.context.annotation.bean;
import org.springframework.context.annotation.configuration;
import org.springframework.data.redis.cache.rediscachemanager;
import org.springframework.data.redis.connection.redisconnectionfactory;
import org.springframework.data.redis.connection.jedis.jedisconnectionfactory;
import org.springframework.data.redis.core.redistemplate;
import org.springframework.data.redis.serializer.jackson2jsonredisserializer;
import org.springframework.data.redis.serializer.stringredisserializer;
import org.springframework.http.converter.json.jackson2objectmapperbuilder;
import redis.clients.jedis.jedispool;
import redis.clients.jedis.jedispoolconfig;

import java.lang.reflect.method;


@configuration
@enablecaching
public class redisconfig extends cachingconfigurersupport {

    private static logger logger = loggerfactory.getlogger(redisconfig.class);

    @value("${spring.redis.host}")
    private string redishost;

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

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

    @value("${spring.redis.password}")
    private string redisauth;

    @value("${spring.redis.database}")
    private int redisdb;

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

    @value("${spring.redis.pool.max-wait}")
    private int maxwait;

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

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

    @bean
    @override
    public keygenerator keygenerator() {
        return new keygenerator() {
            @override
            public object generate(object target, method method, object... params) {
                stringbuilder sb = new stringbuilder();
                sb.append(target.getclass().getname());
                sb.append(method.getname());
                for (object obj : params) {
                    sb.append(obj.tostring());
                }
                return sb.tostring();
            }
        };
    }

    @bean
    public cachemanager rediscachemanager() {
        rediscachemanager cachemanager = new rediscachemanager(redistemplate());
        //默认300秒过期
        cachemanager.setdefaultexpiration(300);
        // 启动时加载远程缓存
        cachemanager.setloadremotecachesonstartup(true);
        //是否使用前缀生成器
        cachemanager.setuseprefix(true);
        return cachemanager;
    }



    @bean
    public redisconnectionfactory redisconnectionfactory() {
        jedispoolconfig poolconfig = new jedispoolconfig();
        poolconfig.setmaxtotal(maxactive);
        poolconfig.setmaxidle(maxidle);
        poolconfig.setmaxwaitmillis(maxwait);
        poolconfig.setminidle(minidle);
        poolconfig.settestonborrow(true);
        poolconfig.settestonreturn(false);
        poolconfig.settestwhileidle(true);
        jedisconnectionfactory jedisconnectionfactory = new jedisconnectionfactory(poolconfig);
        jedisconnectionfactory.setpassword(redisauth);
        jedisconnectionfactory.sethostname(redishost);
        jedisconnectionfactory.setdatabase(redisdb);
        jedisconnectionfactory.setport(redisport);
        jedisconnectionfactory.settimeout(redistimeout);
        return jedisconnectionfactory;
    }

    @bean
    public redistemplate<string, object> redistemplate() {
        redistemplate<string, object> redistemplate = new redistemplate<>();
        jackson2jsonredisserializer<object> serializer = jackson2jsonredisserializer();
        redistemplate.setconnectionfactory(redisconnectionfactory());
        redistemplate.setkeyserializer(new stringredisserializer());
        redistemplate.setvalueserializer(serializer);
        redistemplate.sethashkeyserializer(new stringredisserializer());
        redistemplate.sethashvalueserializer(serializer);
        return redistemplate;
    }

    @bean
    public jackson2jsonredisserializer<object> jackson2jsonredisserializer() {
        final jackson2jsonredisserializer<object> jackson2jsonredisserializer = new jackson2jsonredisserializer<>(object.class);
        final objectmapper objectmapper = jackson2objectmapperbuilder
                .json().build();
        objectmapper.setvisibility(propertyaccessor.all, jsonautodetect.visibility.any);
        objectmapper.enabledefaulttyping(objectmapper.defaulttyping.non_final);
        jackson2jsonredisserializer.setobjectmapper(objectmapper);
        return jackson2jsonredisserializer;
    }

    @bean
    public jedispool redispoolfactory() throws exception {
        jedispoolconfig jedispoolconfig = new jedispoolconfig();
        jedispoolconfig.setmaxidle(maxidle);
        jedispoolconfig.setmaxwaitmillis(maxwait);
        // 连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true
        jedispoolconfig.setblockwhenexhausted(true);
        // 是否启用pool的jmx管理功能, 默认true
        jedispoolconfig.setjmxenabled(true);
        jedispool jedispool = new jedispool(jedispoolconfig, redishost, redisport, redistimeout, redisauth);
        return jedispool;
    }
}

上述主要用到 redispoolfactory方法,用来初始化jedispool,缓存等不需要用到可以删除

1.3. 引入springboot

/**
 * redis分布式锁
 * @author laoliangliang
 * @date 2019/2/12 16:49
 */
@component
public class redislock {

    @autowired
    private jedispool jedispool;

    public boolean lock(string lockkey, string requestid, int expiretime) {
        jedis jedis = jedispool.getresource();
        return redistool.trygetdistributedlock(jedis, lockkey, requestid, expiretime);
    }

    public boolean unlock(string lockkey, string requestid) {
        jedis jedis = jedispool.getresource();
        return redistool.releasedistributedlock(jedis, lockkey, requestid);
    }
}

参考 https://www.cnblogs.com/linjiqin/p/8003838.html