redis简单的分布式锁

tech2023-08-24  100

分布式锁的演进:

分布式锁演进——阶段1

分布式锁演进——阶段2

分布式锁演进——阶段3

分布式锁演进——阶段4

分布式锁演进——最终形态

java源代码:

private Map<Long,List<Category2Level>> getCategorysJsonFromDBWithRedisLock() { final String LOCK_KEY = "lock"; // 生成每个线程各自的的唯一表示,区分lock值 String uuid = UUID.randomUUID().toString(); // 取redis中占坑,其他的线程就只能等待、(set lock 123 EX 300 NX),这边的过期时间和加锁一起设置,保证原子性 Boolean lock = redisTemplate.opsForValue().setIfAbsent(LOCK_KEY, uuid, 300, TimeUnit.SECONDS); // 当前一个成功占坑 if(lock) { System.out.println("获取分布式锁成功"); Map<Long, List<Category2Level>> datasFromDB = null; try { // 查询缓存 String s = redisTemplate.opsForValue().get(CATEGORY_JSON_KEY); // 缓存中没有 if (StringUtils.isEmpty(s)){ // System.out.println("查询数据库"); // getDatasFromDB();查询数据库的逻辑 datasFromDB = getDatasFromDB(); // 在redis缓存中存数据 在锁结束时保存到缓存中 redisTemplate.opsForValue().set(CATEGORY_JSON_KEY,JSON.toJSONString(datasFromDB),1, TimeUnit.DAYS); } datasFromDB = JSON.parseObject(s, new TypeReference<Map<Long, List<Category2Level>>>() { }); return datasFromDB; }catch (Exception e){ System.out.println("业务逻辑出现异常"); }finally { // 通过lua脚本删除锁 String script = "if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end"; redisTemplate.execute(new DefaultRedisScript<Long>(script,Long.class), Arrays.asList(LOCK_KEY), uuid); } return datasFromDB; } else { System.out.println("获取分布式锁失败,等待重试"); // 加锁失败。。。重试 // 休眠100ms重试 try { Thread.sleep(200); }catch (Exception e){} return getCategorysJsonFromDBWithRedisLock();// 自旋的方式重试 } }

主要是用了redis当中set命令:

SET key value [EX seconds] [PX milliseconds] [NX|XX]

PX milliseconds – 设置键key的过期时间,单位时毫秒 NX – 只有键key不存在的时候才会设置key的值

这时可以引入Redission

参考:redis中文网(set命令)

最新回复(0)