在实际的开发场景中,我们可能会遇到不同客户端需要互斥地访问某个共享资源,也就是同一时刻只允许一个客户端操作这个共享资源,为了达到这个目的,一般会采用分布式锁来解决,目前流行的分布式锁实现方式有数据库、Memcached、Redis、文件系统、ZooKeeper,因Redis高性能、部署简单被广泛采用,那么今天我就给大家分享下,如何用Redis实现分布式锁。
一、一个可靠的、高可用的分布式锁需要满足以下几点
互斥性:任意时刻只能有一个客户端拥有锁,不能被多个客户端获取
安全性:锁只能被持有该锁的客户端删除,不能被其它客户端删除
死锁:获取锁的客户端因为某些原因而宕机,而未能释放锁,其它客户端也就无法获取该锁,需要有机制来避免该类问题的发生
高可用:当部分节点宕机,客户端仍能获取锁或者释放锁
二、利用单节点Redis实现分布式锁
利用单节点Redis实现分布式锁是最常用的一种方式,虽然没有考虑高可用,但是实现简单、成本低廉而被很多中小型企业所采用。
网上很多文章说采用setnx实现分布式锁,但是setnx命令无法原子性的设置锁的自身过期时间,也就是说执行setnx命令时我们无法同时设置其过期时间,那么就会出现死锁,例如:客户端A刚执行完setnx,这时候客户端A挂掉了,没有完成给锁设置过期时间,此时就产生了死锁,所有的客户端再也无法获得该锁,这种情况一般采用Lua脚本来实现(因为Redis执行Lua脚本是原子性的),其实从Redis2.6.12版本开始set命令完全可以替代setnx命令,我们看