zookeeper分布式锁

分布式锁介绍

        分布式锁主要用于在分布式环境中保护跨进程、跨主机、跨网络的共享资源实现互斥访问,以达到保证数据的一致性

本文主要谈的是Zookeeper的分布式锁,在此之前先了解下基于数据库和redis的分布式锁的实现。

基于数据库

1. 基于数据库表

最简单的方式可能就是直接创建一张锁表,当我们要锁住某个方法或资源时,我们就在该表中增加一条记录,想要释放锁的时候就删除这条记录。给某字段添加唯一性约束,如果有多个请求同时提交到数据库的话,数据库会保证只有一个操作可以成功,那么我们就可以认为操作成功的那个线程获得了该方法的锁,可以执行方法体内容。

会引入数据库单点、无失效时间、不阻塞、不可重入等问题。

2. 基于数据库排他锁

如果使用的是MySql的InnoDB引擎,在查询语句后面增加for update,数据库会在查询过程中(须通过唯一索引查询)给数据库表增加排他锁,我们可以认为获得排它锁的线程即可获得分布式锁,通过 connection.commit() 操作来释放锁。

会引入数据库单点、不可重入、无法保证一定使用行锁(部分情况下MySQL自动使用表锁而不是行锁)、排他锁长时间不提交导致占用数据库连接等问题。

3. 数据库实现分布式锁总结

优点:

  • 直接借助数据库,容易理解。

缺点:

  • 会引入更多的问题,使整个方案变得越来越复杂

  • 操作数据库需要一定的开销,有一定的性能问题

  • 使用数据库的行级锁并不一定靠谱,尤其是当我们的锁表并不大的时候

基于缓存

相比较于基于数据库实现分布式锁的方案来说,基于缓存来实现在性能方面会表现的更好一点。目前有很多成熟的缓存产品,包括Redis、memcached、tair等。

这里以Redis为例举出几种实现方法:

1. 基于 redis 的 setnx()、expire() 方法做分布式锁

setnx 的含义就是 SET if Not Exists,其主要有两个参数 setnx(key, value)。该方法是原子的,如果 key 不存在,则设置当前 key 成功,返回 1;如果当前 key 已经存在,则设置当前 key 失败,返回 0。

expire 设置过期时间,要注意的是 setnx 命令不能设置 key 的超时时间,只能通过 expire() 来对 key 设置。

2. 基于 redis 的 setnx()、get()、getset()方法做分布式锁

getset 这个命令主要有两个参数 getset(key,newValue),该方法是原子的,对 key 设置 newValue 这个值,并且返回 key 原来的旧值。

3. 基于 Redlock 做分布式锁

Redlock 是 Redis 的作者 antirez 给出的集群模式的 Redis 分布式锁,它基于 N 个完全独立的 Redis 节点(通常情况下 N 可以设置成 5)

4. 基于 redisson 做分布式锁

redisson 是 redis 官方的分布式锁组件

5. 基于缓存实现分布式锁总结

优点:

  • 性能好

缺点:

  • 实现中需要考虑的因素太多

  • 通过超时时间来控制锁的失效时间并不是十分的靠谱

Zookeeper 如何实现分布式锁?

下面讲如何实现排他锁和共享锁,以及如何解决羊群效应。

排他锁:利用zk上临时节点路径的唯一性,哪个JVM先创建临时节点,哪个JVM就成功获取锁。

共享锁:在zk统一持久节点下创建临时顺序节点,哪个JVM创建的顺序节点的序号最小哪个JVM先获取锁。

排他锁

排他锁,又称写锁或独占锁。如果事务T1对数据对象O1加上了排他锁,那么在整个加锁期间,只允许事务T1对O1进行读取或更新操作,其他任务事务都不能对这个数据对象进行任何操作,直到T1释放了排他锁。

排他锁核心是保证当前有且仅有一个事务获得锁,并且锁释

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值