分布式锁应该具备的能力
1、在分布式情况下,一个方法只能被同一个节点下的一个线程执行。
2、高可用的获取锁,释放锁。
3、高性能的获取锁,释放锁。
4、具有可重入性。
5、具备锁失效机制,防止死锁。
6、具备非阻塞特性,及如果没有会去到锁直接返回获取锁失败。
Redis 实现分布式锁的基本思路
大体思路:oneServer 去 resourceServer 上获同步 resourceId,然后在 redis 上 执行 SETNX 命令,以这个 resourceId 作为Key,存在redis 中,当oneServer完成业务操作之后删除redis当中设置的key。当twoServer申请 resourceId 之前,首先去检查 redis 是否存在已经存在 resourceId 占用位置的 redis,如果存在返回resourceId已存在,等待 redis 释放 resourceId,然后去resourceServer 去申请 resourceId,申请到之后重复 oneServer 的操作。
redis操作流程: oneServer 执行 SETNX 设置 resourceId 。当执行完成后执行 DEL。twoServer 执行 EXISTS 检查是否存在 resourceId,如果存在返回resourceId已存在,如果不存在重复 oneServer 的操作。为实现《锁失效机制》,可以使用 SETEX 命令设置锁过期时间 替换 SETNX 命令占用资源。
存在的问题
误删锁:当在过期时间内 oneServer 操作未完成,所释放了,然后 twoServer 获取到了同步 resourceId,当oneServer执行完成,释放resourceId,是不是把 twoServer 的 resourceId 删除了。
解决方案:
1、判断是不是自己的锁。 SETEX 设置 value 设置为自己的 threadId,删除时判断是不是自己的锁。
2、判断是否处理完成,设置守护线程,判断执行线程是否完成,当执行线程没有执行完成时,设置延期,处理完成后下线守护线程。