今天来聊 一聊自己对分布式锁的想法(java)
- 在我们的项目中,不可避免的会出现类似 秒杀 的场景,如果是单机架构,自然java提供的锁就可以搞定
- 可是当项目是集群的时候,这个实现方案就不行了,java提供的锁只是在 同一个jvm下可行;
- 我们可以采用 redis来做 分布式锁,比如 设值key 为"goods1000",值为一个随机数;
- 当请求进来的时候,查看redis中是否有"goods1000",如果没有,则写入一个随机数,如果有,则等待100毫秒再去查询;
- 写个try finally 包裹业务代码,当代码执行完成 或者 发生了异常,删除"goods1000"这个key;
这样看来,分布式的锁好像已经搞定了?不,我们再考虑一下
- 如果在执行业务代码的时候,服务器忽然宕机了,那会发生什么情况?
- 宕机问题,我们可以 为key设值过期时间10s,过了10秒之后自动删除这个key,就不怕服务器忽然宕机啦;
- 那么问题又来了,如果这个请求10秒钟都没执行完怎么办呢?设值20秒?30秒?1分钟吗?
- 这个解决方案比较复杂,我们可以在获取到锁之后,开辟一个新的线程,设值为守护线程,在线程中每过一小段(小于过期时间)时间为这个key增加存活时间,如果这个执行逻辑的程序挂了,守护线程就会终结;
这样看来,我们的问题就已经解决了吧?不对!我们再考虑一下
- 如果redis忽然挂了会出什么情况???永远都获取不到锁,这个代码就永远进不去了对吧?
- 那我们做个哨兵模式吧!!问题解决?
- 既然是高并发,那会不会出现这种情况:我们在 redis的主服务器加入这个键之后,还没有写入 其他redis服务器的时候,主服务器就挂了.那会出现啥情况?上一个请求相当于没有加锁,这个怎么解决呢?
- 这时候,我们基本是没办法解决的,只能在代码中抛出异常,让这个请求回滚了…我暂时只能想到这个解决方案,路过的大佬有更好的解决方案请指点一下,谢谢