分布式锁

  为什么需要有分布式锁呢,在单点的时候synchronized 就能解决,但是服务拆分之后,每个服务都是单独的机器,无法解决,所以出现了分布式锁,其实也就是用各种手段,实现获取唯一锁,别人无法得到。

  其实在做分布式锁的前提,需要先明白,synchronized  为啥不能使用了,啥原理让他在一个机器上可以使用。

  


synchronized 的原理   

众所周知 Synchronize 关键字是解决并发问题常用解决方案,有以下三种使用方式:

  • 同步静态方法,锁的是当前 Class 对象。
  • 同步块,锁的是 {} 中的对象。
  • 同步普通方法,锁的是当前对象。

  实现原理:
  JVM 是通过进入、退出对象监视器( Monitor )来实现对方法、同步块的同步的。

  具体实现是在编译之后在同步方法调用前加入一个 monitor.enter 指令,在退出方法和异常处插入 monitor.exit 的指令。

  其本质就是对一个对象监视器( Monitor )进行获取,而这个获取过程具有排他性从而达到了同一时刻只能一个线程访问的目的。

  而对于没有获取到锁的线程将会阻塞到方法入口处,直到获取锁的线程 monitor.exit 之后才能尝试继续获取锁。

可以通过使用 javap -c Synchronize 可以查看编译之后的具体信息 ,这里我就不再粘贴了。

所以可以知道,单独的Java虚拟机是可实现锁的,但是多台手就伸不到了,只能在依赖外部的形式去产生一个唯一锁。

以上是参考别人的博客拿到的信息,亲自试用得到,准确   :链接:https://www.jianshu.com/p/2ba154f275ea


  Redis实现的分布式锁

  主要是利用了redis的set NX的原理,以及对redis的script脚本原子性利用。(个人看法,其实后面一步就看各自的程序逻辑如何去判定到底要不要这一步了)

  简单的说一下主要流程:

  1. 首先设置一个全局唯一的key和一个唯一性的value(value是一个解锁的保障,删除之前判断一下值是否一致)
  2. 使用Redis的set 方法 以多参数形式配置key,value,nx,px,过期时间 (参数 NX:只有键不存在时,才能对其进行设置操作)
  3. 利用Redis的script脚本来对key的删除操作,只能自己删除自己的value(删除之前先判断一下value是否是我之前的value,是否被改过,没有就删了)

   这是脚本的主要 内容 if redis.call("get",KEYS[1]) == ARGV[1] then return redis.call("del",KEYS[1]) else  return 0 end

   对其解释: 根据 get 获取到 key 的值 ,判断key的值是否跟你传的值相等,相等则 执行del  key 否则返回0 结束
   对此推荐去看一下redis的Lua脚本,给个简单的:http://redisdoc.com/script/eval.html
  
  在实际场景中可以利用AOP的切点切面形式,实现具体是什么地方需要分布式锁,搭配分布式锁,再搭配注解方式,来实现想要的自定义设置那里需要就点哪里
  AOP的主要实现是
  1. @pointcut 切注解类
  2. 在使用@around环绕对前后做处理
  3. 前面加锁
  4. 后面解锁del  使用script脚本
  

  代码主要实现

  注解类 DistributedLock

  

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface DistributedLock { /**
* 自定义形式添加你对分布式锁的对外配置属性
* 例如:key的规则,锁的超时时间,获取锁的等待时间,等一系列的属性配置
*
*/ }
  切面类 DistributedLockAspect
@Aspect
@Component
public class DistributedLockAspect { /**
* 层切点
*/
@Pointcut("@annotation(com.creditease.hardess.common.annotation.DistributedLock)")
public void distributedLockAspect() {} /**
* @param joinPoint 切点
* @return Object 添加分布式锁后,实际调用业务逻辑部分代码的返回值
* @throws Throwable 产生的所有异常,为了避免对异常处理流程产生干扰,所有异常都应该继续抛出
*/
@Around("distributedLockAspect()")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
/**
*主要写一些锁的获取,和业务逻辑执行,锁的删除等
*
*/
return returnObject;
} /**
* 获取 DistributedLock 注解
*
* @param joinPoint
* @return 代码中定义的注解
* @throws NoSuchMethodException
*/
private static DistributedLock getDistributedLock(ProceedingJoinPoint joinPoint)
throws NoSuchMethodException {
String methodName = joinPoint.getSignature().getName(); Class<?> classTarget = joinPoint.getTarget().getClass();
Class<?>[] par = ((MethodSignature) joinPoint.getSignature()).getParameterTypes();
Method objMethod = classTarget.getMethod(methodName, par); return objMethod.getAnnotation(DistributedLock.class);
} } }

