分布式锁的概念:
为了控制分布式系统或不同系统之间共同访问共享资源的一种锁实现。如果不同的系统或同一个系统的不同主机之间共享了某个资源时,往往需要互斥来防止彼此干扰来保证一致性。
为了保证一个代码块在同一时间只能由一个线程访问,它是控制分布式系统之间互斥访问共享资源的一种方式。保证多个服务之间互斥的访问共享资源,如果一个服务抢占了分布式锁,其他服务没获取到锁,就不进行后续操作。
分布式锁的特点:
1、互斥性:同一时刻只能有一个线程持有锁
2、可重入特征:同一节点上的同一个线程如果获取了锁之后能够再次获取锁
3、锁超时:支持锁超时,具备锁失效机制,防止死锁
4、具备非阻塞锁特征:即没有获取锁将直接返回获取锁失败
5、高可用、高性能的获取锁与释放锁;
分布式锁的实现方式:
1、基于数据库
2、基于redis
3、基于zookeeper
分布式锁的场景:
1、多个服务实例都能执行某个任务,如果限制只能被一台机器执行,不能重复执行,就可以用分布式锁来做标记。
2、秒杀场景,要求并发量很高,那么同一个商品只能被一个用户抢到,就可以使用分布式锁实现
3、比较敏感的数据比如金额修改,同一时间只能有一个人操作,如果2个人同时修改金额,一个加一个减金额,为了防止同时操作造成数据不一致,就可以使用分布式锁实现
redis分布式锁实现:
1、利用setnx+expire命令
redis的setnx命令:当键不存在时,设置key的值成功,返回1,当key存在时,什么也不做,返回0。
redis的expire命令:设置key值的有效时间,因为分布式锁有超时机制,可以用该命令设置。
所以我们利用setnx+expire命令
但是因为setnx和expire是分开的两步操作,不具有原子性,如果执行完第一条指令应用异常或者重启了,锁将无法过期,造成死锁。
解决上面缺陷可以使用:
1、redis2.8版本之后引入了指令 set key value [EX seconds] [PX milliseconds] [NX|XX]
,该指令可以同时执行 setnx 和 expire ,于是解决了死锁问题;
参数列表解释
- EX seconds: 设定过期时间,单位为秒
- PX milliseconds: 设定过期时间,单位为毫秒
- NX: key不存在时设置值
- XX: key存在时设置值