spring boot redis 分布式锁

 

yml文件

  redis:
    host: 127.0.0.1
    port: 40197
    password: 123456
    timeout: 5000
    database: 0
    jedis:
      pool:
        min-idle: 0
        max-idle: 8
        max-active: 8
        max-wait: -1

 

RedisConfig.java

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.support.spring.FastJsonRedisSerializer;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
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.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.*;
import redis.clients.jedis.JedisPoolConfig;

import java.io.Serializable;
import java.time.Duration;

/**
 * @author  
 */
@Configuration
@ConditionalOnProperty("spring.redis.host")
@EnableCaching
@Slf4j
public class RedisConfig extends CachingConfigurerSupport {

	@Value("${spring.redis.host}")
	String redisHost;
	@Value("${spring.redis.port}")
	int redisPort;
	@Value("${spring.redis.password}")
	String redisPassword;
	@Value("${spring.redis.timeout}")
	int redisTimeout;
	@Value("${spring.redis.database}")
	int redisDatabase;

	@Value("${spring.redis.jedis.pool.min-idle}")
	int jedisMinIdle;
	@Value("${spring.redis.jedis.pool.max-idle}")
	int jedisMaxIdle;
	@Value("${spring.redis.jedis.pool.max-active}")
	int jedisMaxActive;
	@Value("${spring.redis.jedis.pool.max-wait}")
	int jedisMaxWait;

	/**
	 * 自定义缓存key生成策略
	 * @return KeyGenerator
	 */
	@Bean
	@Override
	public KeyGenerator keyGenerator() {
		return (target, method, 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 RedisConnectionFactory connectionFactory() {
		JedisPoolConfig poolConfig = new JedisPoolConfig();
		poolConfig.setMaxTotal(jedisMaxActive);
		poolConfig.setMaxIdle(jedisMaxIdle);
		poolConfig.setMaxWaitMillis(jedisMaxWait);
		poolConfig.setMinIdle(jedisMinIdle);
		poolConfig.setTestOnBorrow(true);
		poolConfig.setTestOnReturn(false);
		poolConfig.setTestWhileIdle(true);
		JedisClientConfiguration clientConfig = JedisClientConfiguration.builder().usePooling().poolConfig(poolConfig).and().readTimeout(Duration.ofMillis(redisTimeout)).build();
		// 单点redis
		RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
		log.debug(JSON.toJSONString(redisStandaloneConfiguration));
		redisStandaloneConfiguration.setHostName(redisHost);
		redisStandaloneConfiguration.setPassword(RedisPassword.of(redisPassword));
		redisStandaloneConfiguration.setPort(redisPort);
		redisStandaloneConfiguration.setDatabase(redisDatabase);
		return new JedisConnectionFactory(redisStandaloneConfiguration, clientConfig);
	}

	/**
	 * 缓存管理器
	 * @param redisConnectionFactory RedisConnectionFactory
	 * @return CacheManager
	 */
	@Bean
	public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
		// 设置缓存有效期一小时
		int hour = 1;
		RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofHours(hour));
		return RedisCacheManager.builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory)).cacheDefaults(redisCacheConfiguration).build();
	}

	@Bean
	public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory){
		RedisTemplate<String, String> template = new RedisTemplate<>();
		template.setConnectionFactory(factory);
		//设置序列化工具
		setSerializer(template);
		template.afterPropertiesSet();
		return template;
	}

	private void setSerializer(RedisTemplate<String, String> template) {
		RedisSerializer<String> stringRedisSerializer = new StringRedisSerializer();

		RedisSerializer<Serializable> genericToStringSerializer = new GenericToStringSerializer<>(Serializable.class);
		log.debug(String.valueOf(genericToStringSerializer));

		RedisSerializer<Object> jdkSerializationRedisSerializer = new JdkSerializationRedisSerializer();
		log.debug(String.valueOf(jdkSerializationRedisSerializer));

		Jackson2JsonRedisSerializer<Serializable> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Serializable.class);
		ObjectMapper om = new ObjectMapper();
		om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
		om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
		jackson2JsonRedisSerializer.setObjectMapper(om);

		RedisSerializer<Object> genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();

		RedisSerializer<Serializable> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Serializable.class);

		template.setEnableDefaultSerializer(true);
		template.setDefaultSerializer(fastJsonRedisSerializer);
		template.setStringSerializer(stringRedisSerializer);
		
		template.setKeySerializer(stringRedisSerializer);
		template.setValueSerializer(genericJackson2JsonRedisSerializer);

		template.setHashKeySerializer(stringRedisSerializer);
		template.setHashValueSerializer(fastJsonRedisSerializer);
	}

}

 

 

