redis锁处理并发问题

redis锁处理高并发问题十分常见,使用的时候常见有几种错误,和对应的解决办法。

  • set方式
  • setnx方式
  • setnx+getset方式

set方式 
加锁:redis中set一个值,set(lock,1); 
并发处理:其他线程必须拿到这个值,才可以往下进行,否则等待。

while(jedis.exists(lock)){
Thread.sleep(500);
}
set(lock,1);
执行业务代码;
jedis.del(lock);

释放锁:执行完业务代码之后,释放redis锁,jedis.del(lock) 
防止死锁:set(lock,1) —>3秒后未释放,则自动释放setex(lock, 3, 1) 
问题:高并发情况下,进程同时获取锁状态为null,同时设置,锁之间相互覆盖,但是俩进程仍在并发执行业务代码。

setnx方式 
后来发现有setnx的原子操作命令,锁存在不能设置值,返回0;锁不存在,则设置锁,返回1; 
加锁:jedis.setnx(lock, 1) 
并发处理:

while(jedis.setnx(lock,1)==0){
Thread.sleep(300);
}
执行业务代码;
jedis.del(lock);

释放锁:执行完业务代码之后,释放redis锁,jedis.del(lock) 
问题:当进程执行出现问题,锁未释放,则其他进程永远处于阻塞状态,出现死锁。 
防止死锁:加锁时带上时间戳,setnx(lock, 时间戳+超时时间)

while(jedis.setnx(lock,now+超时时间)==0){
if(jedis.get(lock)<now){
jedis.del(lock);
jedis.setnx(lock,now+超时时间);
break;
}else{
Thread.sleep(300);
}
}
执行业务代码;
jedis.del(lock);

问题:当俩进程同时读到发现锁超时,都去释放锁,相互覆盖,则俩进程同时获得锁,仍并发执行业务代码。

setnx+getset方式 
为解决上面的问题,可以使用getset命令,getset设置键值,并返回原来的键值。 
加锁:setnx(lock, 时间戳+超时时间) 
解决并发

while(jedis.setnx(lock, now+超时时间)==0){
if(now>jedis.get(lock) && now>jedis.getset(lock, now+超时时间)){
break;
}else{
Thread.sleep(300);
}
}
执行业务代码;
jedis.del(lock);

释放锁:jedis.del(lock);

redis锁处理并发问题的更多相关文章

  1. (实例篇)php 使用redis锁限制并发访问类示例

    1.并发访问限制问题 对于一些需要限制同一个用户并发访问的场景,如果用户并发请求多次,而服务器处理没有加锁限制,用户则可以多次请求成功. 例如换领优惠券,如果用户同一时间并发提交换领码,在没有加锁限制 ...

  2. php 使用redis锁限制并发访问类

    1.并发访问限制问题 对于一些需要限制同一个用户并发访问的场景,如果用户并发请求多次,而服务器处理没有加锁限制,用户则可以多次请求成功. 例如换领优惠券,如果用户同一时间并发提交换领码,在没有加锁限制 ...

  3. PHP进阶与redis锁限制并发访问功能示例

    <?php /** * Redis锁操作类 * Date: 2017-06-30 * Author: fdipzone * Ver: 1.0 * * Func: * public lock 获取 ...

  4. redis 初步认识四(redis锁,防并发)

    using System; namespace ConsoleAppRedis { class Program { static void Main(string[] args) { //第一种,无登 ...

  5. 使用Redis构建全局并发锁

    谈起Redis的用途,小伙伴们都会说使用它作为缓存,目前很多公司都用Redis作为缓存,但是使用Redis仅仅作为缓存未免太大材小用了.深究Redis的原理后你会发现它有很多用途,在很多场景下能够使用 ...

  6. 多线程并发问题解决之redis锁

    一 问题背景 我们做的是医疗信息化系统,在系统中一条患者信息对医院中当前科室中的所有诊断医生是可见的,当有一个诊断医生点击按钮处理该数据时,数据的状态发生了变化,其他的医生就不可以再处理此患者的数据了 ...

  7. Redis构建全局并发锁

    Redis构建全局并发锁 https://www.cnblogs.com/FG123/p/9990336.html 谈起Redis的用途,小伙伴们都会说使用它作为缓存,目前很多公司都用Redis作为缓 ...

  8. 利用Redis锁解决高并发问题

    这里我们主要利用Redis的setnx的命令来处理高并发. setnx 有两个参数.第一个参数表示键.第二个参数表示值.如果当前键不存在,那么会插入当前键,将第二个参数做为值.返回 1.如果当前键存在 ...

  9. 利用 Redis 锁解决高并发问题

    这里我们主要利用 Redis 的 setnx 的命令来处理高并发. setnx 有两个参数.第一个参数表示键.第二个参数表示值.如果当前键不存在,那么会插入当前键,将第二个参数做为值.返回 1.如果当 ...

随机推荐

  1. 使用 dynamic 类型让 ASP.NET Core 实现 HATEOAS 结构的 RESTtful API

    上一篇写的是使用静态基类方法的实现步骤:  http://www.cnblogs.com/cgzl/p/8726805.html 使用dynamic (ExpandoObject)的好处就是可以动态组 ...

  2. python入门(9)字符串和编码

    python入门(9)字符串和编码 字符串是一种数据类型,比较特殊的是字符串有一个编码问题. 因为计算机只能处理数字,如果要处理文本,就必须先把文本转换为数字才能处理. 最早的计算机在设计时采用8个比 ...

  3. python 爬取百度翻译进行中英互译

    感谢RoyFans 他的博客地址http://www.cnblogs.com/royfans/p/7417914.html import requests def py(): url = 'http: ...

  4. Django—中间件

    中间件简介 什么是中间件 中间件是一个用来处理Django的请求和响应的框架级别的钩子.它是一个轻量.低级别的插件系统,用于在全局范围内改变Django的输入和输出.每个中间件组件都负责做一些特定的功 ...

  5. 路由测试-lee

    //get 路由 Route::get('/', 'WelcomeController@index'); Route::get('home', 'HomeController@index'); //路 ...

  6. AFNetWorking常用方法

    NSURLConnection,主要对NSURLConnection进行了进一步的封装,包含以下核心的类: AFURLConnectionOperation AFHTTPRequestOperatio ...

  7. Javascript闭包(Closure)

    1.Javascript特殊的变量作用域.变量的作用域无非就是两种:全局变量和局部变量.Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量. function f1() { var ...

  8. RPC服务和HTTP服务

    很长时间以来都没有怎么好好搞清楚RPC(即Remote Procedure Call,远程过程调用)和HTTP调用的区别,不都是写一个服务然后在客户端调用么?这里请允许我迷之一笑~Naive!本文简单 ...

  9. Gold well平台罗琪:叙利亚战火令黄金看涨意愿强烈

    Gold well平台罗琪:叙利亚战火令黄金看涨意愿强烈基本面分析:纸黄金交易通网显示,全球最大黄金上市交易基金(ETF)截至04月14日黄金持仓量较上日持平,当前持仓量为865.89吨,本月止净增持 ...

  10. input和textarea标签的select()方法----选中文本框中的所有文本

    JavaScript select()方法选中文本框中的所有文本 <input>和<textarea>两种文本框都支持select()方法,这个方法用于选择文本框中的所有文本 ...