分布式锁----Redis实现的更多相关文章

  1. 分布式锁--Redis小试牛刀

    参考文章: Redis分布式锁的正确实现方式 分布式锁看这篇就够了 在这两篇文章的指引下亲测 Redis分布式锁 引言 分布式系统一定会存在CAP权衡问题,所以才会出现分布式锁 什么是CAP理论? 为 ...

  2. Redis除了做缓存--Redis做消息队列/Redis做分布式锁/Redis做接口限流

    1.用Redis实现消息队列 用命令lpush入队,rpop出队 Long size = jedis.lpush("QueueName", message);//返回存放的数据条数 ...

  3. java-spring基于redis单机版(redisTemplate)实现的分布式锁+redis消息队列,可用于秒杀,定时器,高并发,抢购

    此教程不涉及整合spring整合redis,可另行查阅资料教程. 代码: RedisLock package com.cashloan.analytics.utils; import org.slf4 ...

  4. 分布式锁redis

    1. 首先看这篇文章中  https://mp.weixin.qq.com/s/s-ozSjM5WmSUopxttSWYeQ 为什么redis能实现锁功能呢,看下图,redis命令窗口中,setnx  ...

  5. 分布式锁-Redis方案

    #!/usr/bin/env python # coding=utf-8 import time import redis class RedisLock(object): def __init__( ...

  6. Lua脚本在redis分布式锁场景的运用

    目录 锁和分布式锁 锁是什么? 为什么需要锁? Java中的锁 分布式锁 redis 如何实现加锁 锁超时 retry redis 如何释放锁 不该释放的锁 通过Lua脚本实现锁释放 用redis做分 ...

  7. Redis 分布式锁的实现

    0X00 测试环境 CentOS 6.6 + Redis 3.2.10 + PHP 7.0.7(+ phpredis 4.1.0) [root@localhost ~]# cat /etc/issue ...

  8. 分布式交易系统的并发处理, 以及用Redis和Zookeeper实现分布式锁

    交易系统 交易系统的数据结构 支付系统API通常需要一个“订单号”作为入参, 而实际调用API接口时使用到的往往不是真正意义的业务订单号, 而是交易订单号.  支付系统的API会使用“商户号+订单号” ...

  9. 基于zookeeper或redis实现分布式锁

    前言 在分布式系统中,分布式锁是为了解决多实例之间的同步问题.例如master选举,能够获取分布式锁的就是master,获取失败的就是slave.又或者能够获取锁的实例能够完成特定的操作. 目前比较常 ...

随机推荐

  1. <iOS 导航栏>第一节:导航栏透明方法实现代码

      说下导航栏的透明方法:   很多应用需要导航栏随着向上滑动,逐渐从透明变成不透明,很炫酷,大部分应用都在使用导航栏渐变效果,现附上代码然后直接将实现,一会讲下如何来实现,这一部分直接上代码.   ...

  2. python常用点小记

    记录一下,经常用到的一些python小工具 1.验证一个字符串是否为url regex = re.compile( r'^(?:http|ftp)s?://' # http:// or https:/ ...

  3. python连接数据库(2)——mongodb

    mongodb是近一段时间以来比较流行的非关系数据库之一,由于python和它都对json类型有着很好的支持,因此配合起来可谓天衣无缝. 首先要下载python对mongodb支持的包pymongo ...

  4. springboot如何读取自定义配置项

    我们springboot项目有自己默认的配置文件,一般地由application.yml和bootstrap.yml组成,前者是模块的配置,后者是微服务的配置,后台比前者先被框架加载. 我们有时需要自 ...

  5. 微服务网关 Spring Cloud Gateway

    1.  为什么是Spring Cloud Gateway 一句话,Spring Cloud已经放弃Netflix Zuul了.现在Spring Cloud中引用的还是Zuul 1.x版本,而这个版本是 ...

  6. python函数之 range()

      Python range() 函数用法 python range() 函数可创建一个整数列表,一般用在 for 循环中. 函数语法 range(start, stop[, step]) 参数说明: ...

  7. asyncio源码分析之基本执行流程

    基于async关键字的原生协程 # 定义一个简单的原生协程cor async def cor(): print('enter cor') print('exit cor') print(type(co ...

  8. POJ 3621:Sightseeing Cows(最优比率环)

    http://poj.org/problem?id=3621 题意:有n个点m条有向边,每个点有一个点权val[i],边有边权w(i, j).找一个环使得Σ(val) / Σ(w)最大,并输出. 思路 ...

  9. iOS 矢量图pdf替换2倍3倍图

    一.在开发中矢量图的使用大大提高设计的切图效率! ios 中可以用pdf替换现在的2倍3倍图(1倍图已经忽略) 1.将pdf矢量图拖进工程Assets.xcassets中 2.按照步骤操作 3.矢量图 ...

  10. Vue技术点整理 vue-devtools

    注:默认浏览器调试工具,在调试vue的页面时,是不能看到vue项目的属性状态值的,所以最好是在浏览器上安装 vue-devtools,这样就可以在浏览器里面审查和调试vue的应用了 1,Chrome浏 ...