首页 » NoSQL » 分布式锁的原理与实现 一、分布式锁的原理

分布式锁的原理与实现 一、分布式锁的原理

原文 http://blog.csdn.net/HappyHeng/article/details/79253677

2018-02-05 02:00:49阅读(583)

一、分布式锁的使用场景

  在web开发中,我们经常会用到单机无法支撑业务的情况,比如,当在访问量比较大的情况下,单机的速度可能会很慢,因为同一时间单机的处理速度是有限的,这时我们就可以使用分布式来解决上述问题,由nginx来做一个负载均衡,把负载均匀的分布在多台单机上。

  当我们使用了分布式的架构后,问题也就随之而来了。比如一个业务我们需要串行化实现(通俗的说,也就是同一时间只能处理一个请求),那该怎么办呢?分布式锁的<a href=原理与实现 一、分布式锁的原理" alt="疑问" src="http://static.blog.csdn.net/xheditor/xheditor_emot/default/doubt.gif">

  举一个例子,现在需要实现一个领券的接口,一个券会对应多个券码,用户领取的是对应的券码,我们的处理逻辑如下:

分布式锁的原理与实现 一、分布式锁的原理

  乍一看流程很简单,我们只需要从数据库中取出一个可用的券码,然后与用户绑定即可,这不是一个很简单的问题么分布式锁的原理与实现 一、分布式锁的原理。可是仔细考虑一下,这里面其实是有并发问题的。

  比如,现在数据库中只有一个券码,按道理来说只允许有一个人来领取。但是这时候如果有两个请求同时过来,我们都走到了第一步,从数据库取出一个可用的券码,两个请求都取出来了。然后再进行绑定,然后返回成功。这时候就出现了问题。本来只允许一个人来领取,结果有两个人都领取成功了,就出现了bug。

  有人说了,解决这种情况使用java里面的 synchronized 关键字不就行了,但是这是在单机的情况下,可以保证多个线程下的安全,如果是分布式呢?有多台单机呢?java里面的 synchronized 就不行了。所以这种情况下,我们需要使用分布式锁,保证在分布式的情况下也能串行的处理业务。


二、分布式锁的原理

  分布式锁如何实现呢?如何保证在分布式的情况下串行处理?分布式锁的原理与实现 一、分布式锁的原理

  这时候需要使用到Redis,众所周知,Redis是一个高性能的key-value内存数据库。我们可以使用里面的 set Nx 命令,即在没有这个key的时候设置value。当设置成功后,表示我们拿到了这个分布式锁,即可以执行我们的业务,在业务执行成功后,使用 del 命令来删除对应的分布式锁的key。

  即,我们需要一个分布式锁的key,这个key是与对应分布式业务挂钩的。比如上述场景,我们使用一个 distributed_key_card_code 来作为key,然后在需要执行业务之前使用 set Nx 来设置 distributed_key_card_code 这个key-value。如果成功了,即可以处理业务。

  但是上述处理还有一些问题,具体在生产环境中的处理逻辑见下:


三、分布式锁的问题

  上述处理会带来两个问题:

  1、如果没有获取到分布式锁怎么办?

  使用 synchronized 关键字时,如果没有获取到锁,会一直等待,直到获取锁。那么按照上述逻辑,如果没有获取到分布式锁,那么有两种处理逻辑,一种是直接失败,一种即是重试,即在指定时间内一直重试(当然中间会有暂停),我们知道前端在请求接口中是有超时时间的,如果我们在这些时间内没有获取到分布式锁,那么就只能失败了。

  2、假如在一个分布式系统中,有三台单机,分别是单机A、单机B、单机C。这时候假如单机A拿到了分布式锁,然后单机A宕机了,单机B和单机C岂不是拿不到分布式锁了?

  是的,这个问题很致命,所以我们需要给分布式锁设置一个超时时间,避免因为单机的宕机导致整个分布式锁系统的崩溃。

  3、如果设置超时时间,比如一个分布式锁给设置5s的超时时间,假如单机A设置了这个超时时间,但是单机A在5s内没有完成业务,然后单机B拿到了锁,这之后单机A完成了业务,把分布式锁删除了,这时候单机C就拿到了这个分布式锁。导致了单机B、单机C同一时间都在处理业务。

  解决这个问题的方案就是,一个单机在获取分布式锁的时候,即使用 setNx 命令的时候,给对应的分布式锁的key设置一个随机的value值,然后记住这个value值,当完成业务后,get分布式锁的value,当发现是之前自己设置的value时,才删除分布式锁。


   





最新发布

CentOS专题

关于本站

5ibc.net旗下博客站精品博文小部分原创、大部分从互联网收集整理。尊重作者版权、传播精品博文,让更多编程爱好者知晓!

小提示

按 Ctrl+D 键,
把本文加入收藏夹