非常完善的Redisson分布式锁使用(附踩坑记录)

一、Config配置文件

import lombok.Data;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.redisson.config.SingleServerConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;

/**
 * redisson配置信息
 */
@Data
@Configuration
@ConfigurationProperties("spring.redis")
public class RedissonConfig {

    private String host;

    private String password;

    private String port;

    private int timeout = 3000;
    private static String ADDRESS_PREFIX = "redis://";


    /**
     * 自动装配
     * 注意不要改 redisson 方法名,因为没指定bean的name,方法名就是bean的名字
     * 如果随意改了方法名,可能会找不到实例化bean
     */
    @Bean
    RedissonClient redisson() {
        Config config = new Config();

        //单redis
        config.useSingleServer()
                .setAddress("redis://" + host + ":" + port)
                .setTimeout(timeOut)
                .setDatabase(0);

        //redis集群
/*        config.useClusterServers().addNodeAddress(
                "redis://127.0.0.1:7181",
                "redis://127.0.0.1:7181",
                "redis://127.0.0.1:7181",
                "redis://127.0.0.1:7181",
                "redis://127.0.0.1:7181");*/

        if(!StringUtils.isEmpty(this.password)) {
            serverConfig.setPassword(this.password);
        }
        return Redisson.create(config);
    }
}

二、使用Demo

@Service
public class DemoService {
    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private RedisClient redisClient;

    @Autowired
    private XxService xxService;

    private String createUser(User userInfo) {
       String phone = userInfo.getPhone();
        String key = RedisKey.getRedisKey("redisKey_", phone);
        String userId = null;

        //以phone为锁
        RLock lock = redissonClient.getLock(phone);

        try {
            // 尝试获取锁的时间为0秒,持有锁的时间为5s
            boolean haveLock = lock.tryLock(0, 5, TimeUnit.SECONDS);
            if (haveLock) {
                userId = xxService.doSomeThing(userInfo);

                //1.往redis放一份,让未持有锁的请求获取
                redisClient.set(key, 60, userId);

                //2.其他业务处理 TODO

            } else {
                //睡2~3s,等持有锁的一方创建好用户线信息,拿userid
                Thread.sleep(new Random().nextInt(1001) + 2000);
                userId = redisClient.get(key);
            }
        } catch (Throwable ex) {
            log.error("redisson fall");
        } finally {
            //释放锁
            if (lock.isLocked() && lock.isHeldByCurrentThread()){
                lock.unlock();
            }
        }
        return userId;
    }

}

三、踩坑注意。

1.tryLock方法:最好不要给尝试获取锁的时间,直接置为0,拿不到锁就等待,否则可能会因为代码执行过快,尝试拿到锁又拿到了,造成锁失效

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值