Redis 并发锁实现

Redis(九):并发问题 上一篇介绍了 Redis 的内存管理。这节开始介绍 Redis 并发方面的问题。Redis 的单个命令是原子的,但是一个业务操作可能包含多条命令,比如以下场景:客户端查询值,并递增,在高并发场景下就可能出现并发问题,导致数据不一致。为了保证并发访问的正确性,Redis 提供了三种方法,原子操作、分布式锁、事务。本文介绍了 Redis 应对并发问题的三种方案,Redis 中的单条命令都是原子操作,而且还有 INCR/DECR 来应对简单的场景。 阅读详情

听到Redis 实现并发锁,大家应该都很熟悉了,不知道有多少同学踩过redis并发锁的坑。

最近项目中有同学实现了并发锁,通过代码review还是发现有些同学理解的并不深入,为后续的运行埋下来了巨大的隐患,今天空闲之余再重温一下并发锁,希望多刚接触redis 锁的同学有启发。

首先列举一下几种常见的写法啊

1、第一种,也是在review代码时经常遇到的

 

Jedis jedis;

public boolean tryLock(String key){

    String value = jedis.get(key);

    if(org.apache.commons.lang3.StringUtils.isEmpty(value)){

        jedis.set(key,"1");
        jedis.expire(key,1000);

        return true;
    }

    return false;

}
这种写法有几个问题呢?
1 String value = jedis.get(key);   多线程高并发访问时,拿到的value都为空都能拿到锁,并发控制失效
2 jedis.set(key,"1") ;jedis.expire(key,1000); 非原子操作,设置失效时间失败时,其他线程将永远获取不到锁。造成死锁。

2、第二种也是经常遇到的,还是先上代码才有说服力

    

Jedis jedis;

public boolean tryLock(String key){

    long value = jedis.incr(key);
    
    // 已经有其他线程获取到锁
    if(value != 1)
    {
      return false;    
    }else
    {
        jedis.expire(key,100);
        return true;
    }
    

}

这种写法又有什么问题呢?

首先和第一个有相似之处的是,设置redis失效时间不是原子操作,中间任何异常导致设置失效时间出错时,会造成后续的死锁

 

看了这几个,有没有踩过同样的坑呢?

首先我认为写redis 并发锁,有几个坚持的原则

A、key和redis的失效时间是不是原子操作

B、get--》compare的方法在高并发场景写不可取

 

3、三是我们最常用的,能满足我们常规加锁需求

 

Jedis jedis;

// 加锁
public boolean tryLock(String key){

    String result = jedis.setex(key,1000,"1");


    if(StringUtils.equals("OK",result)){

        return true;
    }
 
    return false;
}


// 释放锁
public void  releaseLock(String key){
    
    jedis.del(key);
    
}
这里的实现思路是客户端进来加锁、任务执行完毕后释放锁,看上去这种方式是完美的。但......我们redis 设置都是主备的,
Client A 在master上得到锁,此时redis master Down机,redis将切换到Slave机器,Client B在此时去获取锁,
此时Client A的锁信息还有同步到Slave,这种情况Client A、B 都将获取到并发锁。
对于这种情况大家还是多看看redis 官方对并发锁的实现讲解。java 版本的开源实现并发锁Redisson
注:以上代码均为伪代码,有问题大家可以留言讨论,也希望文章对看到的人有些许用途 

 


 

 

 

 

 

PHP实现Redis单据锁,防止并发重复写入 一、写在前面: 在整个供应链系统中,会有很多种单据(采购单、入库单、到货单、运单等等),在涉及写单据数据的接口时(增删改操作),即使前端做了相关限制,还是有可能因为网络或异常操作产生并发重复调用的情况,导致对相同单据做相同的处理; 为了防止这种情况对系统造成异常影响,我们通过Redis实现了一个简单的单据锁,每个请求需先获取锁才能执行业务逻辑,执行结束后才会释放锁;保证了同一单据的并发重复操作... 阅读详情

相关推荐

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

问题描述:某电商平台,首发一款新品手机,每人限购2台,预计会有10W的并发,在该情况下,如果扣减库存,保证不会超卖 方案一 利用数据库机制,通过对记录进行锁定,再进行操作  SELECT * from goods where ID =1 for update; UPDATE goods set stock = stock - 1; 利用排它锁将并行转化为串行操作,但该方案的

Vision 1万+

3.秒杀模块-分布式加锁问题-如何利用Redis分布式锁实现控制并发

redis命令解释说道Redis的分布式锁都是通过setNx命令结合getset来实现的,在讲之前我们先了解下setNx和getset的意思,在redis官网是这样解释的 注:redis的命令都是原子操作SETNX key value(加入没有则设置,有则不设置了)将 key 的值设为 value ,当且仅当 key 不存在。 若给定的 key 已经存在,则 SETNX 不做任何动作。 SETNX...