应用Java


import com.alibaba.fastjson.JSON;
import com.chinamobile.framework.redis.enums.BaseRedisEnum;
import com.chinamobile.framework.redis.service.RedisObjectService;
import com.chinamobile.framework.redis.vo.BaseRedisVo;
import com.chinamobile.scm.order.service.RedisService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.io.Serializable;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
@ConditionalOnProperty("spring.redis.host")
@Slf4j
public   class RedisServiceImpl<T extends Serializable> implements RedisService<T> {

    @Value("${spring.application.name}")
    String app;
    @Autowired
    RedisTemplate<String, String> redisTemplate;

    @Override
    public final String getApp() {
        return app;
    }

    @Override
    public final RedisTemplate<String, String> getRedisTemplate() {
        return redisTemplate;
    }

    @Override
    public   void set(String key, String value) {
        Assert.notNull(key, "参数id不能为空");

        log.debug("set key:" + key + ",value:" + value);
        redisTemplate.opsForValue().set(key, value);
    }


    @Override
    public String get(String key) {
        Assert.notNull(key, "参数key不能为空");
        log.info("get id:" + key +" start get value");
        Object obv ="";
        try {
            obv = redisTemplate.opsForValue().get(key);
        }
        catch (Exception exp)
        {
            String messageerr=exp.getMessage();
            if(messageerr.indexOf("loginUserId")>-1)
            {
                int idxloginUserId=messageerr.indexOf("loginUserId");
                String loginstartidx=messageerr.substring(idxloginUserId-1);
                int idxsencond=loginstartidx.indexOf(",");
                String endindexstr=loginstartidx.substring(0,idxsencond);
                String valuestr="{"+endindexstr.replaceAll(",","")+"}";
                obv=valuestr;
            }
        }
       // Could not read JSON: Missing type id when trying to resolve subtype of [simple type, class java.lang.Object]: missing type id property '@class'\n at [Source: (byte[])\"{\"timestamp\":\"1607414522055\",\"loginUserId\":\"zhanghuan6@tj.cmcc\",\"loginIp\":\"220.196.49.26\",\"loginAddrCode\":\"TJ\",\"loginType\":\"LOGINPAGE\"}\
        String vo=(String)obv;
        log.info("get id:" + key + ",value:" + vo);
        return  vo;
    }
public static void main(String[] args)
{
    String messageerr="Could not read JSON: Missing type id when trying to resolve subtype of [simple type, class java.lang.Object]: missing type id property '@class'\n at [Source: (byte[])\"{\"timestamp\":\"1607414522055\",\"loginUserId\":\"zhanghuan6@tj.cmcc\",\"loginIp\":\"220.196.49.26\",\"loginAddrCode\":\"TJ\",\"loginType\":\"LOGINPAGE\"}\"; line: 1, column: 135]; nested exception is com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Missing type id when trying to resolve subtype of [simple type, class java.lang.Object]: missing type id property '@class'\n at [Source: (byte[])\"{\"timestamp\":\"1607414522055\",\"loginUserId\":\"zhanghuan6@tj.cmcc\",\"loginIp\":\"220.196.49.26\",\"loginAddrCode\":\"TJ\",\"loginType\":\"LOGINPAGE\"}\"; line: 1, column: 135]";

    if(messageerr.indexOf("loginUserId")>-1)
    {
        int idxloginUserId=messageerr.indexOf("loginUserId");
        String loginstartidx=messageerr.substring(idxloginUserId-1);
        int idxsencond=loginstartidx.indexOf(",");
        String endindexstr=loginstartidx.substring(0,idxsencond);
        String valuestr="{"+endindexstr.replaceAll(",","")+"}";
        System.out.println(valuestr);
    }

}


}

 

 

