如何实现分布式锁

      分布式锁是有别于传统锁机制的一种锁。首先说一说,线程锁、进程锁。这些锁其实就是用于保持进程间、线程间对同一个资源的访问加锁。而分布式锁有所不同,它表示多个进程或者线程运行在不同的机器上,就是操作系统上,对同一个资源的访问保护。

1、分布式锁的实现

分布式锁的主要解决方案和思路就在于,在业务集群之外,再搭建一个用于保持锁的服务器,用于完成集群间的分布式锁机制。

具体可以实现的方式主要有以下几种:

      1、基于数据库表做乐观锁,用于分布式锁。

      2、基于数据库的表的唯一性约束来做分布式锁。

      3、使用memcached的add()方法,用于分布式锁。

      4、使用redis的setnx()、expire()方法,用于分布式锁。

      5、使用zookeeper,用于分布式锁。

其实主要还是靠3种额外的机制来实现,分别是数据库、memcached/redis、zookeeper来实现。

2、分布式锁的具体实现方法和原理
2.1、基于数据库实现

     基于数据库的主要实现方式在于通过乐观锁的方式来实现,通过维持一个额外的资源列表,并添加新的字段v1,每次分布式访问该资源时,需要拆分成两个步骤,首先get到该资源对应的字段v1,然后再update时,对比v1字段是否一致,如果一致则说明该线程获取到了对应的分布式锁,这里的v1字段,每次当有新的进程对它进行修改操作后,都会使他的v1+1.

    但是此类方法也存在一些很明显的缺点,其一 加重了数据库的I/O压力,因为一次uodate操作变成了两次,一次select一次update,其二需要维持额外的字段和对应的资源列表,也是一大开销。

    其实还有一种侵入性也较大的方法,同样可以实现分布式锁,那就是再维持一个额外的表格,并对要获取的锁的对象或者方法进行数据库唯一性约束,这样当多个分布式进程想要获取该锁时,就会向数据库中插入一条对应method_name的记录,而由于数据库中该属性是唯一性的,所以同时多个插入操作只有一个可以获取到锁。

2.2、基于memcached实现

     memcached是著名的缓存数据库,也是NoSQL数据库,其中memchached中的所有操作可以看做是原子操作,而add方法,则是如果这个key不存在才会添加上去,而如果存在则会添加失败。因此完全可以利用该特点来进行分布式锁的实现,而且由于memcached的数据全部可以设置过期时间,所以也完全不用担心如果中途memcached出现宕机会造成影响。

2.3、基于redis实现

      redis的实现方式,其实基本上和memcached相同,两者都是NoSQL,也都可以看做是原子操作,所以SETNX(SET if Not eXists),也可以拿来作为和add方法一样的实现方式。设置成功返回1,则表示获取锁成功,就可以为所欲为啦。而如果设置锁失败,就会返回0。

2.4、基于Zookeeper来实现

      zookeeper是一种为分布式系统提供唯一性保证的存储型服务,它的内部是一个分布式的树形的目录结构,同一个集群中,zookeeper保证了同一个目录下,集群中不会出现相同名字的文件。

     所以zookeeper的实现方式主要靠在获取锁的同时,对zookeeper的目录下创建一个临时节点来保证,只要这个临时节点是最小节点,那么就可以保证它可以获取到这个锁。操作完成后,再将该锁删除。

    注意两点,1、这里只有最小节点可以拿到锁,因为它是最早创建的那个;2、这里要创建临时节点,如果服务端由于网络问题,或者服务宕机从而导致链接断开,则这个临时节点也会被自我删除,保证了环境不受影响。例如在目录/my/t下开始创建临时节点,则依次会产生/my/t0000000001、/my/t0000000002、/my/t0000000003这样的子节点。这也是为什么说会选择最小节点的原因。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值