郑学炜的技术博客 3179

IAR编译相同工程生产hex文件checksum不一致问题

IAR Checksum

xqw19891201的博客 1382

redis当中的读写锁

如何实现Redis中的读写锁 概述 在实际开发中,我们经常会碰到需要对数据进行读写操作的场景,而为了保证数据的一致性和并发性,我们需要使用读写锁。Redis中并没有原生支持读写锁的数据结构,但是我们可以借助Redis的原子操作来实现读写锁的功能。 流程 下面是实现Redis中读写锁的流程图: gantt title...

weixin_42306938的博客 347

手把手教你用STM32标准库写一个能OTA升级的Bootloader(附完整代码)

本文详细介绍了如何使用STM32标准库开发支持OTA无线升级的Bootloader系统,包括Flash分区规划、Bootloader核心实现、无线升级流程及安全校验机制。通过实战代码示例,帮助开发者快速掌握STM32固件升级技术,提升物联网设备的远程维护能力。

weixin_30181209的博客 262

2025年最新Cesium学习示例:Cesium-Examples

2025年最新Cesium学习示例:Cesium-Examples

2403_88103571的博客 1010

redisson 底层读写锁 lua实现原理

的一部分,用于标识不同的线程。这个方式可以帮助跟踪锁的持有者,以及每个线程持有该锁的次数。表示锁的主要标识,通常是一个唯一的标识符,比如对象名字或资源名字,用来表示被锁定的资源。通常用于记录哪些线程获取了该锁,每个线程的标识符会作为 KEYS[2]写锁逻辑比较简单..

weixin_56594835的博客 353

MaaS 商业模式全面分析报告:从技术赋能到商业变现的全链条探索

MaaS(模型即服务)商业模式正成为AI产业主流,2024年上半年中国市场规模达2.5亿元,预计2027年占比将提升至47%。该模式通过云服务提供预训练AI模型,大幅降低企业应用AI的技术门槛和成本。核心盈利方式包括按使用量计费、订阅制、定制化服务等,其中混合模式因灵活性成为趋势。MaaS产业链包含模型提供商、云平台、应用开发商和最终用户,重塑了AI产业格局。随着《数据法案》等监管加强,数据增值服务面临更严格合规要求。未来五年,中国MaaS市场增速预计超50%,用户规模将从2025年2.1亿增至2030年5

芯片行业20年 · 参与定义实现千万级量产出货 · AI芯片PM 2889

使用redis,怎么解决并发问题?

这样会明显降低数据处理效率。而线程不安全,是站在客户端的角度说的,redis是只有一个线程在工作,但是客户单端却是有成千上万个的,对于客户端来说,redis是被共享的资源,所以对于客户端来说依旧存在线程安全问题。线程安全,是站在reids的角度来说的,redis使用单线程模型,是不存在线程安全问题的,以为他只有一个线程,不存在多线程间数据的共享,俗话说没有共享就没有伤害。读库存和写库存操作,在redis中是单线程执行的,是原子性的,但是整个扣减库存的操作却不是原子性的,这也是出现线程不安全的根本原因。...

weixin_45701550的博客 9410

群晖Hyper Backup还原实战:加密与非加密备份的完整操作指南

本文详细介绍了群晖Hyper Backup在加密与非加密备份场景下的完整还原操作指南。通过实战案例和高级技巧,帮助用户应对硬盘故障或系统崩溃时的数据恢复挑战,特别是加密备份恢复中的关键节点和常见陷阱。

weixin_29323365的博客 439

YOLOv5+Astra Pro Plus深度相机:手把手教你实现实时目标检测(附ROS配置技巧)

本文详细介绍了如何将YOLOv5目标检测算法与Astra Pro Plus深度相机结合,构建实时目标检测系统。内容涵盖从硬件选型、环境搭建、ROS配置到YOLOv5部署与深度信息融合的完整流程,并分享了性能优化、避障算法等实战技巧,帮助开发者在机器人视觉等场景中快速实现智能感知应用。

weixin_28292761的博客 387

redis并发锁机制 java_【redis】基于redis实现分布式并发锁

基于redis实现分布式并发锁(注解实现)说明前提, 应用服务是分布式或多服务, 而这些"多"有共同的"redis";(2017-12-04) 笑哭, 写这篇之前一直觉得应该有大神已经写好了, 但未找到. 其实redis官网已经给出了实现(百度、阿里都是用的这套): Redis分布式锁、Distributed locks with Redisjava版本的名字叫redisson, 其github:...

weixin_31974443的博客 646

GB28181 —— 3、C++编写GB28181设备端,完成注册、注销、保活心跳、响应查询目录等功能(附源码)

GB28181 —— Win10下编写GB28181设备端,完成注册、注销、保活心跳、响应查询目录等功能(附源码)

1308

使用redis实现并发锁

