分布式锁的实现方式

介绍几种常用的分布式锁的实现

MySql

常用函数
  • lock() 一般是阻塞式的获取锁,意思就是不获取到锁誓不罢休;
  • tryLock() 是非阻塞获取锁,如果获取不到那么就会马上返回。
适用场景
  • Mysql分布式锁一般适用于资源不存在数据库,如果数据库存在比如订单,那么可以直接对这条数据加行锁,不需要我们上面多的繁琐的步骤,比如一个订单,那么我们可以用select * from order_table where id = ‘xxx’ for update进行加行锁,那么其他的事务就不能对其进行修改。
优缺点
  • 优点:理解起来简单,不需要维护额外的第三方中间件(比如Redis,Zk)。
  • 缺点:虽然容易理解但是实现起来较为繁琐,需要自己考虑锁超时,加事务等等。性能局限于数据库,一般对比缓存来说性能较低。对于高并发的场景并不是很适合。
如何避免死锁
  • 我们有可能会遇到我们的机器节点挂了,那么这个锁就不会得到释放,我们可以启动一个定时任务,通过计算一般我们处理任务的一般的时间,比如是5ms,那么我们可以稍微扩大一点,当这个锁超过20ms没有被释放我们就可以认定是节点挂了然后将其直接释放。
乐观锁的实现
  • 对表加一个版本号字段,查询出来一个版本号之后,update或者delete的时候需要依赖我们查询出来的版本号,判断当前数据库和查询出来的版本号是否相等,如果相等那么就可以执行,如果不等那么就不能执行。很像的CAS(Compare And Swap),比较并交换是一个原子操作。这样就能避免加select * for update行锁的开销。

ZooKeeper

  • ZooKeeper是以Paxos算法为基础分布式应用程序协调服务。
  • Curator封装了Zookeeper底层的Api,使我们更加容易方便的对Zookeeper进行操作,并且它封装了分布式锁的功能。Curator实现了可重入锁(InterProcessMutex),也实现了不可重入锁(InterProcessSemaphoreMutex)。在可重入锁中还实现了读写锁。
锁超时
  • Zookeeper不需要配置锁超时,每个机器维护着一个ZK的session,通过这个session,ZK可以判断机器是否宕机。如果我们的机器挂掉的话,那么这个临时节点对应的就会被删除
优缺点
  • 优点:ZK可以不需要关心锁超时时间,实现起来有现成的第三方包,比较方便,并且支持读写锁,ZK获取锁会按照加锁的顺序,所以其是公平锁。对于高可用利用ZK集群进行保证。
  • 缺点:ZK需要额外维护,增加维护成本,性能和Mysql相差不大,依然比较差。并且需要开发人员了解ZK是什么。

Redis

重要函数:setNx(set if not exist),如果不存在则更新
  • 只有在某个 key 不存在的情况下才能设置(set)成功该 key。于是,这就可以让多个进程并发去设置同一个 key,只有一个进程能设置成功。而其它的进程因为之前有人把 key 设置成功了,而导致失败(也就是获得锁失败)。
		SET resource_name my_random_value NX PX 30000
  • SET NX 命令只会在 key 不存在的时候给 key 赋值,PX 命令通知 Redis 保存这个 key 30000ms。
  • my_random_value 必须是全局唯一的值。这个随机数在释放锁时保证释放锁操作的安全性。
  • PX 操作后面的参数代表的是这个 key 的存活时间,称作锁过期时间。
  • 当资源被锁定超过这个时间时,锁将自动释放。
  • 获得锁的客户端如果没有在这个时间窗口内完成操作,就可能会有其他客户端获得锁,引起争用问题。
优缺点
  • 优点:对于Redis实现简单,性能对比ZK和Mysql较好。如果不需要特别复杂的要求,那么自己就可以利用setNx进行实现,如果自己需要复杂的需求的话那么可以利用或者借鉴Redission。对于一些要求比较严格的场景来说的话可以使用RedLock。
  • 缺点:需要维护Redis集群,如果要实现RedLock那么需要维护更多的集群。
推荐
  • 关于 value 的生成,官方推荐从 /dev/urandom 中取 20 个 byte 作为随机数。或者采用更加简单的方式,例如使用 RC4 加密算法在 /dev/urandom 中得到一个种子(Seed),然后生成一个伪随机流。也可以采用更简单的方法,使用时间戳 + 客户端编号的方式生成随机数。

分布式锁服务一般可以通过 Redis 和 ZooKeeper 等实现。Redis会引出了锁超时后的潜在风险,这里不做详细介绍。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值