基础Service Redis类


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.chinamobile.framework.common.constant.CommonConstant;
import com.chinamobile.framework.redis.enums.BaseRedisEnum;
import com.chinamobile.framework.redis.vo.BaseRedisVo;
import lombok.SneakyThrows;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.io.Serializable;
import java.util.*;
import java.util.concurrent.TimeUnit;

@SuppressWarnings("unused")
public interface BaseRedisService {

	String getApp();

	RedisTemplate<String, String> getRedisTemplate();

	/**
	 * 根据module和id生成redis的key
	 * @param module 业务场景code
	 * @param id 主键
	 * @return key
	 */
	default String generateKey(BaseRedisEnum module, String id) {
		StringBuilder buffer = new StringBuilder();
		Assert.hasText(getApp(), "配置spring.application.name错误");
		Assert.notNull(module, "参数module错误");
		Assert.notNull(id, "参数id不能为空");
		Assert.isTrue(!id.startsWith("\"") && !id.endsWith("\""), "id不能以引号开始且不能以引号结束");
		buffer.append(getApp()).append(CommonConstant.COLON).append(module.getKey());
		if (!StringUtils.isEmpty(id)) {
			return buffer.append(CommonConstant.COLON).append(id).toString();
		}
		return "\"" + buffer.toString() + "\"";//必须加引号,超过32个字符
	}

	default Collection<String> generateKeys(BaseRedisEnum module, Collection<String> ids) {
		if (ids == null) {
			return null;
		}
		Collection<String> keys = new ArrayList<>();
		for (String id : ids) {
			keys.add(generateKey(module, id));
		}
		return keys;
	}

	/**
	 * 删除缓存 根据key精确匹配删除
	 * @param module 业务场景code
	 * @param id 主键
	 */
	default void delete(BaseRedisEnum module, String id) {
		this.delete(module, new String[]{id});
	}

	/**
	 * 删除缓存 根据keys批量精确匹配删除
	 * @param module 业务场景code
	 * @param ids 主键数组
	 */
	default void delete(BaseRedisEnum module, String[] ids) {
		if (ids != null && ids.length > 0) {
			List<String> delKeys = new ArrayList<>();
			for (String id : ids) {
				if (!StringUtils.hasText(id)) {
					delKeys.add(generateKey(module, id));
				}
			}
			getRedisTemplate().delete(delKeys);
		}
	}

	/**
	 * 指定缓存的失效时间
	 * @param module 业务场景code
	 * @param id 主键
	 * @param second 有效时间,单位秒
	 * @return 是否成功
	 */
	default Boolean expire(BaseRedisEnum module, String id, long second) {
		return expire(module, id, second, TimeUnit.SECONDS);
	}

	default Boolean expire(BaseRedisEnum module, String id, long time, TimeUnit unit) {
		Assert.notNull(id, "参数id不能为空");
		String key = generateKey(module, id);
		if (time > 0) {
			return getRedisTemplate().expire(key, time, unit);
		}
		return Boolean.FALSE;
	}

	/**
	 * 查看key是否存在
	 * @param module 业务场景code
	 * @param id 主键
	 * @return redis的key集合
	 */
	default Set<String> keys(BaseRedisEnum module, String id) {
		StringBuilder pattern = new StringBuilder();
		Assert.hasText(getApp(), "配置spring.application.name错误");
		Assert.notNull(module, "参数module错误");
		pattern.append(getApp()).append(CommonConstant.COLON).append(module.getKey());
		if (!StringUtils.isEmpty(id)) {
			pattern.append(CommonConstant.COLON).append(id);
		}
		pattern.append("*");
		return getRedisTemplate().keys(pattern.toString());
	}

