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实现分布式锁

在很多互联网产品应用中,有些场景需要加锁处理,比如:秒杀,全局递增ID,楼层生成等等。大部分的解决方案是基于DB实现的,Redis为单进程单线程模式,采用队列模式将并发访问变成串行访问,且多客户端对R...
  • ugg
  • ugg
  • 2014年12月12日 16:33
  • 154687

基于redis分布式锁实现“秒杀”

最近在项目中遇到了类似“秒杀”的业务场景,在本篇博客中,我将用一个非常简单的demo,阐述实现所谓“秒杀”的基本思路。 业务场景 所谓秒杀,从业务角度看,是短时间内多个用户“争抢”资源,这里的...
  • u010359884
  • u010359884
  • 2015年12月18日 08:15
  • 42964

redis分布式锁

  • 2017年09月30日 09:41
  • 647KB
  • 下载

基于redis分布式锁实现“秒杀”

  • 2017年03月01日 15:02
  • 353KB
  • 下载

Redis实现分布式锁

在集群等多服务器中经常要使用到同步处理一下业务,这时普通的事务是满足不要业务需求,需要分布式锁。分布式锁的实现方式有多种,如redis实现分布式锁,zookeeper实现分布式锁等,这篇先实现redi...
  • fengshizty
  • fengshizty
  • 2016年12月10日 22:08
  • 8781

基于redis的分布式锁的实现

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

利用redis实现的分布式锁

假设一个场景: 在分布式系统中,通常会遇到多个服务器处理同一个业务的场景,我们需要利用某种机制避免并发问题。Java语言中,我们可以通过锁的方式避免单个服务的多线程并发问题,而分布式系统中的并发问题用...
  • yuxxz
  • yuxxz
  • 2016年09月15日 23:33
  • 3477

使用Redis实现分布式锁

1.实现分布式锁的几种方案     1.Redis实现   (推荐)     2.Zookeeper实现     3.数据库实现 Redis实现分布式锁 * * 在集群等多服务器中经常使用...
  • he90227
  • he90227
  • 2017年04月07日 16:28
  • 2922

Redis实现分布式锁

基于Redis实现分布式锁
  • java2000_wl
  • java2000_wl
  • 2013年07月26日 22:05
  • 44104

Redis学习笔记(六)redis实现分布式锁

分布式锁介绍 注:本文讲的是分布式互斥锁 在很多互联网产品应用中,有些场景需要加锁处理,比如:秒杀,全局递增ID,楼层生成,还有一些分布式任务调度等等。大部分的解决方案是基于DB实现的,Redis...
  • fgyibupi
  • fgyibupi
  • 2016年12月21日 12:08
  • 5462
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Redis分布式锁
举报原因:
原因补充:

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