1.原理: 当同一个用户获取锁之后,会让该用户一直持有锁。同样 的用户再次获取,会根据原子性 ,lock返回true。

 /**
* 获取锁(非公平锁), 默认获取超时为2分钟
*/
public boolean lock(){
return lock(GETLOCK_TIMEOUT/);
}
/**
* 获取锁(非公平锁), 获取超时为timeoutSeconds秒
*/
public boolean lock(int timeoutSeconds){
int timeout = timeoutSeconds*;
while (timeout >= ) {
//在同一个JVM内,防止出现以下情况:当已经获取此锁的线程实际业务运行时间超过LOCK_EXPIRE_TIMEOUT时,此锁会再被其它线程获取
if(LOCKED_NAMES.contains(lockname)){
int sleeptime = random.nextInt()+;
try{Thread.sleep(sleeptime);} catch (InterruptedException e) {}
timeout -= sleeptime;
continue;
}
//当分布式程序获取同一个锁时,防止出现以下情况:当已经获取此锁的进程(物理机器)实际业务运行时间超过LOCK_EXPIRE_TIMEOUT时,此锁会再被其它进程(物理机器)获取
String hearbeatFlag = RedisCacheUtil.get(lockname + HEARTBEAT_SUFFIX , String.class );
if(hearbeatFlag!=null){
int sleeptime = random.nextInt()+;
try{Thread.sleep(sleeptime);} catch (InterruptedException e) {}
timeout -= sleeptime;
continue;
} //锁到期时间
long expires = System.currentTimeMillis() + LOCK_EXPIRE_TIMEOUT + ;
boolean ok = setNX(expires);
if (ok) {
//System.out.println(Thread.currentThread().getName()+":获得锁成功,通过setNX");
LOCKED_NAMES.add(lockname);
locked = true;
return locked;
}
//获取当前锁信息
RedisLockValue redisLockValue = get();
if (redisLockValue != null && redisLockValue.getExpireTime() < System.currentTimeMillis()) {
//利用getSet的原子性操作来设置并获取到旧值
RedisLockValue oldRedisLockValue = getSet(expires);
//最先设置的获取锁
if (oldRedisLockValue != null && oldRedisLockValue.getToken().equals(redisLockValue.getToken())) {
//System.out.println(Thread.currentThread().getName()+":获得锁成功,通过getSet");
LOCKED_NAMES.add(lockname);
locked = true;
return locked;
}
}
//防止饥饿线程出现 采用随机休眠时间
int sleeptime = random.nextInt()+;
try{Thread.sleep(sleeptime);} catch (InterruptedException e) {}
timeout -= sleeptime;
} //如果已经超时,但只是因为此时缓存还有值,因为反序列化异常导致GET取不到时,解决死锁问题
try{Thread.sleep();} catch (InterruptedException e) {}
RedisLockValue redisLockValue = get();
if(redisLockValue==null){
//强制删掉即可
LOCKED_NAMES.remove(lockname);
RedisCacheUtil.delete(lockname);
RedisCacheUtil.delete( lockname + HEARTBEAT_SUFFIX );
}
return locked;
}