	/**
	 * 检查key是否存在
	 * @param module 业务场景code
	 * @param id 主键
	 * @return 是否存在,true存在,false不存在
	 */
	default boolean exist(BaseRedisEnum module, String id) {
		Assert.notNull(id, "参数id不能为空");
		String key = generateKey(module, id);
		Boolean bool = getRedisTemplate().hasKey(key);
		if (bool == null) {
			return false;
		}
		return bool;
	}

	default <T extends Serializable> Map<String, String> generateMap(BaseRedisEnum module, Map<String, T> data) {
		Map<String, String> map = new HashMap<>();
		for (Map.Entry<String, T> entry : data.entrySet()) {
			BaseRedisVo<T> vo = new BaseRedisVo<>(entry.getValue());
			map.put(generateKey(module, entry.getKey()), JSON.toJSONString(vo));
		}
		return map;
	}

	@SuppressWarnings("unchecked")
	@SneakyThrows
	default <T> T transfer(String vo) {
		if (vo == null) {
			return  null;
		}
		JSONObject json = JSON.parseObject(vo);
		BaseRedisVo<JSONObject> v = json.toJavaObject(BaseRedisVo.class);
		Class<T> clazz = (Class<T>) Class.forName(v.getClazzT());
		JSONObject data = v.getData();
		return data.toJavaObject(clazz);
	}

	@SneakyThrows
	default <T extends Serializable> List<T> transfer(List<String> list) {
		List<T> result = new ArrayList<>();
		if (CollectionUtils.isEmpty(list)) {
			return result;
		}
		for (String vo : list) {
			if (vo != null) {
				result.add(transfer(vo));
			}
		}
		return result;
	}

	@SneakyThrows
	default <T extends Serializable> Set<T> transfer(Set<String> set) {
		Set<T> result = new HashSet<>();
		if (CollectionUtils.isEmpty(set)) {
			return result;
		}
		for (String vo : set) {
			if (vo != null) {
				result.add(transfer(vo));
			}
		}
		return result;
	}

}

调用方分类


import com.alibaba.fastjson.JSON;
import com.chinamobile.framework.redis.enums.BaseRedisEnum;
import com.chinamobile.framework.redis.service.RedisObjectService;
import com.chinamobile.framework.redis.vo.BaseRedisVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.io.Serializable;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
@ConditionalOnProperty("spring.redis.host")
@Slf4j
public final class RedisObjectServiceImpl<T extends Serializable> implements RedisObjectService<T> {

	@Value("${spring.application.name}")
	String app;
	@Autowired
	RedisTemplate<String, String> redisTemplate;

	@Override
	public final String getApp() {
		return app;
	}

	@Override
	public final RedisTemplate<String, String> getRedisTemplate() {
		return redisTemplate;
	}

	@Override
	public final void set(BaseRedisEnum module, String id, T value) {
		Assert.notNull(id, "参数id不能为空");
		BaseRedisVo<T> vo = new BaseRedisVo<>(value);
		String v = JSON.toJSONString(vo);
		log.debug("set id:" + id + ",value:" + v);
		redisTemplate.opsForValue().set(generateKey(module, id), v);
	}

	@Override
	public final void set(BaseRedisEnum module, String id, T value, long second) {
		Assert.notNull(id, "参数id不能为空");
		BaseRedisVo<T> vo = new BaseRedisVo<>(value);
		String key = generateKey(module, id);
		redisTemplate.opsForValue().set(key, JSON.toJSONString(vo), second, TimeUnit.SECONDS);
	}

	@Override
	public final Boolean setIfAbsent(BaseRedisEnum module, String id, T value) {
		Assert.notNull(id, "参数id不能为空");
		BaseRedisVo<T> vo = new BaseRedisVo<>(value);
		return redisTemplate.opsForValue().setIfAbsent(generateKey(module, id), JSON.toJSONString(vo));
	}

