这是我参与11月更文挑战的第8天,活动详情查看:2021最后一次更文挑战
分布式锁简介
在同一个JVM内部,大家往往采用synchronized或者Lock的方式来解决多纯种间的安全问题,但是在分布式架构下,在JVM之间,那么就需要一种更加高级的锁机制,来处理这跨JVM进程之间的纯种安全问题,解决方案就是:使用分布式锁.
Redis分布式锁分析
Redis分布式锁机制,主要借助setnx和expire两个命令完成
- setnx---当key不存在,将key设置为value,存在不做任何操作,返回0
- expire---设置key过期时间
原理分析
- key不存在时创建,并设置value和过期时间,返回值为1;成功获取到锁
- 如key存在时直接返回0,抢锁失败
- 持有锁的线程释放锁时,手动删除key;或者过期时间到,key自动删除,锁释放
加锁的问题
- setnx成功, expire失败
- 如果没有手动释放,那么这个锁永远被占用,其他线程永远也抢不到锁
解决方案
- 使用set的命令时,同时设置过期时间,命令:set lock “1234” EX 100 NX
- 使用lua脚本,将加锁的命令放在lua脚本中原子性的执行
锁过期问题
- 预估业务操作10秒,锁设置20秒,各种原因比如STW问题,业务操作执行超过20秒,业务会在无锁状态下运行,就会发生数据紊乱。
- STW:Java中Stop-The-World机制简称STW,常发生fullGC,这时Java应用程序的其他所有线程都被 挂起(除了垃圾收集器之外)
解决方案
- 乐观锁方式,增加版本号
- watch dog自动延期
Redisson分布式锁
Redisson是基于Netty的Redis客户端,不但能操作原生的Redis数据结构,还为使用者提供了一系列具有分布式特性的常用工具类,实现了分布式锁
分段锁
需求:商品秒杀要求每秒下单600个
可以使用分段锁的方式,以空间换时间。为了达到每秒600个订单,可以将锁分成600/5=120个段,反过来,每个段1秒可以操作5次,120个段,合起来每秒操作600次