1.基于redis的setnx()、expire()方法:
a. setnx(lockkey, 1) 如果返回0,则说明设置失败,当前key已存在,
有其他任务设置了该key;如果返回1,说明设置成功,获取了锁
b. expire()命令对lockkey设置超时时间(setnx不能设置key的过期时间),避免死锁问题。
2.基于数据库资源表做乐观锁
通过为数据库表添加一个 “version”字段来实现读取出数据时,将此版本号一同读出,之后更新时,对此版本号加1。
在更新过程中,会对版本号进行比较,如果是一致的,没有发生改变,则会成功执行本次操作;如果版本号不一致,则会更新失败。
a.先执行select操作查询当前数据的数据版本号,比如当前数据版本号是4:
select column1, version from table where id=1 ;
b. 执行更新操作:
update table set version=version+1 where id=1 and version=4
c. 如果update语句真正更新影响到了一行数据,那就说明占用资源成功。否则则说明
这个资源已经被别人占用了,更新失败。
3.基于zookeeper实现分布式锁
当前任务需要获取锁,需要到zookeeper节点下创建一个临时顺序节点node_n,然后比较当前节点与zookeeper中所有子节点顺序大小,如果自己是最小的,那么表示就获取到锁,否则监听比自己次小的节点node_n-1的删除事件,当次节点删除之后(获取锁的线程执行完任务后,删除节点),再次判断当前节点是不是最小的节点,直到是最小的节点,则表示获取了锁。
这里就不贴代码了。看一张图: