如何利用Redis锁解决高并发问题?
传统单点应用的线程安全问题,因为只涉及到单个应用中多线程之间的资源共享,往往通过加锁synchronized,ReentrantReadWriteLock等手段就能实现共享资源的安全;
但是现在很多大型系统,高并发的量往往较大,整个服务架构也都是设计成分布式架构,原本在单机中的共享资源转而分布在了不同的机器上,这个时候锁也应该相应的升级为分布式锁;
分布式锁有多种方式redis,zookeepper等,因为系统中本就用到了redis,就以redis为例:
分布式锁需要满足什么条件呢?
一,互斥:既然是锁,不能每个客户端都有吧,那还锁啥?
二,不能死锁:让一个客户端抱住锁,永远不释放,别的就获取不到了,那还要分布式系统干啥?
三,每个客户端的锁自己加,自己解;
redis为什么能作为分布式锁的选择呢?本身就是单进程单线程的模式,并且提供的命令具有原子性;
一般用来做分布式锁的方式有1,setnx+getset方式, 2,INCR
1,setnx+getSet方法加锁:
setnx:(set if not exists)不存在就设置,设置成功为1,已经存在,返回0;
getSet: set新key,并返回原来的value;
伪代码如下图:
场景解释如下:
第一个线程读到没有锁存在,使用lock加锁,带上时间戳,超时则释放锁,防止死锁
第二个线程读到锁存在(setnx==0),进入循环,判断锁是否在超时时间内,并使用setGet方法把最新的超时时间set进去,(防止超时时间到了,多个线程读到锁超时,都去释放的情况),
第一个线程处理完业务逻辑,并删除锁,则后面的线程可以获得锁。。。
2,INCR方法加锁
这个方法会在不存在key的时候,先初始化0,然后加1,返回1;如果key存在,则在执行就会大于1;
所以使用INCR方法加锁,伪代码如下图:
1,进行加锁操作;
2,如果锁不存在,并且加锁成功,设置过期时间;
3,如果锁已经存在,查看是否已经过了过期时间,如果过了,则重新设置。。
当然上述的分布式锁只在单机redis中安全,如果存在redis集群,可能会因为宕机,延时等问题,让锁不在唯一。需要redis官方推荐的redlock进行加锁,对此reddssion已经有良好的封装RedissionLock,建议可直接使用。
最近会持续的分享JAVA开发相关的技术,强化自己的技术,也方便大家找工作!更多的技术分享,敬请关注。。
Copyright © 广州京杭网络科技有限公司 2005-2025 版权所有 粤ICP备16019765号
广州京杭网络科技有限公司 版权所有