游戏电视苹果数码历史美丽
投稿投诉
美丽时装
彩妆资讯
历史明星
乐活安卓
数码常识
驾车健康
苹果问答
网络发型
电视车载
室内电影
游戏科学
音乐整形

Springboot使用redis的setnx和getset

  为什么需要分布式锁
  在日常开发中,很多业务场景必须保证原子性。举几个例子:支付订单的操作,就不允许同一个订单,被同时支付,否则会产生错误的数据。拍卖一套房子的下单操作,商品只有一个,那只能一个人下单成功。
  如果你只有一台服务器,只运行一个Java程序,那么可以使用Java语言自身的一些锁来实现原子性。但如果我们有多台服务器,甚至不同服务器上跑的是不同的语言。那这时候,我们就需要一个跨平台、跨语言的加锁方式。redis就是其中最方便的一种。核心操作和原理
  使用redis实现并发锁,主要是靠两个redis的命令:setnx和getset。setnx的作用是,当一个key不存在的时候,给它赋值。如果key存在或赋值失败,都会返回错误。getset的作用是,先获取一个key的值,然后再给这个key赋新的值,该命令有原子性。
  那我们的设计思路就是:先用setnx初步获取锁(set当前的时间戳),如果取不到,那么有两种可能,要么是锁被其他线程持有,要么是其他线程使用完锁后,没有正确释放。所以这个时候,我们需要验证这个锁是否过期。就是把setnx的值拿出来(一个时间戳),和当前时间戳求差,看看超时没有(超时时间是自己设定的)如果锁超时了,我们需要释放它,让它能重新工作。但第二步的操作,不是原子性的。可能有多个线程发现这个锁过期了,都想释放它。这时候,就需要getset这个原子操作,来保证只有一个线程成功。核心代码ServicepublicclassRedisLockService{AutowiredprivateRedisServiceredisService;获取一个Redis分布式锁paramlockKey锁的Key,全局不可重复paramlockExpire锁超时时间,单位毫秒returnpublicbooleangetLock(StringlockKey,longlockExpire){StringredisKeyBaseCommonConfig。REDISLOCKKEYlockKey;if(!redisService。setnx(redisKey,String。valueOf(System。currentTimeMillis()))){没有拿到锁,但有可能是上一个加锁的人忘了释放锁。所以下面验证锁是否超时。StringlockStringredisService。getString(redisKey);if(lockStringnull){前面setnx时,该值还存在,现在不存在了。要么是自然过期了,要么是被别人删掉,准备重新加锁了。稳妥起见,这里返回falsereturnfalse;}longtimestampLong。parseLong(lockString);if(System。currentTimeMillis()timestamplockExpire){锁已经超时先get值,再set值。原子操作,确保不会多个线程进入后面的逻辑StringoldTimestampredisService。setGet(redisKey,String。valueOf(System。currentTimeMillis()));if(oldTimestamp!nulloldTimestamp。equals(lockString)){如果get不到值,或者get到的值不是前面取出来那个了,说明这个锁已经被别的线程占用了。第二次锁竞争成功redisService。setExpireMills(redisKey,lockExpire);returntrue;}else{returnfalse;}}else{returnfalse;}}redisService。setExpireMills(redisKey,lockExpire);returntrue;}删除锁,释放锁paramlockKeypublicvoiddelLock(StringlockKey){StringredisKeyBaseCommonConfig。REDISLOCKKEYlockKey;redisService。del(redisKey);}}
  上面的代码使用了一个RedisService的类,里面主要是简单封装了一下redis的操作,你可以替换为自己的service。代码如下:ServicepublicclassRedisService{AutowiredprivateStringRedisTemplatestringRedisTemplate;ResourceprivateRedisTemplateString,ObjectredisTemplate;publicBooleansetnx(Stringkey,Stringvalue){ValueOperationsString,StringopsstringRedisTemplate。opsForValue();returnops。setIfAbsent(key,value);}publicStringsetGet(Stringkey,Stringvalue){returnstringRedisTemplate。opsForValue()。getAndSet(key,value);}publicLongincr(Stringkey){returnstringRedisTemplate。opsForValue()。increment(key);}publicLongincr(Stringkey,longval){returnstringRedisTemplate。opsForValue()。increment(key,val);}publicLongdecr(Stringkey){returnstringRedisTemplate。opsForValue()。decrement(key);}publicLongdecr(Stringkey,longval){returnstringRedisTemplate。opsForValue()。decrement(key,val);}publicLongsetPutString(Stringkey,Stringvalue){returnstringRedisTemplate。opsForSet()。add(key,value);}publicBooleansetExist(Stringkey,Stringmember){returnstringRedisTemplate。opsForSet()。isMember(key,member);}publicSetStringsetList(Stringkey){returnstringRedisTemplate。opsForSet()。members(key);}publicLongsetSize(Stringkey){returnstringRedisTemplate。opsForSet()。size(key);}逐渐废弃没有过期时间的Redisput操作paramkeyparamvalueDeprecatedpublicvoidputString(Stringkey,Stringvalue){stringRedisTemplate。opsForValue()。set(key,value);}s为单位。paramkeyparamvalueparamtimepublicvoidputString(Stringkey,Stringvalue,longtime){stringRedisTemplate。opsForValue()。set(key,value,time,TimeUnit。SECONDS);}publicBooleanzPutString(Stringkey,Stringvalue,longtime){returnstringRedisTemplate。opsForValue()。setIfAbsent(key,value,time,TimeUnit。SECONDS);}publicvoidputString(Stringkey,Stringvalue,longtime,TimeUnitunit){stringRedisTemplate。opsForValue()。set(key,value,time,unit);}publicStringgetString(Stringkey){ValueOperationsString,StringopsstringRedisTemplate。opsForValue();returnops。get(key);}publicvoidputObject(Stringkey,Objectvalue,longtime,TimeUnitunit){redisTemplate。opsForValue()。set(key,value,time,unit);}publicObjectgetObject(Stringkey){returnredisTemplate。opsForValue()。get(key);}publicBooleanexist(Stringkey){returnstringRedisTemplate。hasKey(key);}key有效时间paramkeyreturnpublicLongexpire(Stringkey){returnstringRedisTemplate。getExpire(key,TimeUnit。SECONDS);}publicBooleanchangeExpire(Stringkey,longtime){returnstringRedisTemplate。expire(key,time,TimeUnit。SECONDS);}publicBooleandel(Stringkey){returnstringRedisTemplate。delete(key);}publicvoidhset(Stringkey,Stringfield,Stringvalue){HashOperationsString,String,StringopsstringRedisTemplate。opsForHash();ops。put(key,field,value);}publicStringhget(Stringkey,Stringfield){HashOperationsString,String,StringopsstringRedisTemplate。opsForHash();returnops。get(key,field);}publicMapString,Stringhmget(Stringkey){HashOperationsString,String,StringopsstringRedisTemplate。opsForHash();returnops。entries(key);}publicvoidhmset(Stringkey,HashMapString,Stringdata){HashOperationsString,String,StringopsstringRedisTemplate。opsForHash();ops。putAll(key,data);}publicvoidhdel(Stringkey,Stringfield){HashOperationsString,String,StringopsstringRedisTemplate。opsForHash();ops。delete(key,field);}publicvoidsadd(Stringkey,Stringvalue){stringRedisTemplate。opsForSet()。add(key,value);}publicBooleansetIsMember(Stringkey,Stringval){returnstringRedisTemplate。opsForSet()。isMember(key,val);}publicLongttl(Stringkey){returnstringRedisTemplate。getExpire(key);}publicvoidsetExpire(Stringkey,longtime){stringRedisTemplate。expire(key,time,TimeUnit。SECONDS);}publicvoidsetExpireMills(Stringkey,longtime){stringRedisTemplate。expire(key,time,TimeUnit。MILLISECONDS);}publicListStringmget(ListStringkeys){returnstringRedisTemplate。opsForValue()。multiGet(keys);}}交个朋友
  以上代码有任何疑问,可以点击右侧边栏联系作者。收费5毛交个朋友,欢迎来撩!
  版权声明:《Springboot使用redis的setnx和getset实现并发锁、分布式锁》为CoderBBB作者的原创文章,转载请附上原文出处链接及本声明。
  原文链接:https:www。coderbbb。comarticles2