	@Override
	public final void multiSet(BaseRedisEnum module, Map<String, T> data) {
		Assert.notEmpty(data, "参数data不能为空");
		redisTemplate.opsForValue().multiSet(generateMap(module, data));
	}

	@Override
	public final Boolean multiSetIfAbsent(BaseRedisEnum module, Map<String, T> data) {
		Assert.notEmpty(data, "参数data不能为空");
		return redisTemplate.opsForValue().multiSetIfAbsent(generateMap(module, data));
	}

	@Override
	public final T get(BaseRedisEnum module, String id) {
		Assert.notNull(id, "参数id不能为空");
		String vo = redisTemplate.opsForValue().get(generateKey(module, id));
		log.debug("get id:" + id + ",value:" + vo);
		return transfer(vo);
	}

	@Override
	public final T getAndSet(BaseRedisEnum module, String id, T value) {
		Assert.notNull(id, "参数id不能为空");
		BaseRedisVo<T> v = new BaseRedisVo<>(value);
		String vo = redisTemplate.opsForValue().getAndSet(generateKey(module, id), JSON.toJSONString(v));
		return transfer(vo);
	}

	@Override
	public final List<T> multiGet(BaseRedisEnum module, Collection<String> ids) {
		Assert.notEmpty(ids, "参数ids不能为空");
		List<String> list = redisTemplate.opsForValue().multiGet(generateKeys(module, ids));
		return transfer(list);
	}

	@Override
	public final long generate(BaseRedisEnum module, String id) {
		Assert.notNull(id, "参数id不能为空");
		return generate(module, id, 1);
	}

	@Override
	public final long generate(BaseRedisEnum module, String id, Date expireTime) {
		Assert.notNull(id, "参数id不能为空");
		return generate(module, id, 1, expireTime);
	}

	@Override
	public final long generate(BaseRedisEnum module, String id, int increment) {
		Assert.notNull(id, "参数id不能为空");
		RedisAtomicLong counter = new RedisAtomicLong(generateKey(module, id), Objects.requireNonNull(redisTemplate.getConnectionFactory()));
		return counter.addAndGet(increment);
	}

	@Override
	public final long generate(BaseRedisEnum module, String id, int increment, Date expireTime) {
		Assert.notNull(id, "参数id不能为空");
		RedisAtomicLong counter = new RedisAtomicLong(generateKey(module, id), Objects.requireNonNull(redisTemplate.getConnectionFactory()));
		counter.expireAt(expireTime);
		return counter.addAndGet(increment);
	}

}

 

分布式锁


import com.chinamobile.framework.common.constant.CommonConstant;
import com.chinamobile.framework.common.exception.CommonException;
import com.chinamobile.framework.redis.enums.CommonDistributedLockEnum;
import com.chinamobile.framework.redis.service.CommonDistributedLockService;
import com.chinamobile.framework.redis.service.RedisObjectService;
import com.chinamobile.framework.utils.ProjectUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Service
@ConditionalOnProperty("spring.redis.host")
@Slf4j
public class CommonDistributedLockServiceImpl implements CommonDistributedLockService {

	private static final long DEFAULT_EXPIRE = -1;

	@Resource
	private ApplicationContext applicationContext;
	@Resource
	private RedisObjectService<String> redisObjectService;

	@Override
	public boolean lock(String id) {
		log.debug("lock:id=" + id);
		return this.lock(id, DEFAULT_EXPIRE);
	}

	@SneakyThrows
	@Override
	public boolean lock(String id, long second) {
		log.debug("lock:id=" + id + ",time(s)=" + second);
		if (!isValidLock(id)) {
			throw new CommonException(CommonConstant.TOO_FREQUENT_CODE, "操作太频繁,请稍候再试。");
		}
		String ip = ProjectUtil.getIp(applicationContext.getEnvironment());
		String port = ProjectUtil.getPort(applicationContext.getEnvironment());
		String value = ip + "_" + port;
		if (!redisObjectService.setIfAbsent(CommonDistributedLockEnum.COMMON_DISTRIBUTED_LOCK, id, value)) {
			throw new CommonException(CommonConstant.TOO_FREQUENT_CODE, "操作太频繁,请稍候再试。");
		}
		if (second > 0) {
			return redisObjectService.expire(CommonDistributedLockEnum.COMMON_DISTRIBUTED_LOCK, id, second);
		}
		return true;
	}

