一、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,拿不到锁就等待,否则可能会因为代码执行过快,尝试拿到锁又拿到了,造成锁失效