大班科学下雨的前兆活动目标:1、让幼儿了解一些常见的下雨前兆的知识,知道动物也会预报天气。2、使幼儿学会观察周围事物的变化,知道天气预报的知识经验在生活加以运用。3、让幼儿了解水蒸气蒸发的现象,……小学数学优秀说课稿直线和线段一、设计理念数学教学活动必须建立在学生的认知发展水平和已有的知识经验基础之上。教学应激发学生的学习积极性,向学生提供充分从事数学活动的机会,帮助他们在自主探索和合作交流的过程中……学习雷锋奉献精神初一主题班会一、班会目的:通过班会让同学们更加了解雷锋,更加能够感受到雷锋精神的可贵,同时利用本次班会表彰上星期晨扫中表现突出,发扬互帮互助,助人为乐精神的同学,让同学们学习他们的奉……科学记数法优秀教学反思科学记数法是在学生学习了有理数的乘方知识后,安排了一节与现实世界中的数据(尤其是大数)相关的数学内容,一方面让学生感受现实宏观世界中的大数,培养学生《数学新课程标准》中的六大核……璀璨的近义词及造句许多近义词都有一个共同的特点,就是它们中间往往有一个相同的词素。以下是璀璨的近义词及造句,希望给大家带来帮助!中文发音:璀璨cucn词语解释:璀璨主要是形容光彩夺目……马价十倍阅读理解练习答案《马价十倍》人有卖骏马者,比三日立市,人莫之知。往见伯乐,曰:臣有骏马欲卖之,比三日立于市,人莫与言。愿子还而视之,去而顾之,臣请献一朝之贾。伯乐乃还而视之,去而顾……小学语文秋天的图画优秀教学设计范文教材简析:《秋天的图画》是一幅色彩的图画。全文语言优美,行文流畅,作者运用比拟的手法,在色彩的搭配上以金黄、火红为主色调,简单几笔,便把丰收的热闹情景与人们的喜悦心情描绘……对立,还是沟通说课稿范文一、说教材1、教材的地位与作用《对立,还是沟通》是北师大版品德与社会六年级下册《成长中的新问题》中的第一个主题活动。教材以三个孩子面对与家长沟通方面存在的问题……小数的大小比较教学反思《小数的大小比较》是在学生学习了整数的大小比较和小数的初步认识和意义的基础上学习的内容,本节课的教学有助于学生数感的培养,为后继小数的加减法的学习奠定了基础。本节课的教学……小学英语20分钟说课稿一、说教材:1、教材内容本节课是人教版小学英语PEP教材四年级上册Unit2Myschoolbag中的第四课时,内容包括P。BLet’slearnLet’schant两部……中班社会活动设计安全小乘客活动目标:1、知到乘坐交通工具的安全事项,掌握一些必要的自我保护的方法。2、教育幼儿做个文明、安全的小乘客。活动准备:教学挂图2幅活动过程:……给外甥女的信阅读及答案给外甥女的信你写信对我说,你愿意生在一个世纪以前伊雷娜对我肯定地说过,她宁可生得晚些,生在未来的世纪里。我认为人们在每一个时期都可以过有趣而且有用的生活。我们应该不虚度一……
马云巴黎演讲担心欧洲过多的监管将会扼杀创新北京时间5月17日晚间消息,阿里巴巴集团董事局主席马云16日在欧洲最大的科技盛会VivaTechnology上表示,希望欧洲不要再担心技术问题,因为更严格的监管可能会阻碍其创新……权健董事长登上财富封面?官方回应靠PSIT之家12月31日消息针对近期天津权健集团发布的、其创始人束昱辉登上《财富》杂志封面一事,近日《财富》发布官方声明,称《财富》杂志从未采访过天津权健集团,束昱辉也没有登上过任……浅谈DesignCompilerVerilog语言结构到门级昨天的文章中,我们了解到DesignCompiler(DC)作为Synopsys公司开发的一款用于电路综合的EDA工具,在全球数字电路市场去得了巨大的成功,它的设计初衷是将用V……超威半导体第一季度财报解读毛利润增长至41,同比增长5个百分IT之家5月6日消息不久前,AMD发布了最新的2019年财报,现在官方也发布了中文版本的财报解读,一起来看一下吧。AMD宣布2019年第一季度营业额为12。7亿美元,经营……华为P30系列真机曝光P30比P30Pro小一圈IT之家3月25日消息距离华为P30系列发布会还有一天的时间,现在数码博主搞机王腾霄曝光了华为P30和P30Pro的真机图,一起来看一下吧。从外观来看,华为P30比P30……微信解封外链实测跳转抖音等需中转站反向分享至微信仍需口令出品搜狐科技作者宋婉心编辑杨锦2021年9月17日,长达13年之久的中国互联网屏蔽高墙开始破拆。此前,工信部举行屏蔽网址链接问题行政指导会,提出9月17……幼儿防台风安全教育教案幼儿防台风安全教育教案一一、设计意图:台风天鸽侵袭了我们广东,经过长时间的暴雨侵袭,广东部分地区经历了多年未见的涝害,许多街道被大水淹没。因为台风原因,全市范围内要……流浪地球导演票房成功因观众宽容IT之家2月26日消息科幻电影《流浪地球》目前票房已破40亿元,成为今年春节档最大赢家。据香港媒体消息,《流浪地球》导演郭帆在美国曼哈顿举办影迷见面会时说,虽然影片取得很……流浪地球档期延长2个月,票价均下调10元IT之家2月22日消息据片方发行方的消息,近日的热门电影《流浪地球》已经延长档期,由原来的3月5日延长至5月5日,将延长上映2个月,同时该片对所有类型的电影票价也做了调整。……流浪地球公布中国风海报逃离混沌新生IT之家2月22日消息随着《流浪地球》电影在全球范围内的热映,《流浪地球》已经成为人们的谈资。日前,电影流浪地球官方微博公布全新的中国风海报,这份海报融合绳艺、道家卦阵、象形文……阿丽塔内地宣传海报公布,战斗天使以云做翼IT之家2月20日消息日前,电影《阿丽塔:战斗天使》公布了中国区独家海报,色调如油画质感,战斗天使阿丽塔独自站在钢铁城的废土之上,她手持大马士革刀,昂起头用利刃直指天空城撒冷,……马斯克玩起文字游戏登月第一人名字藏玄机1月4日消息,马斯克对外太空一直有深切的执念。今日,他在Twitter上贴出一张图片,暗示登月第一人尼尔阿姆斯特朗(NeilArmstrong)有此壮举并非偶然,不过他的理由可……
友情链接:易事利快生活快传网聚热点七猫云快好知快百科中准网快好找文好找中准网快软网