定时任务部署多少台服务器,怎么确保只有一台服务器执行--redis 分布式锁
redis 分布式锁注意事项
- 1.互斥性:在任意时刻,只有一个客户端持有锁
- 2.一致性:加锁和解锁必须在同一个客户端,而且客户端自己不能把别人的锁解了;
- 3.避免死锁:即使有一个客户端在持有锁期间崩溃了而没有主动解锁,也能保证后续其他客户端能加锁
参考代码实现
if(redisTemplate.opsForValue().setIfAbsent("getsnInfo","11")){ //key的值放什么不重要,重要的是key.所以11或者aa都行。多个定时任务,是多个key,不能set一样的,各管各的定时任务。懂redis的应该都明白 try{ // 业务代码 }catch(){ redisTemplate.delete("getsnInfo"); } redisTemplate.delete("getsnInfo"); }
问题分析:
上述代码满足分布式锁的互斥性;
没有避免死锁,假如加锁的客户端挂掉,锁将一直存在,需要给加的锁添加过期时间;
如果保证一致性呢,删除的时候 判断 取出来的值 是否 放进去的值;
代码优化:
/** * 使用redis的set命令实现获取分布式锁 * @param lockKey 可以就是锁 * @param requestId 请求ID,保证同一性 * @param expireTime 过期时间,避免死锁 秒 * @return */ public boolean getLock(String lockKey,String requestId,int expireTime) { Jedis jedis = null; try { jedis = jedisPool.getResource() ; //NX:保证互斥性 String result = jedis.set(lockKey, requestId, "NX", "EX", expireTime); if("OK".equals(result)) { return true; } return false; } catch (Exception e) { e.printStackTrace(); return false; }finally { release(jedis); } }
/** * 释放分布式锁 * @param lockKey * @param requestId */ public boolean releaseLock(String lockKey,String requestId) { String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end"; Jedis jedis = null; try { jedis = jedisPool.getResource(); Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId)); if (result.equals(1L)) { return true; } return false; } catch (Exception e) { e.printStackTrace(); return false; } finally { release(jedis); } }
什么是分布式锁? 为啥需要分布式锁?
分布式锁 是分布式架构下 同步访问共享资源的一种方式
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升