分布式锁

应用场景

商品超卖问题

假设我们要做一个秒杀系统,我们通常的做法是,我们应该是提前设置好库存,然后加载到缓存中,对修改缓存中库存的方法加锁使用synchronized或者ReentrantLock或ReentrantReadWriteLocK加锁

这样在单机多线程下,没有问题,因为这个时候上述锁都在一个jvm里面,一个线程获取到锁后,其他线程就会被阻塞。但是在分布式环境下,同一服务有多个节点,假设有两个节点A、B,当并发请求进来,A节点内a1线程先获得锁,A节点内其他线程会被阻塞,但是B节点是一个单独jvm,B节点内的线程还是能有b1线程获取到锁,b2,、b3线程会被阻塞。这时修改库存的方法就被两个节点内的线程分别同时获取到锁,然后修改数据。

这种情况下,我们就需要用到分布式锁,在修改缓存中库存方法内获得分布式锁,出来完成后在释放掉分布式锁

简单来说就是分布式锁是java本地锁的升级版本,如果项目内有用到java锁的场景,那么多节点部署服务的时候,都要考虑使用分布式锁

分布式锁特性

必须支持的特性:

1,互斥性:只能被一个客户端的一个线程持有

2,锁超时:支持超时,防止持有锁的客户端,还没有释放锁时,宕机了,造成死锁

3,同客户端加解锁:加锁和解锁必须是同一个客户端,客户端a不能解客户端b加的锁

非必须特性:

1,可重入

2,可实现公平锁或非公平锁

解决方案

1,数据库加锁

多个节点连同一个数据库,在数据库层加锁。

优点:实现简单,不需要引入额外的jar包或技术

缺点:依赖数据库,高并发场景数据库压力大

2,redis

单节点的redis没有问题,但是存在单点故障风险

redis集群主从节点是异步同步数据,高并发下可能存在多个线程同时加锁成功或者主从节点还没有同步数据的时候主节点宕机,会造成数据不一致

加锁:使用set(final String key, final String value, final SetParams params)

key=锁名

value=加锁线程的唯一标识,主要用于解锁时判断是否加锁的线程

SetParams setParams.nx();//nx() 相当于setnx()方法,setParams.ex(expireTime);//设置过期时间 ex 单位秒 px 单位毫秒 注:上述方法是较新的jedis才有,有的使用老版本的jedis,使用的是setnx+expire实现加锁设置过期时间,这样的话,加锁和设置过期时间就不是原子操作,如果已经加锁了但还没有设置过期时间宕机了,就会造成锁永远存在

实现demo

2.1 redisson

节点:1,单redis部署认为是一个节点;2,一主N从结构认为是一个节点

redisson操作单节点redis的时候,使用RedissonLock.tryLock()方法加锁,对于一主N从结构的部署是有可能造成同时获取到锁的情况

redisson给redis集群(Cluster)加锁的时候,要先获取到每个节点的锁对象,然后getRedLock(RLock... locks)获取到级联锁,然后使用RedissonRedLock.tryLock()遍历给每个redis节点加锁,加锁成功的节点大于总结点的一半即认为加锁成功

加锁:如果指定了锁失效时间,则锁失效时间过后会自动释放;

如果没有指定锁失效时间,则默认失效时间为30s,但会启动看门狗线程,看门狗线程每10s(默认失效时间的1/3),重新设置当前锁的失效时间为30s,相当于只要当前线程没有释放锁,则看门狗会一直给锁续期

3,zookeeper

zookeeper是强一致性,适合做分布式锁,但是由于是强一致性,所以性能方面会受一定的影响

加锁:主要是利用zk的临时带序号节点,获取锁就是在zk指定目录下创建临时带序号节点,获取锁的线程判断自己创建的节点序号是否是最小的,若是最小的则表示获取到锁,若不是最小的则监听比自己节点序号小一号的节点,然后wait,等待监听的节点发生变化zk通知自己。

优点:不需要设置过期时间,但是客户端要记得解锁,即删除节点,若客户端宕机断开与zk的链接,则zk会自动删除断开链接创建的临时节点

问题:为什么不使用临时无序号节点或者都监听序号最小的节点?因为这样会导致所有等待加锁的线程全部被唤醒,导致无谓的资源浪费

实现demo

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,509评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,806评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,875评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,441评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,488评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,365评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,190评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,062评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,500评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,706评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,834评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,559评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,167评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,779评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,912评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,958评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,779评论 2 354