Redis分布式锁

原创 2018年01月02日 14:33:43

原文:https://redis.io/topics/distlock
翻译:http://udn.yyuap.com/article-6007.html

缓存主要目的是加快查询的速度,最好不要频繁的改动。

但现在有个需求,网站每个店铺的访问量,这个数值,是频繁变动的,也放到redis中了。而且用分布式部署。

对这个数值的操作是读出来,加一,再写回去。这三步应该是原子操作,不应该多个线程交叉进行,否则会出现错误。

如果没有分布式,代码只在一个机器上运行,那么可以在这段代码上加上synchronized关键字保证线程同步。

其实synchronized也就是将一个对象作为锁,线程要想执行代码,必须先获得锁,同一时间只有一个线程有锁,就可以保证线程同步。
参考:https://www.cnblogs.com/QQParadise/articles/5059824.html(synchronized)

现在是分布式系统,一份代码部署到了几台机器上,要想实现线程同步,同样需要一把锁,这个锁可以放到redis中。
参考:https://redis.io/commands/set(set命令)
https://redis.io/commands/setnx(setnx命令)

如果只有一条redis服务器,可以这样做:
对每个店铺设一个锁

SET store_id current_time_mills NX PX 30000

如果store_id不存在,就将它的值设为一个唯一值,设置过期时间为30s,返回值为“OK”,获得锁。如果store_id已经存在,就什么都不做,返回值为“NULL”,没有获得锁,等待,再试。
这里写图片描述

如上图所示,一个线程获得锁后,分几种情况,一个是线程出错了,他没有正常结束,这样锁到期后,会自动打开;还有一种情况是线程正常执行,执行完后要释放锁,释放锁,就是将store_id关键词删除。这又分两种情况,一种是执行时间比锁过期时间短,执行完,删除锁,没有问题;还有一种情况是执行时间比较长,超过了锁过期时间,这是要是删除的话,可能就是删除别的线程的锁了,这样就会出现多个线程同时执行。所以在删除时简单判断下,就可以避免这种情况:

if redis.call("get",KEYS[1]) == ARGV[1]
then
    return redis.call("del",KEYS[1])
else
    return 0
end

判断值是不是当初设的值(所有这个值要唯一),如果是删除,如果不是什么都不做。

如果只有一个redis,这个redis崩溃后,同步机制就瘫痪了。多个redis保证安全。
多个redis是这样做的:
Redlock算法:

  1. 记录当前时间,以毫秒为单位;
  2. 以串行的方式尝试从所有的N个实例中获取锁,使用的是相同的key值和相同的随机的value值。在从每个redis实例获取锁时,客户端会设置一个连接超时,其时长相比锁的自动释放时间要短的多。例如,如果锁的自动释放时间是10s,那么连接超时大概设置在5~50ms之间。这可以避免当Redis节点关掉时,会长时间堵住客户端,如果这个节点没及时响应,就应该尽快转到下个节点。
  3. 客户端计算获取所有锁耗费的时长,方法是当前时间减去步骤1中的时间戳。当且仅当客户端能从多数节点(n/2+1)中获得锁,并且耗费时长小于锁的有效期时,可以认为锁已经获得了。
  4. 如果锁获得了,它的最终有效时长将重新计算为远时长将去步骤3中获取锁耗费的时长;
  5. 如果锁获取失败了(要么是没有锁住N/2+1个节点,要么是锁的最终有效时长为负数),客户端会对所有实例进行解锁操作(即时对没有加锁成功的实例也一样)

分布式锁的作用及实现(Redis)

一、什么是分布式锁?要介绍分布式锁,首先要提到与分布式锁相对应的是线程锁、进程锁。线程锁:主要用来给方法、代码块加锁。当某个方法或代码使用锁,在同一时刻仅有一个线程执行该方法或该代码段。线程锁只在同一...
  • L_BestCoder
  • L_BestCoder
  • 2018-02-19 15:29:38
  • 1463

基于redis的分布式锁的实现

之前一直对分布式锁有所思考。一直觉得现在高性能的redis是个不错的选择; 关于分布式锁的思考 今天也尝试着写了一个基于redis的分布式锁工具 LockUtil.java package yyf...
  • qq_18860653
  • qq_18860653
  • 2017-02-07 10:51:09
  • 2357

基于Redis实现简单的分布式锁

在分布式场景下,有很多种情况都需要实现最终一致性。在设计远程上下文的领域事件的时候,为了保证最终一致性,在通过领域事件进行通讯的方式中,可以共享存储(领域模型和消息的持久化数据源),或者做全局XA事务...
  • hupoling
  • hupoling
  • 2016-11-30 17:47:59
  • 2776

Redis分布式锁思考

redis分布式锁
  • xiangyubobo
  • xiangyubobo
  • 2015-12-26 15:57:11
  • 2401

分布式锁实现方案(REDIS,ZOOKEEPER,TAIR)

Zookeeper 1、原生ZK方案 Zookeeper中有一种节点叫做顺序节点,假如我们在/lock/目录下创建节3个点,ZooKeeper集群会按照提起创建的顺序来创建节点,节点分别为...
  • z69183787
  • z69183787
  • 2017-03-30 13:25:12
  • 4105

Zookeeper、Redis分布式锁,实现与区别

Zookeeper Redis 分布式锁 实现与区别
  • qq_19568599
  • qq_19568599
  • 2016-09-21 19:51:30
  • 2593

经过线上实战的redis 分布式锁与zookeeper分布式锁区别

经过线上实战的redis 分布式锁代码。     能用,但是性能较差。 已考虑:     1.只能被拥有锁的线程解锁     2. 设置节点和超时时间用同一个key  未考虑:  1...
  • fei33423
  • fei33423
  • 2016-03-18 13:57:46
  • 8842

Redis实现分布式锁原理与实现分析

一、关于分布式锁 关于分布式锁,可能绝大部分人都会或多或少涉及到。  我举二个例子:  场景一:从前端界面发起一笔支付请求,如果前端没有做防重处理,那么可能在某一个时刻会有二笔一样的单子...
  • jp413670706
  • jp413670706
  • 2016-10-05 08:02:04
  • 6943

使用redis和zookeeper实现分布式锁

redis和zookeeper实现分布式锁
  • haitunlianren
  • haitunlianren
  • 2017-07-01 14:18:21
  • 542

使用Redis实现分布式锁

1.实现分布式锁的几种方案     1.Redis实现   (推荐)     2.Zookeeper实现     3.数据库实现 Redis实现分布式锁 * * 在集群等多服务器中经常使用...
  • he90227
  • he90227
  • 2017-04-07 16:28:24
  • 4942
收藏助手
不良信息举报
您举报文章:Redis分布式锁
举报原因:
原因补充:

(最多只允许输入30个字)