使用redis 处理高并发场景的更多相关文章

  1. 高并发场景系列(一) 利用redis实现分布式事务锁,解决高并发环境下减库存

    原文:http://blog.csdn.net/heyewu4107/article/details/71009712 高并发场景系列(一) 利用redis实现分布式事务锁,解决高并发环境下减库存 问 ...

  2. 高并发场景之RabbitMQ篇

    上次我们介绍了在单机.集群下高并发场景可以选择的一些方案,传送门:高并发场景之一般解决方案 但是也发现了一些问题,比如集群下使用ConcurrentQueue或加锁都不能解决问题,后来采用Redis队 ...

  3. 高并发场景之RabbitMQ

    高并发场景之RabbitMQ 上次我们介绍了在单机.集群下高并发场景可以选择的一些方案,传送门:高并发场景之一般解决方案 但是也发现了一些问题,比如集群下使用ConcurrentQueue或加锁都不能 ...

  4. Java电商项目,秒杀,抢购等高并发场景的具体场景和一些概念以及处理思路

    这里我借鉴了网上其他大佬的观点: 一:高并发带来的挑战 原因:秒杀抢购会经常会带来每秒几万的高并发场景,为了更快的返回结果给用户. 吞吐量指标QPS(每秒处理请求数),假设一个业务请求响应耗时为100 ...

  5. 关于redis的几件小事(五)redis保证高并发以及高可用

    如果你用redis缓存技术的话,肯定要考虑如何用redis来加多台机器,保证redis是高并发的,还有就是如何让Redis保证自己不是挂掉以后就直接死掉了,redis高可用 redis高并发:主从架构 ...

  6. Redis的高并发、持久化、高可用架构设计

    就是如果你用redis缓存技术的话,肯定要考虑如何用redis来加多台机器,保证redis是高并发的,还有就是如何让Redis保证自己不是挂掉以后就直接死掉了,redis高可用 我这里会选用我之前讲解 ...

  7. MySQL在大数据、高并发场景下的SQL语句优化和"最佳实践"

    本文主要针对中小型应用或网站,重点探讨日常程序开发中SQL语句的优化问题,所谓“大数据”.“高并发”仅针对中小型应用而言,专业的数据库运维大神请无视.以下实践为个人在实际开发工作中,针对相对“大数据” ...

  8. 高并发场景-请求合并(二)揭秘HystrixCollapser-利用Queue和线程池异步实现

    背景 在互联网的高并发场景下,请求会非常多,但是数据库连接池比较少,或者说需要减少CPU压力,减少处理逻辑的,需要把单个查询,用某些手段,改为批量查询多个后返回. 如:支付宝中,查询"个人信 ...

  9. 高并发场景-请求合并(一)SpringCloud中Hystrix请求合并

    背景 在互联网的高并发场景下,请求会非常多,但是数据库连接池比较少,或者说需要减少CPU压力,减少处理逻辑的,需要把单个查询,用某些手段,改为批量查询多个后返回. 如:支付宝中,查询"个人信 ...

随机推荐

  1. python 字符串操作。。

    #字符串操作 以0开始,有负下标的使用0第一个元素,-1最后一个元素,-len第一个元 素,len-1最后一个元素 name= "qwe , erw, qwe "print(nam ...

  2. web的脚本安全-CSRF

    CSRF,即Cross-site request forgery,中文一般叫跨站请求伪造. 攻击原理是,用户在A网站(登录,之后打开一个B网站,B网站的脚本(或HTML标签)向A网站发送一个请求,这个 ...

  3. Android Design Support Library——Navigation View

    前沿 Android 从5.0开始引入了Material design元素的设计,这种新的设计语言让整个安卓的用户体验焕然一新,google在Android Design Support Librar ...

  4. PLSQL Developer是什么?

    不多说,直接上干货! PLSQL Developer是一款可以帮助用户管理Oracle数据库开发存储程序单元的集成开发环境IDE,通过该软件,用户可以编辑.编译.纠正.测试.调试.优化.查询您的数据信 ...

  5. 全网最详细的Windows里下载与安装Sublime Text *(图文详解)

    不多说,直接上干货! 前言 这是代码编程软件,可以性感编程自己代码,有着非常丰富的插件,界面整洁清爽.第一次使用可能不习惯,当你使用一段时间之后,你就会爱上它. 下载与安装 1.下载:目前官方的正式版 ...

  6. Spring开发步骤

    1) 源码, jar文件:此处用的是spring-framework-3.2.5.RELEASE commons-logging-1.1.3.jar                日志 spring- ...

  7. CentOS 7下搭配简单的C语言开发环境

    在CentOS 7下安装gcc,gcc是编译和运行C语言的工具, 安装命令: yum install gcc 中途如果有询问则输入y 安装成功后,通过以下命令 gcc --version 来查看安装的 ...

  8. VMware ESX常用命令

    一. VMware ESX Command 1. 看你的esx版本 vmware –v 2. 查看显示ESX硬件,内核,存储,网络等信息 esxcfg-info -a(显示所有相关的信息) esxcf ...

  9. 线程池ThreadPoolExecutor的一种扩展办法

    概述 在JAVA的世界里,如果想并行的执行一些任务,可以使用ThreadPoolExecutor. 大部分情况下直接使用ThreadPoolExecutor就可以满足要求了,但是在某些场景下,比如瞬时 ...

  10. es6学习笔记11--Proxy和Reflect

    Proxy概述 Proxy用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种“元编程”(meta programming),即对编程语言进行编程. Proxy可以理解成,在目标对象之前 ...