整合redis
简单的原生实现
1 2 3 4 5
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <version>2.1.5.RELEASE</version> </dependency>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| @Component public class RedisLockCommon { @Resource private RedisTemplate redisTemplate;
public Boolean tryLock(String key, String value) {
boolean localresult = redisTemplate.opsForValue().setIfAbsent(key,value,2000,TimeUnit.MILLISECONDS); System.out.println("key:"+key+" value: "+value); if(localresult){ System.out.println("创建成功"); return true; }if(!localresult){ System.out.println("已存在,循环等待"); return false; }
return false; }
public void unlock(String key, String value) { String currentValue = redisTemplate.opsForValue().get(key).toString(); try { if (StringUtil.isNotEmpty(currentValue) && currentValue.equals(value)) { redisTemplate.opsForValue().getOperations().delete(key); } } catch (Exception e) { } } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| @Resource private RedisLockCommon redisLock;
public void doThings(){ String key = "dec_store_lock"; String value = UUID.randomUUID().toString(); try { boolean flag = true; while(flag){ if(redisLock.tryLock(key, value)){
flag = false; } } } catch (Exception e) { e.printStackTrace(); } finally { redisLock.unlock(key, value); }
}
|
注:本例子只是为了简单实现redis分布式锁,未表示出可重入锁、和看门狗特性,具体请百度
也可使用jedis来实现,Jedis 是简单的封装了 Redis 的API库,可以看作是Redis客户端,它的方法和Redis 的命令很类似,尝试加锁的命令是 setnx()
redis分布式锁实现原理
1.关键在于setIfAbsent()方法,对应linux命令setnx,即若已经存在同样的key则返回false,若不存在则创建
2.加锁即在该key中,将区分本线程与其它线程的信息写入该key的value中,可以是本线程产生的uuid也可以是本线程的线程id
3.未抢到锁的线程需不断地循环去获取锁,即创建 键值对
使用redisson实现
1 2 3 4 5 6
| <dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.15.4</version> </dependency>
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| String host = "localhost"; String port = "6379";
@Bean public RedissonClient redissonClient() { Config config = new Config(); config.useSingleServer().setAddress("redis://" + host + ":" + port); return Redisson.create(config); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| @Autowired private RedissonClient redissonClient;
public void doThings(){ String key = "lock_product"; RLock lock = redissonClient.getLock(key);
try { boolean flag = lock.tryLock(5000, 60000, TimeUnit.MILLISECONDS); if (flag) { } } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } }
|