前言 Redis是一个使用ANSI C编写的开源、支持网络、基于内存、可选持久性的键值对存储数据库。同时也是最流行的键值对存储数据库(之一)。 由于其基于内存的特性,在使用上轻量高速,在面对并发场景时,可以基于其构建并发锁(分布式锁)。 分布式锁一般有三种实现方式: 数据库锁 基于Redis的分布式锁 基于ZooKeeper的分布式锁 实现 import redis def get_redis_client(host, port, db): redis_client = redis.Red

TracelessLe的专栏 1424

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

java redis 并发_基于redis的分布式并发锁java实现

主要概念:1、如何争锁2、锁的表达方式3、避免死锁4、死锁过期网上找了一些资料:针对redisTemplate 实现的,但是在试用过的过程中也遇到了一些坑:public interface DistributionLock {//加锁成功 返回加锁时间Long lock(String lockKey, String threadname);//解锁 需要更加加锁时间判断是否有权限void unlo...

weixin_39738380的博客 222

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

PHP基于redis实现的并发锁

在用redis做缓存时, 如果不考虑并发问题, 在缓存不存在或过期时, 会导致很多请求直接进入数据库,造成很多"意外"的负载. 所以, 需要对缓存不存在->走...

aben_sky的专栏 756

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

Springboot 使用 RedisTemplate 整合 Redis 实现并发锁以及redis工具类

代码实现 1、maven依赖pom.xml <!-- springboot 集成 redis 依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</ar...

weixin_44605704的博客 4076

php redis并发读写,PHP实现Redis单据锁以及防止并发重复写入

一、写在前面:在整个供应链系统中,会有很多种单据(采购单、入库单、到货单、运单等等),在涉及写单据数据的接口时(增删改操作),即使前端做了相关限制,还是有可能因为网络或异常操作产生并发重复调用的情况,导致对相同单据做相同的处理;为了防止这种情况对系统造成异常影响,我们通过Redis实现了一个简单的单据锁,每个请求需先获取锁才能执行业务逻辑,执行结束后才会释放锁;保证了同一单据的并发重复操作请求只有...

weixin_29503627的博客 358

java+springboot使用StringRedisTemplate实现redis的并发锁

redis的依赖先引入 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> 并发锁相关命令介绍 说到redis的并发锁就要先介绍一下这两个redis命令 先上一波中文翻译官网 http:/

奔跑的菜鸡 1498

redis并发锁 thinkphp5_php在大并发下redis锁实现

在现如今电商盛行的时期,会出现很多促销活动,最为常见的就是秒杀。在秒杀系统中最为常见的问题就是会出现超卖的情况,那么如何来杜绝超卖的情形了,在业务逻辑层面可以使用缓存以及加锁的手法来避免超卖的情形。现如今nosql已经非常流行和稳定了,在此我将通过redis和php来说明如何实现锁机制。当然我使用redis加锁并不是我的秒杀系统,而是最近做的一个项目有个用户提现,初期没有考虑到会有人恶意刷新接口,...

weixin_28871475的博客 922

Springboot 使用 Jedis、RedisTemplate 整合 Redis 实现并发锁

代码实现 1、maven依赖pom.xml <!-- redis --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data...

weixin_44605704的博客 3614

【redis】基于redis实现分布式并发锁

基于redis实现分布式并发锁(注解实现) 说明   前提, 应用服务是分布式或多服务, 而这些"多"有共同的"redis";   (2017-12-04) 笑哭, 写这篇之前一直觉得应该有大神已经写好了, 但未找到. 其实redis官网已经给出了实现(百度、阿里都是用的这套): Redis分布式锁、Distributed locks with Redis   java版本的名字叫redisson...

weixin_30788239的博客 182

redis setnx原子性_PHP实现Redis单据锁以及防止并发重复写入

一、前言:在整个供应链系统中,会有很多种单据(采购单、入库单、到货单、运单等等),在涉及写单据数据的接口时(增删改操作),即使前端做了相关限制,还是有可能因为网络或异常操作产生并发重复调用的情况,导致对相同单据做相同的处理;为了防止这种情况对系统造成异常影响,我们通过Redis实现了一个简单的单据锁,每个请求需先获取锁才能执行业务逻辑,执行结束后才会释放锁;保证了同一单据的并发重复操作请求只有一个...

weixin_39627665的博客 859

nx set 怎么实现的原子性_PHP如何正确的使用Redis的SETNX设置一个并发锁

最近有朋友问如何使用Redis的SETNX设置一个并发锁(针对的是同一个用户在同一点进行一次行为操作),他发了一段代码,我们看看问题;先来看下php 中setNx这个函数的介绍:Set the string value in argument as value of the key if the key doesn't already exist in the database.如果键在数据库中不...

weixin_42520573的博客 486
上一篇: Java中Synchronized 和ReentrantLock的用法
下一篇: Redis 内存持续飙高,小心监控命令monitor 惹的祸
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值