【新梦想老师分享】分布式锁的正确"姿势"
admin
2023-02-20 03:20:05
0

一、概述


在如今高并发、分布式大行其道的今天,如果你还只会单体项目,那未免也太落伍了。撇开技术落伍、受人耻笑外(脸皮厚的人根本不在乎耻笑),更为现实的问题是:如果你是刚进入职场的新人,即将面临找工作,估计连面试机会都没有;如果你是已经在职的人士,不知晓分布式的各种成人姿势,那你也只有在公司任人玩弄的份。说到分布式这么重要,那今天我作为一个潜伏IT圈多年的老将,跟大家分享下分布式下的分布式锁的各种成人姿势,注意是成人哦,未成年人勿入。


二、问题现场还原—秒杀系统下单功能


1.mysql数据库有2张表:stock(库存表) ,stock_order(订单表)。


2.后台通过spring boot构建下单的业务接口(下单流程=查库存–下单–减库存)。


3.打开浏览器正常业务流程再现,刷新多少次,卖出多少份皮蛋粥,没毛病。




4.使用压测工具(ab/jemter/loaderrunner)进行压力测试ab -n 100 -c 100 http://127.0.0.1:8080/second-kill3/skill/order/123456


5.再次打开浏览器查看库存




各位看官,看到这个结果是不是有一种蛋碎一地的感觉!!! 怎么可能10000份皮蛋粥可以卖出(9989+109),如果你感觉奇怪,那说明你的技术已经out了。好了到此场景还原就到此结束。接下来给各位介绍下解决这种问题的各种姿势。


三、姿势一:synchronized


了解多线程的同学肯定会想到,并发线程安全问题,可以用jdk同步工具synchronized解决。正确的说法给大家更正下,叫做数据库丢失更新。能想到这里的我算你有点社会实践姿势,但是效果如何,请看:


1.给下单方法加synchronized,做同步。




2.继续压力测试


ab -n 100 -c 100 http://127.0.0.1:8080/second-kill3/skill/order/123456




3.synchronized姿势总结:


1)是一种解决方案。


2)synchronized无法实现细粒度的锁。


在下单的方法中加synchronized会将所有商品下单都做同步,如果另外一件商品并没有很高并发量。也会导致很请求 很慢,锁的粒度太大。


3)只适合单点情况。(而现实是高并发、分布式集群当道)


四、姿势二:分布式锁


接下来是我们的主角:分布式锁登场了。


分布式锁的三种实现方式:数据库分布式锁、redis分布式锁、zookeeper分布式锁。今天打算给大家介绍下redis分布式锁的实现方式。


1.安装redis【不知道怎么安装的,请咨询我的官方秘书度娘】


2.maven工程中导入spring-redis依赖。


org.springframework.boot


spring-boot-starter-data-redis


3.编写redisLock实现加锁与解锁


org.springframework.boot spring-boot-starter-data-redis


3.编写redisLock实现加锁与解锁


/**


加锁


@param key


@param value 当前时间+超时时间


@return


*/


public static boolean lock (String key ,String value){


//setIfAbsent=setNX 如果不存在,就设置值并返回true,否返回false


//1,加锁成功 if(redisTemplate.opsForValue().setIfAbsent(key,value)){ return true; }


//2,避免死锁(线程1加锁成功,结果在解锁前出现异常,没有解锁,导致死锁)


//2.1获取过期时间 StringcurrentValue=redisTemplate.opsForValue().get(key);


//2.2判断过期时间于当前时间的关系


if(!StringUtils.isEmpty(currentValue)


&&Long.parseLong(currentValue)


}


}


//3,加锁失败 t2结束 返回false


return false;


}


/**


解锁


@param key


@param value


*/


public void unLock(String key,String value){


try {


String currentValue = redisTemplate.opsForValue().get(key);


if(!StringUtils.isEmpty(currentValue)&¤tValue.equals(value)){


redisTemplate.opsForValue().getOperations().delete(key);


}


}catch (Exception e){


log.error("【redis分布式锁】 解锁异常");


}


}


4.下单方法加锁、解锁


@Override


public void orderProductMockDiffUser(String productId) throws Exception {


//【加锁】


long time = System.currentTimeMillis()+TIMEOUT;


if(!redisLock.lock(productId,String.valueOf(time))){


throw new Exception(“人也太多了,换个姿势在试试,~~~~”);


}


//1.查询该商品库存,为0则结束活动


int stockNum = stock.get(productId);


if(stockNum==0){


throw new Exception(“活动结束”);


}else{


//2.下单(模拟不同的用户openid 不同)


orders.put(KeyUtil.genUniqueKey(),productId);


//3.减库存


stockNum-=1;


try {


Thread.sleep(100);


}catch (Exception e){


e.printStackTrace();


}


stock.put(productId,stockNum);


}


//3.解锁


redisLock.unLock(productId,String.valueOf(time));


}


5.redis姿势总结:


1)锁的粒度小。(多个商品同时秒杀不会阻塞)


2)适合高并发,分布式集群部署。


好啦,今天的内容就到此结束了,希望对大家理解分布式锁有所帮助。


相关内容

热门资讯

石化油服获得实用新型专利授权:... 证券之星消息,根据天眼查APP数据显示石化油服(600871)新获得一项实用新型专利授权,专利名为“...
服务六大场景 机器人公园上岗 玉渊潭公园投用水面割草机器人。(刘平 摄) 天坛公园的智能巡护机器人上岗。(刘平 摄) 盛夏七月,...
力箭一号遥十五运载火箭圆满完成... 红星新闻网7月24日讯2026年7月24日07时33分,我国在东风商业航天创新试验区使用力箭一号遥十...
特朗普:美方正与伊朗谈判,不排... 当地时间7月24日,美国总统特朗普在白宫谈及对伊朗战争的“退出战略”时表示,美国有两种选择:一是继续...
小伙相亲2天后花33万闪婚,一... 极目新闻记者 邓波2025年4月,安徽安庆小伙何攀到贵州贵阳花果园相亲,并与相识两天的贵阳籍女子陆某...
丘成桐:王虹和邓煜都在MIT待... 当地时间7月23日,在美国费城举行的2026年国际数学家大会开幕式上,中国数学家邓煜、王虹获得菲尔兹...
欧盟对俄制裁列单中企,中国驻欧... 问:2026年7月23日,欧盟通过第21轮对俄罗斯制裁方案,新增列单制裁中国企业。中方对此有何评论?...
特朗普预警9月政府“停摆”,美... 一国总统公开预警自家联邦政府即将“停摆”,这种魔幻剧情又双叒叕要在华盛顿上演?当地时间7月22日,特...
视频丨2026年APEC数字和... 昨天(23日),2026年亚太经合组织数字和人工智能部长会议在四川成都举行。本届会议的主题为“数字和...
海南商发二期发射区土建完工,建... 7 月 24 日消息,海南商发今日宣布,海南商业航天发射场二期发射区建设项目土建工作完成,全面转入设...