1.前言
并发的解决方式是锁,那么分布式并发解决方式则是分布式锁。本文将从原理解析redis分布式锁是如何一步一步实现的
2.分布式锁的实现及问题解决
redis分布式锁完全建立在redis为单线程上,因为redis是单线程的,放在队列中的请求是要一条一条执行的。
redis加锁:使用setnx方法进行加锁;setnx方法设置key-value和超时时间(重点:key,value,超时时间)
1)redis的setnx的为原子操作,如果存在key则返回失败,否则写入成功,获得key锁
2)超时时间:必须设置!如果获得锁的线程由于某种原因一直不释放锁,那么这个锁就永远无法被别的线程获取了,而且还可能导致死锁的
3)超时时间导致的问题:a).如果线程1获得锁,但是任务还没执行完,锁失效(删除key-value),这时线程2就可以获得锁,会导致线程1和线程2同时操作某些资源,导致脏数据产生。解决方法是设置一个监听,当任务没有执行完时,给锁增加超时时间
b).还是上面的例子,线程1执行完任务后,会去释放锁(删除key-value),但是此时的锁已经不是线程1的锁了,是线程2的锁,这样又可能导致其他的问题。解决方式是给每个线程的锁设定唯一标志,要删也只能删自己的那个锁,这时就使用到了value这个值了。每次获取锁时,将value存在threadlocal中,当要删除锁的时候,先获取redis中的value,判断和threadlocal中的value是否一致,是则释放锁,否则不释放。但是这又会产生一个问题,获取判断释放是3步操作,非原子操作,执行中value的值随时可能改变。这时就要使用lua脚本了,将获取判断释放3个操作放在一起,再给redis执行就是原子性的了。
以上是redis实现互斥锁的原理以及解决问题的办法,如果看懂了的话,可以研究下链接里的实际使用方式:https://blog.csdn.net/wutengfei_java/article/details/100699538(转载)