当多个服务需要抢夺资源时,避免对资源的超额使用等情况,应使用分布式锁
常用的分布式锁 Mysql Redis Zookeeper
分布式锁的原理,多个服务抢占资源,只有一个能抢到,其它的需要等待
Mysql实现分布式锁
mysql实现分布式锁的原理:mysql可以用表的主键当做竞争条件,或则用唯一索引列当做竞争条件,多个服务谁先写入该条数据谁则获取了处理权利。处理完后将锁释放,也就是将该条数据删除。该情况下,如果服务处理过程中宕机,就会出现,mysql库中的数据不会被删除,造成死锁,就是其它服务永远获取不到该锁。避免该情况的发生可以设置一个过期时间,通过过期时间来定时删除mysql的数据,来保证锁可以被获取到。此种分布式锁实现方式不是特别好。不推荐使用。
Redis实现分布式锁
redis有个setnx的命令,当该key已经被设置过值的时候,其它client再去设置的时候是不成功的。由此保证只有一个服务能抢占到资源。但是该命令没有提供过期时间的原子设置,也会出现跟使用mysql一样的问题,当服务宕机,锁没释放掉造成死锁。但是redis官网提供了解决方案,可以使用ruby脚本使得两条命令变成原子操作。官网也提供了很其它语言解决方案。
zookeeper实现分布式锁(比较优异的方案)
zookeeper首先能充分保证自己的高可用,其内部有临时节点的创建,临时节点的过期是随着客户的session来确定的。当session不存在则节点自动删除。我能只需要在多个服务抢占资源的时候设置相同的节点到zk的临时节点上,成功则表示抢占成功。用完释放该节点。如果发生业务处理中服务宕机,zk会自动根据session和心跳机制,将该节点删除,充分实现了可靠性和及时性。
hdfs的HA和yarn的HA都是采取这种分布式锁来实现高可用的。