redis解决并发问题

用redis处理高并发是个很常见的方式,因为redis的访问效率很高(直接访问内存),一般我们会用来处理网站一瞬间的并发量。

那如果要使用redis来进行高并发问题的解决的话,应注意以下几点:

1、首先我们要先知道,我们在存储时,应使用redis的setnx方法,不应该使用set方法,因为setnx拥有原子操作命令(正确点说法应该是使用setnx,根据其属性可以保证共享资源的原子性操作),当资源锁存在不能设置值,则返回0,而当锁不存在,则设置锁,返回1; 但如果使用set方法,则会出现在高并发情况下,进程同时获取锁状态为null,同时设置,锁之间相互覆盖,但是俩进程仍在并发执行业务代码的情况。

2、为了防止死锁,我们不应直接使用jedis.setnx(lock, 1) 来进行简单的加锁,这样会导致当进程执行出现问题,锁未释放,则其他进程永远处于阻塞状态,出现死锁。 为了避免死锁,我们在加锁时带上时间戳,setnx(lock, 时间戳+超时时间),当发现锁超时了,便可以对锁进行重置,避免死锁。

接下来,实际操作!

设置锁:

//其中currentTimeMullis为当前时间、valideTime为超时时间,key为资源

//对该资源进行锁获取,如果存在锁则会返回false,不存在则设置值并返回true

boolean lock = redisService.setnx(key, currentTimeMullis+valideTime);

//如果不存在并设置了值,则可以直接返回,因为已经获取资源锁成功

//否则,则代表存在这个锁,则进行锁是否超时的判断。获取该资源的锁时间,用于判断是否超时了

String keyTime = redisService.get(key);

if((Long.valueOf(currentTimeMullis)-Long.valueOf(keyTime))>valideTime){

//该判断代表该资源锁已经超时,那么便进行资源锁的重置,也就是进行资源锁的重新设置(删除并重新设置)

//重新设置成功后也返回,因为获取锁成功,可以进行操作啦。

}

//如果以上操作都没有成功,则返回失败,代表获取锁失败,不可以进行操作。

释放锁:

当对资源处理结束后,则调用释放方法释放锁资源

(经提醒,我发现我这里少了个判断逻辑…)

//在删除前,应该先对该资源锁进行获取,判断值与此时释放锁的线程所携带的值是否相等,也就是我们上面创建时用的currentTimeMullis+valideTime。

String keyLockTime = redisService.get(key);

if(keyLockTime!=null&&keyLockTime.equals(currentTimeMullis+valideTime)){

//此时锁还由当前线程保持则释放锁

redisService.del(key);

}else{

//此时说明该资源锁被其他线程重置或释放,已不再拥有锁的释放权

//结束

}

发布了8 篇原创文章 · 获赞 5 · 访问量 1976

猜你喜欢

转载自blog.csdn.net/qq_41536778/article/details/90375267