1,分布式锁的应用场景之前在zookeeper 的已经说过了,zookpper 的实现方式如下
https://www.cnblogs.com/pickKnow/p/11338579.html
2,基于redis 实现分布式锁
了解set 和 setnx 命令的不同:
127.0.0.1:6379> set name 'chris' OK 127.0.0.1:6379> setnx name 'chris' (integer) 0 127.0.0.1:6379> setnx age 20 (integer) 1 127.0.0.1:6379> set name 'chris' OK 127.0.0.1:6379>
set:往数据库里面插入值,成功,返回ok,key 如果相同,后面的会覆盖前面的
setnx: 往数据库里面插入值,成功返回1,失败返回0,如果key已经存在,则会插入失败,则会返回0
expire key timeout:设置有效时长
name 设置了20秒,过期了key 就不存在了
127.0.0.1:6379> expire name 20 (integer) 1 127.0.0.1:6379> get name (nil) 127.0.0.1:6379> get age "20"
del key: 删除key
127.0.0.1:6379> del age
3,基于上面三条命令,可以实现redis分布式锁
实现思想:在分布式集群环境中,多台JVM 共同去创建key,通过setnx 方式去创建,返回1,代表创建成功,创建成功,则能够获取到锁。
给锁设置有效期,根据业务逻辑来设置时长,方式死锁。
没有获取到锁的JVM,则一直等待。获取到锁的JVM 实现业务逻辑,逻辑完成,则删除key,将锁释放。
4,实现脚本如下:
private static JedisPool pool = null; // 设置最大连接数 private static int maxTotal =200; // 设置最大空闲数 private static int maxIdle = 8; // 设置最大等待时间 private static long maxWaitMillis = 1000*100; // 在borrow一个jedis实例时,是否需要验证,若为true,则所有jedis实例均是可用的 private static boolean testOnBorrow = true; // redis ip private static String ip = "192.168.178.110"; // redis 端口 private static int port = 6379; // redis连接timeout private static int timeOut = 6000; // redis 上锁的key private static String redisLockKey = "redisLockKey"; // redis 上锁的key 豪秒 private static long redisLockTimeOut = 6000; static { JedisPoolConfig config = new JedisPoolConfig(); config.setMaxTotal(maxTotal); config.setMaxIdle(maxIdle); config.setMaxWaitMillis(maxWaitMillis); config.setTestOnBorrow(testOnBorrow); pool = new JedisPool(config, ip, port, timeOut); } @Override public boolean lock(String redisLockValue) { Jedis resource = null; try { resource = pool.getResource(); // 当前时间 long moment = System.currentTimeMillis(); // 一把锁的的有效期是 redisLockTimeOut,所以在这个期间内,一直抢key // 超过这个时间,说明锁不用抢了,已经过期了,等待下次抢 while (System.currentTimeMillis() < moment + redisLockTimeOut) { Long setnx = resource.setnx(redisLockKey, redisLockValue); if (setnx == 1) { // 获取到了锁,给锁加上有效期 resource.pexpire(redisLockKey, redisLockTimeOut); return true; } } } catch (Exception e) { e.printStackTrace(); } finally { resource.close(); } return false; } public void unlock() { Jedis resource = null; try { resource = pool.getResource(); resource.del(redisLockKey); } catch (Exception e) { e.printStackTrace(); } finally { resource.close(); } }