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. Python-面向对象(二)-Day7

    1.字段 12.方法 43.属性 63.1.属性的基本使用 73.2.实例:对于主机列表 83.3.属性的两种定义方式 94.对于类的成员而言都有两种形式: 144.1.私有成员和公有成员的访问限制不 ...

  2. 新概念英语(1-129)Seventy miles an hour

    Lesson 129 Seventy miles an hour 时速70英里 Listen to the tape then answer this question. What does Ann ...

  3. linux下的Shell编程(8)自定义函数

    Shell Script中也可以使用自定义的函数,其语法形式如下: functionname() { - }

  4. 新概念英语(1-17)How do you do ?

    Is there a problem wtih the Customers officer? What are Michael Baker and Jeremy Short's jobs? A:Com ...

  5. 2.x与3.x差异、条件语句、数据类型、其他

    一.输入(raw_input)=====>python2.x版本 #!/usr/bin/env python # -*- coding: utf-8 -*- # 将用户输入的内容赋值给 name ...

  6. python的单元测试

    单元测试实际上就是一些"断言"(assert)代码 断言就是判断一个函数或对象的一个方法所产生的结果是否符合你期望的那个结果. python中assert断言是声明布尔值为真的判定 ...

  7. JVM 掌握要点

    重读JVM jvm系列:jvm知识点总览 1. 认识Java虚拟机 默认Hotspot实现 2. 类加载机制 知道双亲委派模型 编译为class javac → 装载 class ClassLoade ...

  8. 移动端,input输入框被手机输入法解决方案

    当界面元素靠下时候的时候,input输入框会被系统的键盘遮挡. 我们可以让界面向上移动一定距离去避免遮挡. $('#money').click(function(){ setTimeout(funct ...

  9. [转]scrapy中的request.meta

    作者:知乎用户链接:https://www.zhihu.com/question/54773510/answer/146971644 meta属性是字典,字典格式即{'key':'value'},字典 ...

  10. javascript的变量声明、数据类型

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...