	@Override
	public void unlock(String id) {
		log.debug("unlock:id=" + id);
//		redisObjectService.delete(CommonDistributedLockEnum.COMMON_DISTRIBUTED_LOCK, id);
		redisObjectService.expire(CommonDistributedLockEnum.COMMON_DISTRIBUTED_LOCK, id, 1, TimeUnit.NANOSECONDS);//改成1毫秒过期
	}

	@SneakyThrows
	@Override
	public void cleanLock() {
		List<String> deletes = new ArrayList<>();
		Set<String> keys = redisObjectService.keys(CommonDistributedLockEnum.COMMON_DISTRIBUTED_LOCK, null);
		if (!CollectionUtils.isEmpty(keys)) {
			String ip = ProjectUtil.getIp(applicationContext.getEnvironment());
			String port = ProjectUtil.getPort(applicationContext.getEnvironment());
			String data = ip + "_" + port;
			for (String key : keys) {
				String vo = redisObjectService.getRedisTemplate().opsForValue().get(key);
				if (vo != null && data.equals(redisObjectService.transfer(vo))) {
					deletes.add(key);
					redisObjectService.getRedisTemplate().expire(key, 1, TimeUnit.NANOSECONDS);
				}
			}
			log.info("cleanLock:ids=" + deletes);
//			redisObjectService.getRedisTemplate().delete(deletes);
		}
	}

	@Override
	public boolean isValidLock(String id) {
		log.debug("isValidLock:id=" + id);
		return !redisObjectService.exist(CommonDistributedLockEnum.COMMON_DISTRIBUTED_LOCK, id);
	}

}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Spring Boot中实现Redis分布式锁可以通过以下步骤: 1. 添加Redis依赖:在`pom.xml`文件中添加Redis的依赖,例如: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> ``` 2. 配置Redis连接信息:在`application.properties`或`application.yml`文件中配置Redis连接信息,例如: ```properties spring.redis.host=127.0.0.1 spring.redis.port=6379 ``` 3. 创建Redis分布式锁实现类:创建一个实现了分布式锁接口的类,例如`RedisDistributedLock`,在该类中注入`StringRedisTemplate`用于操作Redis。 4. 实现加锁方法:在`RedisDistributedLock`类中实现加锁方法,可以使用Redis的`setnx`命令来进行加锁操作,例如: ```java public boolean lock(String key, String value, long expireTime) { Boolean success = redisTemplate.opsForValue().setIfAbsent(key, value, expireTime, TimeUnit.MILLISECONDS); return success != null && success; } ``` 5. 实现释放锁方法:在`RedisDistributedLock`类中实现释放锁方法,使用Redis的`del`命令来删除锁对应的键,例如: ```java public boolean unlock(String key) { return redisTemplate.delete(key); } ``` 6. 在业务代码中使用分布式锁:在需要加锁的代码块前后调用加锁和释放锁方法,例如: ```java @Autowired private RedisDistributedLock redisDistributedLock; public void doSomethingWithLock() { String lockKey = "my-lock"; String lockValue = UUID.randomUUID().toString(); long expireTime = 10000; // 过期时间,单位为毫秒 try { boolean locked = redisDistributedLock.lock(lockKey, lockValue, expireTime); if (locked) { // 执行业务逻辑 } else { // 获取锁失败,可以进行重试或处理其他逻辑 } } finally { redisDistributedLock.unlock(lockKey); } } ``` 通过以上步骤,就可以在Spring Boot中实现Redis分布式锁。注意在使用分布式锁时需要考虑锁的粒度和超时处理等问题,以确保分布式锁的正确使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杨航 AI

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值