孤尽T31训练营12分布式锁笔记

206 阅读2分钟

这是我参与11月更文挑战的第8天,活动详情查看:2021最后一次更文挑战

分布式锁简介

在同一个JVM内部,大家往往采用synchronized或者Lock的方式来解决多纯种间的安全问题,但是在分布式架构下,在JVM之间,那么就需要一种更加高级的锁机制,来处理这跨JVM进程之间的纯种安全问题,解决方案就是:使用分布式锁.

Redis分布式锁分析

Redis分布式锁机制,主要借助setnx和expire两个命令完成

  • setnx---当key不存在,将key设置为value,存在不做任何操作,返回0
  • expire---设置key过期时间

原理分析

  1. key不存在时创建,并设置value和过期时间,返回值为1;成功获取到锁
  2. 如key存在时直接返回0,抢锁失败
  3. 持有锁的线程释放锁时,手动删除key;或者过期时间到,key自动删除,锁释放

加锁的问题

  • setnx成功, expire失败
  • 如果没有手动释放,那么这个锁永远被占用,其他线程永远也抢不到锁

解决方案

  1. 使用set的命令时,同时设置过期时间,命令:set lock “1234” EX 100 NX
  2. 使用lua脚本,将加锁的命令放在lua脚本中原子性的执行

锁过期问题

  • 预估业务操作10秒,锁设置20秒,各种原因比如STW问题,业务操作执行超过20秒,业务会在无锁状态下运行,就会发生数据紊乱。
  • STW:Java中Stop-The-World机制简称STW,常发生fullGC,这时Java应用程序的其他所有线程都被 挂起(除了垃圾收集器之外)

解决方案

  1. 乐观锁方式,增加版本号
  2. watch dog自动延期

Redisson分布式锁

Redisson是基于Netty的Redis客户端,不但能操作原生的Redis数据结构,还为使用者提供了一系列具有分布式特性的常用工具类,实现了分布式锁

分段锁

需求:商品秒杀要求每秒下单600个

可以使用分段锁的方式,以空间换时间。为了达到每秒600个订单,可以将锁分成600/5=120个段,反过来,每个段1秒可以操作5次,120个段,合起来每秒操作600次