分布式锁
分布式锁的作用就是,当某一个请求产生高并发等操作时,会对其进行限定,保证其数据的准确性。通俗点讲就是:我在拜访一户人家的时候,我进门后立即把门关上,等我访问结束后,我出来,再把门打开,你们再去争,去抢,谁抢到了,再学我的步骤,挨次拜访。当然会出现一些锁超时的现象:拜访人家的时候,赖着不走了,也不出来,别人也进不去,那么这类人我们会强制将其拖走,继续进行有序拜访。对于分布式锁可以采用redis缓存共享实现。
参考:分布式锁是什么
分布式锁具备的条件
- 在分布式系统环境下,一个方法在同一时间只能被一个机器的一个线程执行;
- 高可用的获取锁与释放锁;
- 高性能的获取锁与释放锁;
- 具备可重入特性;
- 具备锁失效机制,防止死锁;
- 具备非阻塞锁特性,即没有获取到锁将直接返回获取锁失败。
什么方式实行分布式锁
基于数据库实现分布式锁;
缺点:
- 这把锁强依赖数据库的可用性,数据库是一个单点,一旦数据库挂掉,会导致业务系统不可用。
- 这把锁没有失效时间,一旦解锁操作失败,就会导致锁记录一直在数据库中,其他线程无法再获得到锁。
- 这把锁只能是非阻塞的,因为数据的insert操作,一旦插入失败就会直接报错。没有获得锁的线程并不会进入排队队列,要想再次获得锁就要再次触发获得锁操作。
- 这把锁是非重入的,同一个线程在没有释放锁之前无法再次获得该锁。因为数据中数据已经存在了。
解决方案:
- 数据库是单点?搞两个数据库,数据之前双向同步。一旦挂掉快速切换到备库上。
- 没有失效时间?只要做一个定时任务,每隔一定时间把数据库中的超时数据清理一遍。
- 非阻塞的?搞一个while循环,直到insert成功再返回成功。
- 非重入的?在数据库表中加个字段,记录当前获得锁的机器的主机信息和线程信息,那么下次再获取锁的时候先查询数据库,如果当前机器的主机信息和线程信息在数据库可以查到的话,直接把锁分配给他就可以了。
基于缓存(Redis等)实现分布式锁;
基于Zookeeper实现分布式锁;
从实现的复杂性角度(从低到高)
- Zookeeper >= 缓存 > 数据库
从性能角度(从高到低)
- 缓存 > Zookeeper >= 数据库
从可靠性角度(从高到低)
- Zookeeper > 缓存 > 数据库
评论