实现:
- 基于zookeeper实现分布式锁 https://mp.csdn.net/editor/html/109091509
- 基于Redis缓存实现分布式锁
1.redis
Boolean isLockFree = RedisUtils.isLockFree(LIVE_LOCK, LIVE_LOCK, LOCK_TIME);
if(!isLockFree){
log.info("当前推送被锁定无法执行!!!");
return;
}
public static boolean isLockFree(String key, String value,int circleSecond)
{
//返回0表示该key的资源已经被占用,不能修改
long rs = getJedis().setnx(key, value);
if (0 == rs)
{
return false;
}
//锁最多的持续时间,避免死锁.一定要加这个功能,为了避免重启服务的时候在执行中,导致死锁,下次无法启动服务
getJedis().expire(key, circleSecond);
return true;
}
上面会有一个问题:如果缓存时间5s但是当前代码执行要10s,在还没执行完,锁就释放了,别的线程再去获取加锁也是成功的,会导致业务逻辑混乱或者脏数据。
使用redisson能避免这个问题。
2.redisson
2.0 新建redisson.yml 四个文件内容一致,替换各自环境集群即可
clusterServersConfig:
idleConnectionTimeout: 10000
connectTimeout: 10000
timeout: 3000
retryAttempts: 3
retryInterval: 1500
password: null
subscriptionsPerConnection: 5
clientName: null
#loadBalancer: !<org.redisson.connection.balancer.RoundRobinLoadBalancer> {}
slaveSubscriptionConnectionMinimumIdleSize: 1
slaveSubscriptionConnectionPoolSize: 50
slaveConnectionMinimumIdleSize: 32
slaveConnectionPoolSize: 64
masterConnectionMinimumIdleSize: 32
masterConnectionPoolSize: 64
readMode: "SLAVE"
nodeAddresses:
- "redis://172.28.1.127:7000"
- "redis://172.28.1.127:7001"
- "redis://172.28.1.127:7002"
scanInterval: 1000
threads: 0
nettyThreads: 0
2.1
package com.test.mybatisplus.util;
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
@Configuration
@Slf4j
public class RedissonUtils {
@Value("${spring.profiles.active}")
private String active;
@Bean
public RedissonClient redissonClient() {
//方式一
// Config config = new Config();
//
// config.useClusterServers()
// .setScanInterval(2000)
// .addNodeAddress("redis://172.28.1.127:7000", "redis://172.28.1.127:7001")
// .addNodeAddress("redis://172.28.1.127:7002");
//
// RedissonClient redisson = Redisson.create(config);
//方式二
log.error("active::::::"+active);
RedissonClient redisson =null;
try {
// Config config1=Config.fromYAML(new ClassPathResource("redisson.yml").getInputStream());
Config config1=Config.fromYAML(new ClassPathResource("redisson-"+active+".yml").getInputStream());
redisson = Redisson.create(config1);
}catch (Exception e){
log.error(e.getMessage());
}
return redisson;
}
}
2.2
RLock lock=redissonUtils.redissonClient().getLock(ES_LOCK);
try{
if(lock.isLocked()){
log.info("islock");
}else{
lock.lock();
//do something
String date= DateUtils.dateToStr(DateUtils.addDay(new Date(),-1), DateUtils.YYYY_MM_DD);
updateEsData(date);
}
}catch (Exception e){
log.error(e.getMessage());
}finally {
//是否有锁且是否是当前线程持有
if(lock.isLocked()&&lock.isHeldByCurrentThread()){
log.info("isHeldByCurrentThread");
lock.unlock();
}
}