为了保证在高并发下,一个方法或者属性同一时间只能被同一个线程执行,单机部署下可以用ReentrantLock或者Synchronized进行互斥控制。分布式集群系统中就需要用分布式锁来解决。一般来说实现分布式锁有三种方式。
一、基于数据库实现排他锁
建一张表,设置方法名称字段唯一,在获取锁的时候可以通过两种方法:
1、直接insert,如果失败则已经存在锁了,获取锁失败,如果insert成功则获取锁成功,释放锁直接delete。
2、update,再加一个字段,锁的状态,先查寻,然后update,如果update没有影响一条数据,则表示获取锁失败。释放锁则把状态字段修改。
缺点:
1、依赖数据库的可用性
2、没有失效时间,一旦解锁失败其他线程将无法获取锁
3、只能是非阻塞的,因为insert会直接报错
4、非重入的
解决方案:
1、两个数据库双向同步
2、采用定时任务来删除数据库中的超时数据
3、insert的地方采用while循环,直到insert成功之后再返回成功
4、非重入问题可以再表中加字段,记录当前获得锁的机器的主机信息和线程信息,下次获取锁的时候先根据主机信息和线程信息及方法名称一起查,如果能查到的话,直接把锁给他。
二、基于redis实现
获取锁的时候直接setIfAbsent(),如果返回false则获取失败,如果true则获取成功。
缺点:在redis使用主从结构中存在明显缺陷,